From c02eb652e40c5c31f2a0e4002eecbc33f1fd4dbc Mon Sep 17 00:00:00 2001 From: /alex/ Date: Thu, 9 Oct 2025 07:44:19 +0200 Subject: [PATCH 01/10] getting into the mess --- .../examples/package_upgrade.rs | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 crates/iota-graphql-client/examples/package_upgrade.rs diff --git a/crates/iota-graphql-client/examples/package_upgrade.rs b/crates/iota-graphql-client/examples/package_upgrade.rs new file mode 100644 index 000000000..7656e2f1f --- /dev/null +++ b/crates/iota-graphql-client/examples/package_upgrade.rs @@ -0,0 +1,56 @@ +// Copyright (c) 2025 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use eyre::{Result, bail}; +use iota_graphql_client::Client; +use iota_transaction_builder::{MovePackageData, TransactionBuilder}; +use iota_types::ObjectId; + +#[tokio::main] +async fn main() -> Result<()> { + // let client = Client::new_devnet(); + let client = Client::new_localnet(); + + // let sender = + // "0x1ca3c38e888493f869ac35346a2041d6cf87b0b935ebba14b35a08811d8a76e4".parse()? + // ; + let sender = "0x8bcf06501122587266e2c3b808a10b8df45d92e40768a34ad6f4a76248faf79e".parse()?; + + // let package_id = + // "0xb9d617f24c84826bf660a2f4031951678cc80c264aebc4413459fb2a95ada9ba". + // parse()?; + let package_id = + "0x6a888f3955174a182aab178341ffb61a0cbe789aa74980acf90e9c5d2d06f9c6".parse()?; + // let upgrade_cap = + // "0xd64205c4b10eff4b4adb00ab6f754cda8d8e7525985a31307f7e232481dfaf6e". + // parse::()?; + let upgrade_cap = + "0x753342ea0078818f5374cc06c9cb7ac6ae478c4a5dc5f907513eb62b004ec77e".parse::()?; + + let mut builder = TransactionBuilder::new(sender).with_client(client.clone()); + builder.gas_budget(5_000_000); + + let data: MovePackageData = serde_json::from_str(SERIALIZED_MOVE_PACKAGE_DATA)?; + println!("#Modules = {}", data.modules.len()); + println!("#Deps = {}", data.dependencies.len()); + println!("#Digest = {:?}", data.digest); + + builder.upgrade(package_id, upgrade_cap, data); + + let tx = builder.finish().await?; + + let res = client.dry_run_tx(&tx, false).await?; + if let Some(err) = res.error { + bail!("Dry run failed: {err}"); + } + + println!("Dry run succeeded"); + + Ok(()) +} + +const SERIALIZED_MOVE_PACKAGE_DATA_OLD: &str = r#"{"modules":["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CQACBggNBggGAggHCxABBQEIAQMHCwgCCQAJAQkACQECCxABBQgNAgsQAQUHCA0BBwkBAQgDAgcIDQsQAQUBCAUBCAQBBwgNAgcIDQMCBwgOAwIHCA0LCgIIEQgRAggMBggNAggNCA4ECAwCBggGBwgJAQMCCAcDBgsQAQgMBggACxABBQsQAQgNBggNCA0CBQYLCAIFCAwIQWRtaW5DYXAFQ2xvY2sCSUQETmFtZQpOYW1lUmVjb3JkFE5hbWVSZWNvcmRBZGRlZEV2ZW50Fk5hbWVSZWNvcmRSZW1vdmVkRXZlbnQQTmFtZVJlZ2lzdHJhdGlvbgZPcHRpb24IUmVnaXN0cnkVUmV2ZXJzZUxvb2t1cFNldEV2ZW50F1JldmVyc2VMb29rdXBVbnNldEV2ZW50BlN0cmluZxNTdWJuYW1lUmVnaXN0cmF0aW9uBVRhYmxlFVRhcmdldEFkZHJlc3NTZXRFdmVudAlUeENvbnRleHQGVmVjTWFwA2FkZA9hZGRfbGVhZl9yZWNvcmQKYWRkX3JlY29yZCBhZGRfcmVjb3JkX2lnbm9yaW5nX2dyYWNlX3BlcmlvZAVhZG1pbhhhc3NlcnRfbmZ0X2lzX2F1dGhvcml6ZWQGYm9ycm93CmJvcnJvd19tdXQEYnVybhhidXJuX3JlZ2lzdHJhdGlvbl9vYmplY3QTYnVybl9zdWJuYW1lX29iamVjdAVjbG9jawhjb250YWlucwRkYXRhD2RlZmF1bHRfYWRkcmVzcwxkZWZhdWx0X25hbWUMZGVzdHJveV9zb21lBGVtaXQFZXZlbnQXZXhwaXJhdGlvbl90aW1lc3RhbXBfbXMHZXh0cmFjdBNmb3JjZV9yZW1vdmVfcmVjb3JkCGdldF9kYXRhIGhhbmRsZV9pbnZhbGlkYXRlX3JldmVyc2VfcmVjb3JkC2hhc19leHBpcmVkHWhhc19leHBpcmVkX3Bhc3RfZ3JhY2VfcGVyaW9kCmhhc19yZWNvcmQCaWQTaW50ZXJuYWxfYWRkX3JlY29yZAppb3RhX25hbWVzDmlzX2xlYWZfcmVjb3JkB2lzX25vbmUHaXNfc29tZQppc19zdWJuYW1lBmxvb2t1cARuYW1lC25hbWVfcmVjb3JkEW5hbWVfcmVnaXN0cmF0aW9uA25ldwhuZXdfbGVhZgZuZnRfaWQEbm9uZQZvYmplY3QGb3B0aW9uBnBhcmVudAhyZWdpc3RyeQZyZW1vdmUscmVtb3ZlX2V4aXN0aW5nX3JlY29yZF9pZl9leGlzdHNfYW5kX2V4cGlyZWQScmVtb3ZlX2xlYWZfcmVjb3JkDnJldmVyc2VfbG9va3VwEHJldmVyc2VfcmVnaXN0cnkIc2V0X2RhdGEbc2V0X2V4cGlyYXRpb25fdGltZXN0YW1wX21zEnNldF9yZXZlcnNlX2xvb2t1cBJzZXRfdGFyZ2V0X2FkZHJlc3MEc29tZQZzdHJpbmcUc3VibmFtZV9yZWdpc3RyYXRpb24FdGFibGUOdGFyZ2V0X2FkZHJlc3MKdHhfY29udGV4dBR1bnNldF9yZXZlcnNlX2xvb2t1cAd2ZWNfbWFwDHdyYXBfc3VibmFtZbnWF/JMhIJr9mCi9AMZUWeMyAwmSuvEQTRZ+yqVram6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgoCDAtFTmZ0RXhwaXJlZAoCJCNUaGUgYE5hbWVSZWdpc3RyYXRpb25gIGhhcyBleHBpcmVkLgoCEhFFUmVjb3JkTm90RXhwaXJlZAoCHBtSZWNvcmQgaGFzIG5vdCB5ZXQgZXhwaXJlZC4KAgwLRUlkTWlzbWF0Y2gKAjg3VGhlIGBOYW1lUmVnaXN0cmF0aW9uYCBkb2VzIG5vdCBtYXRjaCB0aGUgYE5hbWVSZWNvcmRgLgoCDw5FUmVjb3JkRXhwaXJlZAoCHh1UaGUgYE5hbWVSZWNvcmRgIGhhcyBleHBpcmVkLgoCEA9FUmVjb3JkTWlzbWF0Y2gKAjs6VGhlIHJldmVyc2UgbG9va3VwIHJlY29yZCBkb2VzIG5vdCBtYXRjaCB0aGUgYE5hbWVSZWNvcmRgLgoCDg1FVGFyZ2V0Tm90U2V0CgJBQFRyeWluZyB0byBhZGQgYSByZXZlcnNlIGxvb2t1cCByZWNvcmQgd2hpbGUgdGhlIHRhcmdldCBpcyBlbXB0eS4KAg8ORU5vbkxlYWZSZWNvcmQKAk5NVHJ5aW5nIHRvIHJlbW92ZSBvciBvcGVyYXRlIG9uIGEgbm9uLWxlYWYgcmVjb3JkIGFzIGlmIGl0IHdlcmUg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YWxhbmNlBUNsb2NrBENvaW4KQ29yZUNvbmZpZwlJb3RhTmFtZXMETmFtZQpOYW1lUmVjb3JkEE5hbWVSZWdpc3RyYXRpb24GT3B0aW9uDVBheW1lbnRJbnRlbnQNUHJpY2luZ0NvbmZpZwdSZWNlaXB0DFJlZ2lzdHJhdGlvbghSZWdpc3RyeQdSZW5ld2FsDVJlbmV3YWxDb25maWcLUmVxdWVzdERhdGEGU3RyaW5nEFRyYW5zYWN0aW9uRXZlbnQJVHhDb250ZXh0CFR5cGVOYW1lBlZlY01hcAphZGRfcmVjb3JkA2FwcBRhc3NlcnRfaXNfYXV0aG9yaXplZBhhc3NlcnRfaXNfdmFsaWRfZm9yX3NhbGUQYXV0aF9hZGRfYmFsYW5jZQdiYWxhbmNlC2Jhc2VfYW1vdW50D2Jhc2VfYW1vdW50X211dBxjYWxjdWxhdGVfYmFzZV9wcmljZV9vZl9uYW1lHmNhbGN1bGF0ZV90b3RhbF9hZnRlcl9kaXNjb3VudAVjbG9jawRjb2luBmNvbmZpZwljb25zdGFudHMLY29yZV9jb25maWcIY3VycmVuY3kPY3VycmVuY3lfYW1vdW50DGRlc3Ryb3lfc29tZQRlbWl0BWVtcHR5BWV2ZW50F2V4cGlyYXRpb25fdGltZXN0YW1wX21zEGZpbmFsaXplX3BheW1lbnQDZ2V0CmdldF9jb25maWcdaGFzX2V4cGlyZWRfcGFzdF9ncmFjZV9wZXJpb2QRaW5pdF9yZWdpc3RyYXRpb24MaW5pdF9yZW5ld2FsDGludG9fYmFsYW5jZQppb3RhX25hbWVzCmlzX3JlbmV3YWwHaXNfc29tZQppc19zdWJuYW1lBmxvb2t1cAltYXhfeWVhcnMIbWV0YWRhdGEMbWV0YWRhdGFfbXV0BG5hbWULbmFtZV9yZWNvcmQRbmFtZV9yZWdpc3RyYXRpb24DbmV3Bm9wdGlvbgdwYXltZW50EHBheW1lbnRzX3ZlcnNpb24QcGtnX3JlZ2lzdHJ5X211dARwb3MwDnByaWNpbmdfY29uZmlnCHJlZ2lzdGVyCHJlZ2lzdHJ5BXJlbmV3E3JlcXVlc3RfYmFzZV9hbW91bnQMcmVxdWVzdF9kYXRhEHJlcXVlc3RfZGF0YV9tdXQUcmVxdWVzdF9kYXRhX3ZlcnNpb24bc2V0X2V4cGlyYXRpb25fdGltZXN0YW1wX21zBnN0cmluZxF0YXJnZXRfZXhwaXJhdGlvbgx0aW1lc3RhbXBfbXMIdG9fZXZlbnQKdHhfY29udGV4dAl0eXBlX25hbWUKdmFsaWRhdGlvbgV2YWx1ZQd2ZWNfbWFwB3ZlcnNpb24HeWVhcl9tcwV5ZWFyc7nWF/JMhIJr9mCi9AMZUWeMyAwmSuvEQTRZ+yqVram6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgoCEhFFTm90U3VwcG9ydGVkVHlwZQoCRkVSZW5ld2FsIGlzIG5vdCBzdXBwb3J0ZWQgaW4gdGhpcyBmdW5jdGlvbiBjYWxsLiBDYWxsIGByZW5ld2AgaW5zdGVhZC4KAhAPRVJlY29yZE5vdEZvdW5kCgJaWVRyaWVkIHRvIHJlbmV3IGEgbmFtZSB0aGF0IGRvZXMgbm90IGV4aXN0IGluIHRoZSByZWdpc3RyeSAoaGFzIGV4cGlyZWQgKyBoYXMgYmVlbiBidXJuZWQpCgIPDkVSZWNvcmRFeHBpcmVkCgI0M1RyaWVkIHRvIHJlbmV3IGFuIGV4cGlyZWQgbmFtZSAocG9zdCBncmFjZSBwZXJpb2QpLgoCFRRFUmVjZWlwdE5hbWVNaXNtYXRjaAoCNTRUaGUgcmVjZWlwdCBuYW1lIGRvZXMgbm90IG1hdGNoIHRoZSBuYW1lIG9mIHRoZSBORlQuCgIREEVWZXJzaW9uTWlzbWF0Y2gKAlVUVmVyc2lvbiBtaXNtYXRjaC4gVGhlIHBheW1lbnQgaW50ZW50IGlzIG5vdCBvZiB0aGUgY29ycmVjdCB2ZXJzaW9uIGZvciB0aGlzIHBhY2thZ2UuCgIUE0VDYW5ub3RSZW5ld1N1Ym5hbWUKAjEwQ2Fubm90IHJlbmV3IGEgc3VibmFtZSB1c2luZyB0aGUgcGF5bWVudCBzeXN0ZW0uCgIWFUVDYW5ub3RFeGNlZWRNYXhZZWFycwoCKypDYW5ub3QgZXhjZWVkIHRoZSBtYXhpbXVtIG51bWJlciBvZiB5ZWFycy4AAgVWAjsIC1gCHAM5CwgCCBIIEgICCRcIEzsIC1gCSwIcAzkLCAIIEggSNAElCBMmAwABAAAXNQ4ADgM4ADgBOAILAQsCCwM4AzgECwAMBg4GDAUKBVYACwVRAAELBlAADAcOBxAAFA4HEAEUDgcQAhROAQwEBTMLBVECAQsGUAIMCA4IEAAUDggQARQOCBACFE4DDAQLBAIBAAIBECIBAQAAHx4LAREeDAUKAC44BQoALg4FEScLAC44BgoFESIMBgsFDAILBgwDOAcMBDEBCwIxAQsDCwQSAE4AAgACAQAAKjILAREhDAcOBxEdIAQIBQwLAAEGCwAKAJ8A/8AnCgIKAC44BREXJQQUBRgLAAEGDQAMAKAA/8AnCwAuOAgRIwoHESIMCAsHDAMKAgwECwgLAjQYDAU4BwwGMQELAwsECwULBhIATgICAAMBAAAxRwoBLjgFDAgLAAwFDgUMBAoEVgALBFEBAQEBCwVQAQwGDAcMCQsHDAoLBgoIERghBBwFOgsBAQsDAQsIAQsCAQYJAAgAvAD/wCcLAQELAwELCAELAgELBFEDAQEBCwVQAwEBAQYBAAAAwQD/wCcLCAoBLg4JEScLATgJCwkLCgsCCwMRJAIBAQIBCiYEAQAANm0LAAwGDgYMBQoFVgALAgELAQELAwELBVEBAQEBCwZQAQEBAQYBAAAA7wD/wCcLBVEDAQEBCwZQAwwHDAgMCwsIDA8LBwwOCgEuOAUMCQoJERcMCgsOCwkRGCEEMwU7CwIBCwEBCwMBBgkACADUAP/AJwoCLhEhCgshBEIFSgsCAQsBAQsDAQYHAAYA1QD/wCcLATgJDAwKDC4KCwoDCw8REAwNCg0LAxERCwoxARY0ERYYFiUEYQVnCwwBCwIBBg0ADADlAP/AJwsMCwILCwsNESYCAQECAQYYBQEAADkVCwAMAwoDDAIKAlYACwJRAAELA1EADAEFEwsCUQIBCwNRAgwBCwECAQACAQYNBgEAADoYCwE4CgsADAUKBS4MBAoEVgALBFEAAQsFUgAMAwUWCwRRAgELBVICDAMLAwIBAAIBCRAHAQAACAMLABADAgAIAQAACAMLAA8DAgAJAQAACAQLABEFEQsCAAoBAAAIBAsAEAEUAgALAQAACAQLABAEFAIADAEAAAgDCwAPBAIADQEAAAgDCwAQAAIADgEAADsRCwAQBBQMAwoDNQsBNRgyZAAAAAAAAAAAAAAAAAAAABo0DAILAwsCFwIADwAAADwpCgARBQwECwAMAwoDVgALA1EAAQkMAgUSCwNRAgEIDAILAgwFOAsKBBAAFAoEEAEUCgQQAhQKBBAEFAsEEAMUCwU4DAsBEgECAQACAQcNEAAAAD4fCwALARElDAUOBTgNBAgFDAsCAQYDAAIAPQH/wCcLBTgODAQOBAsCESAgBBUFFwYFAAQAQwH/wCcOBBEfCwM0ERYYFgIAAAEAAgAAAAQAAwECAgwBQwgADgFDCAADAgIMAzsIC1gCVgIOAzsIC1gCVgIAAAEAAAEBAQA="],"dependencies":["0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000001"],"digest":[58,97,194,221,249,209,230,133,181,214,220,184,122,231,179,254,41,250,109,198,137,213,117,151,245,178,83,124,217,172,110,232]}"#; + +const SERIALIZED_MOVE_PACKAGE_DATA: &str = r#" +{"modules":["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CQACBggNBggGAggHCxABBQEIAQMHCwgCCQAJAQkACQECCxABBQgNAgsQAQUHCA0BBwkBAQgDAgcIDQsQAQUBCAUBCAQBBwgNAgcIDQMCBwgOAwIHCA0LCgIIEQgRAggMBggNAggNCA4ECAwCBggGBwgJAQMCCAcDBgsQAQgMBggACxABBQsQAQgNBggNCA0CBQYLCAIFCAwIQWRtaW5DYXAFQ2xvY2sCSUQETmFtZQpOYW1lUmVjb3JkFE5hbWVSZWNvcmRBZGRlZEV2ZW50Fk5hbWVSZWNvcmRSZW1vdmVkRXZlbnQQTmFtZVJlZ2lzdHJhdGlvbgZPcHRpb24IUmVnaXN0cnkVUmV2ZXJzZUxvb2t1cFNldEV2ZW50F1JldmVyc2VMb29rdXBVbnNldEV2ZW50BlN0cmluZxNTdWJuYW1lUmVnaXN0cmF0aW9uBVRhYmxlFVRhcmdldEFkZHJlc3NTZXRFdmVudAlUeENvbnRleHQGVmVjTWFwA2FkZA9hZGRfbGVhZl9yZWNvcmQKYWRkX3JlY29yZCBhZGRfcmVjb3JkX2lnbm9yaW5nX2dyYWNlX3BlcmlvZAVhZG1pbhhhc3NlcnRfbmZ0X2lzX2F1dGhvcml6ZWQGYm9ycm93CmJvcnJvd19tdXQEYnVybhhidXJuX3JlZ2lzdHJhdGlvbl9vYmplY3QTYnVybl9zdWJuYW1lX29iamVjdAVjbG9jawhjb250YWlucwRkYXRhD2RlZmF1bHRfYWRkcmVzcwxkZWZhdWx0X25hbWUMZGVzdHJveV9zb21lBGVtaXQFZXZlbnQXZXhwaXJhdGlvbl90aW1lc3RhbXBfbXMHZXh0cmFjdBNmb3JjZV9yZW1vdmVfcmVjb3JkCGdldF9kYXRhIGhhbmRsZV9pbnZhbGlkYXRlX3JldmVyc2VfcmVjb3JkC2hhc19leHBpcmVkHWhhc19leHBpcmVkX3Bhc3RfZ3JhY2VfcGVyaW9kCmhhc19yZWNvcmQCaWQTaW50ZXJuYWxfYWRkX3JlY29yZAppb3RhX25hbWVzDmlzX2xlYWZfcmVjb3JkB2lzX25vbmUHaXNfc29tZQppc19zdWJuYW1lBmxvb2t1cARuYW1lC25hbWVfcmVjb3JkEW5hbWVfcmVnaXN0cmF0aW9uA25ldwhuZXdfbGVhZgZuZnRfaWQEbm9uZQZvYmplY3QGb3B0aW9uBnBhcmVudAhyZWdpc3RyeQZyZW1vdmUscmVtb3ZlX2V4aXN0aW5nX3JlY29yZF9pZl9leGlzdHNfYW5kX2V4cGlyZWQScmVtb3ZlX2xlYWZfcmVjb3JkDnJldmVyc2VfbG9va3VwEHJldmVyc2VfcmVnaXN0cnkIc2V0X2RhdGEbc2V0X2V4cGlyYXRpb25fdGltZXN0YW1wX21zEnNldF9yZXZlcnNlX2xvb2t1cBJzZXRfdGFyZ2V0X2FkZHJlc3MEc29tZQZzdHJpbmcUc3VibmFtZV9yZWdpc3RyYXRpb24FdGFibGUOdGFyZ2V0X2FkZHJlc3MKdHhfY29udGV4dBR1bnNldF9yZXZlcnNlX2xvb2t1cAd2ZWNfbWFwDHdyYXBfc3VibmFtZWqIjzlVF0oYKqsXg0H/thoMvniap0mArPkOnF0tBvnGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgoCDAtFTmZ0RXhwaXJlZAoCJCNUaGUgYE5hbWVSZWdpc3RyYXRpb25gIGhhcyBleHBpcmVkLgoCEhFFUmVjb3JkTm90RXhwaXJlZAoCHBtSZWNvcmQgaGFzIG5vdCB5ZXQgZXhwaXJlZC4KAgwLRUlkTWlzbWF0Y2gKAjg3VGhlIGBOYW1lUmVnaXN0cmF0aW9uYCBkb2VzIG5vdCBtYXRjaCB0aGUgYE5hbWVSZWNvcmRgLgoCDw5FUmVjb3JkRXhwaXJlZAoCHh1UaGUgYE5hbWVSZWNvcmRgIGhhcyBleHBpcmVkLgoCEA9FUmVjb3JkTWlzbWF0Y2gKAjs6VGhlIHJldmVyc2UgbG9va3VwIHJlY29yZCBkb2VzIG5vdCBtYXRjaCB0aGUgYE5hbWVSZWNvcmRgLgoCDg1FVGFyZ2V0Tm90U2V0CgJBQFRyeWluZyB0byBhZGQgYSByZXZlcnNlIGxvb2t1cCByZWNvcmQgd2hpbGUgdGhlIHRhcmdldCBpcyBlbXB0eS4KAg8ORU5vbkxlYWZSZWNvcmQKAk5NVHJ5aW5nIHRvIHJlbW92ZSBvciBvcGVyYXRlIG9uIGEgbm9uLWxlYWYgcmVjb3JkIGFzIGlmIGl0IHdlcmUg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AQgMAQYLEQEJAAELEQEJAAIGCAwGCAUBBggMB0JhbGFuY2UFQ2xvY2sEQ29pbgpDb3JlQ29uZmlnCUlvdGFOYW1lcwROYW1lCk5hbWVSZWNvcmQQTmFtZVJlZ2lzdHJhdGlvbgZPcHRpb24NUGF5bWVudEludGVudA1QcmljaW5nQ29uZmlnB1JlY2VpcHQMUmVnaXN0cmF0aW9uCFJlZ2lzdHJ5B1JlbmV3YWwNUmVuZXdhbENvbmZpZwtSZXF1ZXN0RGF0YQZTdHJpbmcQVHJhbnNhY3Rpb25FdmVudAlUeENvbnRleHQIVHlwZU5hbWUGVmVjTWFwCmFkZF9yZWNvcmQDYXBwFGFzc2VydF9pc19hdXRob3JpemVkGGFzc2VydF9pc192YWxpZF9mb3Jfc2FsZRBhdXRoX2FkZF9iYWxhbmNlB2JhbGFuY2ULYmFzZV9hbW91bnQPYmFzZV9hbW91bnRfbXV0HGNhbGN1bGF0ZV9iYXNlX3ByaWNlX29mX25hbWUeY2FsY3VsYXRlX3RvdGFsX2FmdGVyX2Rpc2NvdW50BWNsb2NrBGNvaW4GY29uZmlnCWNvbnN0YW50cwtjb3JlX2NvbmZpZwhjdXJyZW5jeQ9jdXJyZW5jeV9hbW91bnQMZGVzdHJveV9zb21lBGVtaXQFZW1wdHkFZXZlbnQXZXhwaXJhdGlvbl90aW1lc3RhbXBfbXMQZmluYWxpemVfcGF5bWVudANnZXQKZ2V0X2NvbmZpZx1oYXNfZXhwaXJlZF9wYXN0X2dyYWNlX3BlcmlvZBFpbml0X3JlZ2lzdHJhdGlvbhxpbml0X3JlZ2lzdHJhdGlvbl93aXRoX3llYXJzDGluaXRfcmVuZXdhbAxpbnRvX2JhbGFuY2UKaW90YV9uYW1lcwppc19yZW5ld2FsB2lzX3NvbWUKaXNfc3VibmFtZQZsb29rdXAJbWF4X3llYXJzCG1ldGFkYXRhDG1ldGFkYXRhX211dARuYW1lC25hbWVfcmVjb3JkEW5hbWVfcmVnaXN0cmF0aW9uA25ldwZvcHRpb24HcGF5bWVudBBwYXltZW50c192ZXJzaW9uEHBrZ19yZWdpc3RyeV9tdXQEcG9zMA5wcmljaW5nX2NvbmZpZwhyZWdpc3RlcghyZWdpc3RyeQVyZW5ldxNyZXF1ZXN0X2Jhc2VfYW1vdW50DHJlcXVlc3RfZGF0YRByZXF1ZXN0X2RhdGFfbXV0FHJlcXVlc3RfZGF0YV92ZXJzaW9uG3NldF9leHBpcmF0aW9uX3RpbWVzdGFtcF9tcwZzdHJpbmcRdGFyZ2V0X2V4cGlyYXRpb24MdGltZXN0YW1wX21zCHRvX2V2ZW50CnR4X2NvbnRleHQJdHlwZV9uYW1lCnZhbGlkYXRpb24FdmFsdWUHdmVjX21hcAd2ZXJzaW9uB3llYXJfbXMFeWVhcnNqiI85VRdKGCqrF4NB/7YaDL54mqdJgKz5DpxdLQb5xgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIKAhIRRU5vdFN1cHBvcnRlZFR5cGUKAkZFUmVuZXdhbCBpcyBub3Qgc3VwcG9ydGVkIGluIHRoaXMgZnVuY3Rpb24gY2FsbC4gQ2FsbCBgcmVuZXdgIGluc3RlYWQuCgIQD0VSZWNvcmROb3RGb3VuZAoCWllUcmllZCB0byByZW5ldyBhIG5hbWUgdGhhdCBkb2VzIG5vdCBleGlzdCBpbiB0aGUgcmVnaXN0cnkgKGhhcyBleHBpcmVkICsgaGFzIGJlZW4gYnVybmVkKQoCDw5FUmVjb3JkRXhwaXJlZAoCNDNUcmllZCB0byByZW5ldyBhbiBleHBpcmVkIG5hbWUgKHBvc3QgZ3JhY2UgcGVyaW9kKS4KAhUURVJlY2VpcHROYW1lTWlzbWF0Y2gKAjU0VGhlIHJlY2VpcHQgbmFtZSBkb2VzIG5vdCBtYXRjaCB0aGUgbmFtZSBvZiB0aGUgTkZULgoCERBFVmVyc2lvbk1pc21hdGNoCgJVVFZlcnNpb24gbWlzbWF0Y2guIFRoZSBwYXltZW50IGludGVudCBpcyBub3Qgb2YgdGhlIGNvcnJlY3QgdmVyc2lvbiBmb3IgdGhpcyBwYWNrYWdlLgoCFBNFQ2Fubm90UmVuZXdTdWJuYW1lCgIxMENhbm5vdCByZW5ldyBhIHN1Ym5hbWUgdXNpbmcgdGhlIHBheW1lbnQgc3lzdGVtLgoCFhVFQ2Fubm90RXhjZWVkTWF4WWVhcnMKAisqQ2Fubm90IGV4Y2VlZCB0aGUgbWF4aW11bSBudW1iZXIgb2YgeWVhcnMuCgIVFEVZZWFyc011c3RCZVBvc2l0aXZlCgIhIFllYXJzIG11c3QgYmUgZ3JlYXRlciB0aGFuIHplcm8uAAIFVwI8CAtZAhwDOgsIAggSCBICAgkXCBM8CAtZAkwCHAM6CwgCCBIIEjUBJQgTJgMAAQAAGDUOAA4DOAA4ATgCCwELAgsDOAM4BAsADAYOBgwFCgVWAAsFUQABCwZQAAwHDgcQABQOBxABFA4HEAIUTgEMBAUzCwVRAgELBlACDAgOCBAAFA4IEAEUDggQAhROAwwECwQCAQACARAiAQEAACAeCwERHwwFCgAuOAUKAC4OBREoCwAuOAYKBREjDAYLBQwCCwYMAzgHDAQxAQsCMQELAwsEEgBOAAIAAgEAACtNCgIxACQEBQUJCwABBg8ADgCcAP/AJwoCMQEhBBELAAsBEQECCwERHwwHCgAuOAUKAC4OBxEoCgIKAC44BREYJQQjBScLAAEGDQAMAKMA/8AnCgAuOAYKBxEjDAgLAC44CBEkCgcRIwwJCwgLCQoCMQEXNBgWDAoLBwwDCwIMBAsKDAU4BwwGMQELAwsECwULBhIATgACAAMBAAAwOwsBESIMBw4HER4gBAgFDAsAAQYLAAoAwQD/wCcKAjEAJAQRBRULAAEGDwAOAMIA/8AnCgIKAC44BREYJQQdBSELAAEGDQAMAMMA/8AnCwAuOAgRJAoHESMMCAsHDAMKAgwECwgLAjQYDAU4BwwGMQELAwsECwULBhIATgICAAQBAAAzRwoBLjgFDAgLAAwFDgUMBAoEVgALBFEBAQEBCwVQAQwGDAcMCQsHDAoLBgoIERkhBBwFOgsBAQsDAQsIAQsCAQYJAAgA3wD/wCcLAQELAwELCAELAgELBFEDAQEBCwVQAwEBAQYBAAAA5AD/wCcLCAoBLg4JESgLATgJCwkLCgsCCwMRJQIBAQIBCiYFAQAAOG0LAAwGDgYMBQoFVgALAgELAQELAwELBVEBAQEBCwZQAQEBAQYBAAAAEgH/wCcLBVEDAQEBCwZQAwwHDAgMCwsIDA8LBwwOCgEuOAUMCQoJERgMCgsOCwkRGSEEMwU7CwIBCwEBCwMBBgkACAD3AP/AJwoCLhEiCgshBEIFSgsCAQsBAQsDAQYHAAYA+AD/wCcLATgJDAwKDC4KCwoDCw8REQwNCg0LAxESCwoxARY0ERcYFiUEYQVnCwwBCwIBBg0ADAAIAf/AJwsMCwILCwsNEScCAQECAQYYBgEAADsVCwAMAwoDDAIKAlYACwJRAAELA1EADAEFEwsCUQIBCwNRAgwBCwECAQACAQYNBwEAADwYCwE4CgsADAUKBS4MBAoEVgALBFEAAQsFUgAMAwUWCwRRAgELBVICDAMLAwIBAAIBCRAIAQAACQMLABADAgAJAQAACQMLAA8DAgAKAQAACQQLABEGEQwCAAsBAAAJBAsAEAEUAgAMAQAACQQLABAEFAIADQEAAAkDCwAPBAIADgEAAAkDCwAQAAIADwEAAD0RCwAQBBQMAwoDNQsBNRgyZAAAAAAAAAAAAAAAAAAAABo0DAILAwsCFwIAEAAAAD4pCgARBgwECwAMAwoDVgALA1EAAQkMAgUSCwNRAgEIDAILAgwFOAsKBBAAFAoEEAEUCgQQAhQKBBAEFAsEEAMUCwU4DAsBEgECAQACAQcNEQAAAEAfCwALAREmDAUOBTgNBAgFDAsCAQYDAAIAYwH/wCcLBTgODAQOBAsCESEgBBUFFwYFAAQAaQH/wCcOBBEgCwM0ERcYFgIAAAEAAgAAAAQAAwECAgwBRAgADgFECAADAgIMAzwIC1kCVwIOAzwIC1kCVwIAAAEAAAEBAQA="],"dependencies":["0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000001"],"digest":[131,29,1,9,120,43,123,254,72,188,71,120,87,180,130,193,154,165,189,15,178,167,55,165,100,164,50,192,230,71,158,125]} +"#; From c26aff41b1fd4fcfea71f4e6b98dc6f1a11a625a Mon Sep 17 00:00:00 2001 From: /alex/ Date: Mon, 13 Oct 2025 08:45:33 +0200 Subject: [PATCH 02/10] publish and upgrade --- .../examples/package_upgrade.rs | 56 ------ .../examples/publish_upgrade.rs | 161 ++++++++++++++++++ crates/iota-sdk-types/src/type_tag/mod.rs | 9 + .../src/publish_type.rs | 2 +- 4 files changed, 171 insertions(+), 57 deletions(-) delete mode 100644 crates/iota-graphql-client/examples/package_upgrade.rs create mode 100644 crates/iota-graphql-client/examples/publish_upgrade.rs diff --git a/crates/iota-graphql-client/examples/package_upgrade.rs b/crates/iota-graphql-client/examples/package_upgrade.rs deleted file mode 100644 index 7656e2f1f..000000000 --- a/crates/iota-graphql-client/examples/package_upgrade.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2025 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use eyre::{Result, bail}; -use iota_graphql_client::Client; -use iota_transaction_builder::{MovePackageData, TransactionBuilder}; -use iota_types::ObjectId; - -#[tokio::main] -async fn main() -> Result<()> { - // let client = Client::new_devnet(); - let client = Client::new_localnet(); - - // let sender = - // "0x1ca3c38e888493f869ac35346a2041d6cf87b0b935ebba14b35a08811d8a76e4".parse()? - // ; - let sender = "0x8bcf06501122587266e2c3b808a10b8df45d92e40768a34ad6f4a76248faf79e".parse()?; - - // let package_id = - // "0xb9d617f24c84826bf660a2f4031951678cc80c264aebc4413459fb2a95ada9ba". - // parse()?; - let package_id = - "0x6a888f3955174a182aab178341ffb61a0cbe789aa74980acf90e9c5d2d06f9c6".parse()?; - // let upgrade_cap = - // "0xd64205c4b10eff4b4adb00ab6f754cda8d8e7525985a31307f7e232481dfaf6e". - // parse::()?; - let upgrade_cap = - "0x753342ea0078818f5374cc06c9cb7ac6ae478c4a5dc5f907513eb62b004ec77e".parse::()?; - - let mut builder = TransactionBuilder::new(sender).with_client(client.clone()); - builder.gas_budget(5_000_000); - - let data: MovePackageData = serde_json::from_str(SERIALIZED_MOVE_PACKAGE_DATA)?; - println!("#Modules = {}", data.modules.len()); - println!("#Deps = {}", data.dependencies.len()); - println!("#Digest = {:?}", data.digest); - - builder.upgrade(package_id, upgrade_cap, data); - - let tx = builder.finish().await?; - - let res = client.dry_run_tx(&tx, false).await?; - if let Some(err) = res.error { - bail!("Dry run failed: {err}"); - } - - println!("Dry run succeeded"); - - Ok(()) -} - -const SERIALIZED_MOVE_PACKAGE_DATA_OLD: &str = r#"{"modules":["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CQACBggNBggGAggHCxABBQEIAQMHCwgCCQAJAQkACQECCxABBQgNAgsQAQUHCA0BBwkBAQgDAgcIDQsQAQUBCAUBCAQBBwgNAgcIDQMCBwgOAwIHCA0LCgIIEQgRAggMBggNAggNCA4ECAwCBggGBwgJAQMCCAcDBgsQAQgMBggACxABBQsQAQgNBggNCA0CBQYLCAIFCAwIQWRtaW5DYXAFQ2xvY2sCSUQETmFtZQpOYW1lUmVjb3JkFE5hbWVSZWNvcmRBZGRlZEV2ZW50Fk5hbWVSZWNvcmRSZW1vdmVkRXZlbnQQTmFtZVJlZ2lzdHJhdGlvbgZPcHRpb24IUmVnaXN0cnkVUmV2ZXJzZUxvb2t1cFNldEV2ZW50F1JldmVyc2VMb29rdXBVbnNldEV2ZW50BlN0cmluZxNTdWJuYW1lUmVnaXN0cmF0aW9uBVRhYmxlFVRhcmdldEFkZHJlc3NTZXRFdmVudAlUeENvbnRleHQGVmVjTWFwA2FkZA9hZGRfbGVhZl9yZWNvcmQKYWRkX3JlY29yZCBhZGRfcmVjb3JkX2lnbm9yaW5nX2dyYWNlX3BlcmlvZAVhZG1pbhhhc3NlcnRfbmZ0X2lzX2F1dGhvcml6ZWQGYm9ycm93CmJvcnJvd19tdXQEYnVybhhidXJuX3JlZ2lzdHJhdGlvbl9vYmplY3QTYnVybl9zdWJuYW1lX29iamVjdAVjbG9jawhjb250YWlucwRkYXRhD2RlZmF1bHRfYWRkcmVzcwxkZWZhdWx0X25hbWUMZGVzdHJveV9zb21lBGVtaXQFZXZlbnQXZXhwaXJhdGlvbl90aW1lc3RhbXBfbXMHZXh0cmFjdBNmb3JjZV9yZW1vdmVfcmVjb3JkCGdldF9kYXRhIGhhbmRsZV9pbnZhbGlkYXRlX3JldmVyc2VfcmVjb3JkC2hhc19leHBpcmVkHWhhc19leHBpcmVkX3Bhc3RfZ3JhY2VfcGVyaW9kCmhhc19yZWNvcmQCaWQTaW50ZXJuYWxfYWRkX3JlY29yZAppb3RhX25hbWVzDmlzX2xlYWZfcmVjb3JkB2lzX25vbmUHaXNfc29tZQppc19zdWJuYW1lBmxvb2t1cARuYW1lC25hbWVfcmVjb3JkEW5hbWVfcmVnaXN0cmF0aW9uA25ldwhuZXdfbGVhZgZuZnRfaWQEbm9uZQZvYmplY3QGb3B0aW9uBnBhcmVudAhyZWdpc3RyeQZyZW1vdmUscmVtb3ZlX2V4aXN0aW5nX3JlY29yZF9pZl9leGlzdHNfYW5kX2V4cGlyZWQScmVtb3ZlX2xlYWZfcmVjb3JkDnJldmVyc2VfbG9va3VwEHJldmVyc2VfcmVnaXN0cnkIc2V0X2RhdGEbc2V0X2V4cGlyYXRpb25fdGltZXN0YW1wX21zEnNldF9yZXZlcnNlX2xvb2t1cBJzZXRfdGFyZ2V0X2FkZHJlc3MEc29tZQZzdHJpbmcUc3VibmFtZV9yZWdpc3RyYXRpb24FdGFibGUOdGFyZ2V0X2FkZHJlc3MKdHhfY29udGV4dBR1bnNldF9yZXZlcnNlX2xvb2t1cAd2ZWNfbWFwDHdyYXBfc3VibmFtZbnWF/JMhIJr9mCi9AMZUWeMyAwmSuvEQTRZ+yqVram6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgoCDAtFTmZ0RXhwaXJlZAoCJCNUaGUgYE5hbWVSZWdpc3RyYXRpb25gIGhhcyBleHBpcmVkLgoCEhFFUmVjb3JkTm90RXhwaXJlZAoCHBtSZWNvcmQgaGFzIG5vdCB5ZXQgZXhwaXJlZC4KAgwLRUlkTWlzbWF0Y2gKAjg3VGhlIGBOYW1lUmVnaXN0cmF0aW9uYCBkb2VzIG5vdCBtYXRjaCB0aGUgYE5hbWVSZWNvcmRgLgoCDw5FUmVjb3JkRXhwaXJlZAoCHh1UaGUgYE5hbWVSZWNvcmRgIGhhcyBleHBpcmVkLgoCEA9FUmVjb3JkTWlzbWF0Y2gKAjs6VGhlIHJldmVyc2UgbG9va3VwIHJlY29yZCBkb2VzIG5vdCBtYXRjaCB0aGUgYE5hbWVSZWNvcmRgLgoCDg1FVGFyZ2V0Tm90U2V0CgJBQFRyeWluZyB0byBhZGQgYSByZXZlcnNlIGxvb2t1cCByZWNvcmQgd2hpbGUgdGhlIHRhcmdldCBpcyBlbXB0eS4KAg8ORU5vbkxlYWZSZWNvcmQKAk5NVHJ5aW5nIHRvIHJlbW92ZSBvciBvcGVyYXRlIG9uIGEgbm9uLWxlYWYgcmVjb3JkIGFzIGlmIGl0IHdlcmUg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YWxhbmNlBUNsb2NrBENvaW4KQ29yZUNvbmZpZwlJb3RhTmFtZXMETmFtZQpOYW1lUmVjb3JkEE5hbWVSZWdpc3RyYXRpb24GT3B0aW9uDVBheW1lbnRJbnRlbnQNUHJpY2luZ0NvbmZpZwdSZWNlaXB0DFJlZ2lzdHJhdGlvbghSZWdpc3RyeQdSZW5ld2FsDVJlbmV3YWxDb25maWcLUmVxdWVzdERhdGEGU3RyaW5nEFRyYW5zYWN0aW9uRXZlbnQJVHhDb250ZXh0CFR5cGVOYW1lBlZlY01hcAphZGRfcmVjb3JkA2FwcBRhc3NlcnRfaXNfYXV0aG9yaXplZBhhc3NlcnRfaXNfdmFsaWRfZm9yX3NhbGUQYXV0aF9hZGRfYmFsYW5jZQdiYWxhbmNlC2Jhc2VfYW1vdW50D2Jhc2VfYW1vdW50X211dBxjYWxjdWxhdGVfYmFzZV9wcmljZV9vZl9uYW1lHmNhbGN1bGF0ZV90b3RhbF9hZnRlcl9kaXNjb3VudAVjbG9jawRjb2luBmNvbmZpZwljb25zdGFudHMLY29yZV9jb25maWcIY3VycmVuY3kPY3VycmVuY3lfYW1vdW50DGRlc3Ryb3lfc29tZQRlbWl0BWVtcHR5BWV2ZW50F2V4cGlyYXRpb25fdGltZXN0YW1wX21zEGZpbmFsaXplX3BheW1lbnQDZ2V0CmdldF9jb25maWcdaGFzX2V4cGlyZWRfcGFzdF9ncmFjZV9wZXJpb2QRaW5pdF9yZWdpc3RyYXRpb24MaW5pdF9yZW5ld2FsDGludG9fYmFsYW5jZQppb3RhX25hbWVzCmlzX3JlbmV3YWwHaXNfc29tZQppc19zdWJuYW1lBmxvb2t1cAltYXhfeWVhcnMIbWV0YWRhdGEMbWV0YWRhdGFfbXV0BG5hbWULbmFtZV9yZWNvcmQRbmFtZV9yZWdpc3RyYXRpb24DbmV3Bm9wdGlvbgdwYXltZW50EHBheW1lbnRzX3ZlcnNpb24QcGtnX3JlZ2lzdHJ5X211dARwb3MwDnByaWNpbmdfY29uZmlnCHJlZ2lzdGVyCHJlZ2lzdHJ5BXJlbmV3E3JlcXVlc3RfYmFzZV9hbW91bnQMcmVxdWVzdF9kYXRhEHJlcXVlc3RfZGF0YV9tdXQUcmVxdWVzdF9kYXRhX3ZlcnNpb24bc2V0X2V4cGlyYXRpb25fdGltZXN0YW1wX21zBnN0cmluZxF0YXJnZXRfZXhwaXJhdGlvbgx0aW1lc3RhbXBfbXMIdG9fZXZlbnQKdHhfY29udGV4dAl0eXBlX25hbWUKdmFsaWRhdGlvbgV2YWx1ZQd2ZWNfbWFwB3ZlcnNpb24HeWVhcl9tcwV5ZWFyc7nWF/JMhIJr9mCi9AMZUWeMyAwmSuvEQTRZ+yqVram6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgoCEhFFTm90U3VwcG9ydGVkVHlwZQoCRkVSZW5ld2FsIGlzIG5vdCBzdXBwb3J0ZWQgaW4gdGhpcyBmdW5jdGlvbiBjYWxsLiBDYWxsIGByZW5ld2AgaW5zdGVhZC4KAhAPRVJlY29yZE5vdEZvdW5kCgJaWVRyaWVkIHRvIHJlbmV3IGEgbmFtZSB0aGF0IGRvZXMgbm90IGV4aXN0IGluIHRoZSByZWdpc3RyeSAoaGFzIGV4cGlyZWQgKyBoYXMgYmVlbiBidXJuZWQpCgIPDkVSZWNvcmRFeHBpcmVkCgI0M1RyaWVkIHRvIHJlbmV3IGFuIGV4cGlyZWQgbmFtZSAocG9zdCBncmFjZSBwZXJpb2QpLgoCFRRFUmVjZWlwdE5hbWVNaXNtYXRjaAoCNTRUaGUgcmVjZWlwdCBuYW1lIGRvZXMgbm90IG1hdGNoIHRoZSBuYW1lIG9mIHRoZSBORlQuCgIREEVWZXJzaW9uTWlzbWF0Y2gKAlVUVmVyc2lvbiBtaXNtYXRjaC4gVGhlIHBheW1lbnQgaW50ZW50IGlzIG5vdCBvZiB0aGUgY29ycmVjdCB2ZXJzaW9uIGZvciB0aGlzIHBhY2thZ2UuCgIUE0VDYW5ub3RSZW5ld1N1Ym5hbWUKAjEwQ2Fubm90IHJlbmV3IGEgc3VibmFtZSB1c2luZyB0aGUgcGF5bWVudCBzeXN0ZW0uCgIWFUVDYW5ub3RFeGNlZWRNYXhZZWFycwoCKypDYW5ub3QgZXhjZWVkIHRoZSBtYXhpbXVtIG51bWJlciBvZiB5ZWFycy4AAgVWAjsIC1gCHAM5CwgCCBIIEgICCRcIEzsIC1gCSwIcAzkLCAIIEggSNAElCBMmAwABAAAXNQ4ADgM4ADgBOAILAQsCCwM4AzgECwAMBg4GDAUKBVYACwVRAAELBlAADAcOBxAAFA4HEAEUDgcQAhROAQwEBTMLBVECAQsGUAIMCA4IEAAUDggQARQOCBACFE4DDAQLBAIBAAIBECIBAQAAHx4LAREeDAUKAC44BQoALg4FEScLAC44BgoFESIMBgsFDAILBgwDOAcMBDEBCwIxAQsDCwQSAE4AAgACAQAAKjILAREhDAcOBxEdIAQIBQwLAAEGCwAKAJ8A/8AnCgIKAC44BREXJQQUBRgLAAEGDQAMAKAA/8AnCwAuOAgRIwoHESIMCAsHDAMKAgwECwgLAjQYDAU4BwwGMQELAwsECwULBhIATgICAAMBAAAxRwoBLjgFDAgLAAwFDgUMBAoEVgALBFEBAQEBCwVQAQwGDAcMCQsHDAoLBgoIERghBBwFOgsBAQsDAQsIAQsCAQYJAAgAvAD/wCcLAQELAwELCAELAgELBFEDAQEBCwVQAwEBAQYBAAAAwQD/wCcLCAoBLg4JEScLATgJCwkLCgsCCwMRJAIBAQIBCiYEAQAANm0LAAwGDgYMBQoFVgALAgELAQELAwELBVEBAQEBCwZQAQEBAQYBAAAA7wD/wCcLBVEDAQEBCwZQAwwHDAgMCwsIDA8LBwwOCgEuOAUMCQoJERcMCgsOCwkRGCEEMwU7CwIBCwEBCwMBBgkACADUAP/AJwoCLhEhCgshBEIFSgsCAQsBAQsDAQYHAAYA1QD/wCcLATgJDAwKDC4KCwoDCw8REAwNCg0LAxERCwoxARY0ERYYFiUEYQVnCwwBCwIBBg0ADADlAP/AJwsMCwILCwsNESYCAQECAQYYBQEAADkVCwAMAwoDDAIKAlYACwJRAAELA1EADAEFEwsCUQIBCwNRAgwBCwECAQACAQYNBgEAADoYCwE4CgsADAUKBS4MBAoEVgALBFEAAQsFUgAMAwUWCwRRAgELBVICDAMLAwIBAAIBCRAHAQAACAMLABADAgAIAQAACAMLAA8DAgAJAQAACAQLABEFEQsCAAoBAAAIBAsAEAEUAgALAQAACAQLABAEFAIADAEAAAgDCwAPBAIADQEAAAgDCwAQAAIADgEAADsRCwAQBBQMAwoDNQsBNRgyZAAAAAAAAAAAAAAAAAAAABo0DAILAwsCFwIADwAAADwpCgARBQwECwAMAwoDVgALA1EAAQkMAgUSCwNRAgEIDAILAgwFOAsKBBAAFAoEEAEUCgQQAhQKBBAEFAsEEAMUCwU4DAsBEgECAQACAQcNEAAAAD4fCwALARElDAUOBTgNBAgFDAsCAQYDAAIAPQH/wCcLBTgODAQOBAsCESAgBBUFFwYFAAQAQwH/wCcOBBEfCwM0ERYYFgIAAAEAAgAAAAQAAwECAgwBQwgADgFDCAADAgIMAzsIC1gCVgIOAzsIC1gCVgIAAAEAAAEBAQA="],"dependencies":["0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000001"],"digest":[58,97,194,221,249,209,230,133,181,214,220,184,122,231,179,254,41,250,109,198,137,213,117,151,245,178,83,124,217,172,110,232]}"#; - -const SERIALIZED_MOVE_PACKAGE_DATA: &str = r#" -{"modules":["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CQACBggNBggGAggHCxABBQEIAQMHCwgCCQAJAQkACQECCxABBQgNAgsQAQUHCA0BBwkBAQgDAgcIDQsQAQUBCAUBCAQBBwgNAgcIDQMCBwgOAwIHCA0LCgIIEQgRAggMBggNAggNCA4ECAwCBggGBwgJAQMCCAcDBgsQAQgMBggACxABBQsQAQgNBggNCA0CBQYLCAIFCAwIQWRtaW5DYXAFQ2xvY2sCSUQETmFtZQpOYW1lUmVjb3JkFE5hbWVSZWNvcmRBZGRlZEV2ZW50Fk5hbWVSZWNvcmRSZW1vdmVkRXZlbnQQTmFtZVJlZ2lzdHJhdGlvbgZPcHRpb24IUmVnaXN0cnkVUmV2ZXJzZUxvb2t1cFNldEV2ZW50F1JldmVyc2VMb29rdXBVbnNldEV2ZW50BlN0cmluZxNTdWJuYW1lUmVnaXN0cmF0aW9uBVRhYmxlFVRhcmdldEFkZHJlc3NTZXRFdmVudAlUeENvbnRleHQGVmVjTWFwA2FkZA9hZGRfbGVhZl9yZWNvcmQKYWRkX3JlY29yZCBhZGRfcmVjb3JkX2lnbm9yaW5nX2dyYWNlX3BlcmlvZAVhZG1pbhhhc3NlcnRfbmZ0X2lzX2F1dGhvcml6ZWQGYm9ycm93CmJvcnJvd19tdXQEYnVybhhidXJuX3JlZ2lzdHJhdGlvbl9vYmplY3QTYnVybl9zdWJuYW1lX29iamVjdAVjbG9jawhjb250YWlucwRkYXRhD2RlZmF1bHRfYWRkcmVzcwxkZWZhdWx0X25hbWUMZGVzdHJveV9zb21lBGVtaXQFZXZlbnQXZXhwaXJhdGlvbl90aW1lc3RhbXBfbXMHZXh0cmFjdBNmb3JjZV9yZW1vdmVfcmVjb3JkCGdldF9kYXRhIGhhbmRsZV9pbnZhbGlkYXRlX3JldmVyc2VfcmVjb3JkC2hhc19leHBpcmVkHWhhc19leHBpcmVkX3Bhc3RfZ3JhY2VfcGVyaW9kCmhhc19yZWNvcmQCaWQTaW50ZXJuYWxfYWRkX3JlY29yZAppb3RhX25hbWVzDmlzX2xlYWZfcmVjb3JkB2lzX25vbmUHaXNfc29tZQppc19zdWJuYW1lBmxvb2t1cARuYW1lC25hbWVfcmVjb3JkEW5hbWVfcmVnaXN0cmF0aW9uA25ldwhuZXdfbGVhZgZuZnRfaWQEbm9uZQZvYmplY3QGb3B0aW9uBnBhcmVudAhyZWdpc3RyeQZyZW1vdmUscmVtb3ZlX2V4aXN0aW5nX3JlY29yZF9pZl9leGlzdHNfYW5kX2V4cGlyZWQScmVtb3ZlX2xlYWZfcmVjb3JkDnJldmVyc2VfbG9va3VwEHJldmVyc2VfcmVnaXN0cnkIc2V0X2RhdGEbc2V0X2V4cGlyYXRpb25fdGltZXN0YW1wX21zEnNldF9yZXZlcnNlX2xvb2t1cBJzZXRfdGFyZ2V0X2FkZHJlc3MEc29tZQZzdHJpbmcUc3VibmFtZV9yZWdpc3RyYXRpb24FdGFibGUOdGFyZ2V0X2FkZHJlc3MKdHhfY29udGV4dBR1bnNldF9yZXZlcnNlX2xvb2t1cAd2ZWNfbWFwDHdyYXBfc3VibmFtZWqIjzlVF0oYKqsXg0H/thoMvniap0mArPkOnF0tBvnGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgoCDAtFTmZ0RXhwaXJlZAoCJCNUaGUgYE5hbWVSZWdpc3RyYXRpb25gIGhhcyBleHBpcmVkLgoCEhFFUmVjb3JkTm90RXhwaXJlZAoCHBtSZWNvcmQgaGFzIG5vdCB5ZXQgZXhwaXJlZC4KAgwLRUlkTWlzbWF0Y2gKAjg3VGhlIGBOYW1lUmVnaXN0cmF0aW9uYCBkb2VzIG5vdCBtYXRjaCB0aGUgYE5hbWVSZWNvcmRgLgoCDw5FUmVjb3JkRXhwaXJlZAoCHh1UaGUgYE5hbWVSZWNvcmRgIGhhcyBleHBpcmVkLgoCEA9FUmVjb3JkTWlzbWF0Y2gKAjs6VGhlIHJldmVyc2UgbG9va3VwIHJlY29yZCBkb2VzIG5vdCBtYXRjaCB0aGUgYE5hbWVSZWNvcmRgLgoCDg1FVGFyZ2V0Tm90U2V0CgJBQFRyeWluZyB0byBhZGQgYSByZXZlcnNlIGxvb2t1cCByZWNvcmQgd2hpbGUgdGhlIHRhcmdldCBpcyBlbXB0eS4KAg8ORU5vbkxlYWZSZWNvcmQKAk5NVHJ5aW5nIHRvIHJlbW92ZSBvciBvcGVyYXRlIG9uIGEgbm9uLWxlYWYgcmVjb3JkIGFzIGlmIGl0IHdlcmUg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AQgMAQYLEQEJAAELEQEJAAIGCAwGCAUBBggMB0JhbGFuY2UFQ2xvY2sEQ29pbgpDb3JlQ29uZmlnCUlvdGFOYW1lcwROYW1lCk5hbWVSZWNvcmQQTmFtZVJlZ2lzdHJhdGlvbgZPcHRpb24NUGF5bWVudEludGVudA1QcmljaW5nQ29uZmlnB1JlY2VpcHQMUmVnaXN0cmF0aW9uCFJlZ2lzdHJ5B1JlbmV3YWwNUmVuZXdhbENvbmZpZwtSZXF1ZXN0RGF0YQZTdHJpbmcQVHJhbnNhY3Rpb25FdmVudAlUeENvbnRleHQIVHlwZU5hbWUGVmVjTWFwCmFkZF9yZWNvcmQDYXBwFGFzc2VydF9pc19hdXRob3JpemVkGGFzc2VydF9pc192YWxpZF9mb3Jfc2FsZRBhdXRoX2FkZF9iYWxhbmNlB2JhbGFuY2ULYmFzZV9hbW91bnQPYmFzZV9hbW91bnRfbXV0HGNhbGN1bGF0ZV9iYXNlX3ByaWNlX29mX25hbWUeY2FsY3VsYXRlX3RvdGFsX2FmdGVyX2Rpc2NvdW50BWNsb2NrBGNvaW4GY29uZmlnCWNvbnN0YW50cwtjb3JlX2NvbmZpZwhjdXJyZW5jeQ9jdXJyZW5jeV9hbW91bnQMZGVzdHJveV9zb21lBGVtaXQFZW1wdHkFZXZlbnQXZXhwaXJhdGlvbl90aW1lc3RhbXBfbXMQZmluYWxpemVfcGF5bWVudANnZXQKZ2V0X2NvbmZpZx1oYXNfZXhwaXJlZF9wYXN0X2dyYWNlX3BlcmlvZBFpbml0X3JlZ2lzdHJhdGlvbhxpbml0X3JlZ2lzdHJhdGlvbl93aXRoX3llYXJzDGluaXRfcmVuZXdhbAxpbnRvX2JhbGFuY2UKaW90YV9uYW1lcwppc19yZW5ld2FsB2lzX3NvbWUKaXNfc3VibmFtZQZsb29rdXAJbWF4X3llYXJzCG1ldGFkYXRhDG1ldGFkYXRhX211dARuYW1lC25hbWVfcmVjb3JkEW5hbWVfcmVnaXN0cmF0aW9uA25ldwZvcHRpb24HcGF5bWVudBBwYXltZW50c192ZXJzaW9uEHBrZ19yZWdpc3RyeV9tdXQEcG9zMA5wcmljaW5nX2NvbmZpZwhyZWdpc3RlcghyZWdpc3RyeQVyZW5ldxNyZXF1ZXN0X2Jhc2VfYW1vdW50DHJlcXVlc3RfZGF0YRByZXF1ZXN0X2RhdGFfbXV0FHJlcXVlc3RfZGF0YV92ZXJzaW9uG3NldF9leHBpcmF0aW9uX3RpbWVzdGFtcF9tcwZzdHJpbmcRdGFyZ2V0X2V4cGlyYXRpb24MdGltZXN0YW1wX21zCHRvX2V2ZW50CnR4X2NvbnRleHQJdHlwZV9uYW1lCnZhbGlkYXRpb24FdmFsdWUHdmVjX21hcAd2ZXJzaW9uB3llYXJfbXMFeWVhcnNqiI85VRdKGCqrF4NB/7YaDL54mqdJgKz5DpxdLQb5xgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIKAhIRRU5vdFN1cHBvcnRlZFR5cGUKAkZFUmVuZXdhbCBpcyBub3Qgc3VwcG9ydGVkIGluIHRoaXMgZnVuY3Rpb24gY2FsbC4gQ2FsbCBgcmVuZXdgIGluc3RlYWQuCgIQD0VSZWNvcmROb3RGb3VuZAoCWllUcmllZCB0byByZW5ldyBhIG5hbWUgdGhhdCBkb2VzIG5vdCBleGlzdCBpbiB0aGUgcmVnaXN0cnkgKGhhcyBleHBpcmVkICsgaGFzIGJlZW4gYnVybmVkKQoCDw5FUmVjb3JkRXhwaXJlZAoCNDNUcmllZCB0byByZW5ldyBhbiBleHBpcmVkIG5hbWUgKHBvc3QgZ3JhY2UgcGVyaW9kKS4KAhUURVJlY2VpcHROYW1lTWlzbWF0Y2gKAjU0VGhlIHJlY2VpcHQgbmFtZSBkb2VzIG5vdCBtYXRjaCB0aGUgbmFtZSBvZiB0aGUgTkZULgoCERBFVmVyc2lvbk1pc21hdGNoCgJVVFZlcnNpb24gbWlzbWF0Y2guIFRoZSBwYXltZW50IGludGVudCBpcyBub3Qgb2YgdGhlIGNvcnJlY3QgdmVyc2lvbiBmb3IgdGhpcyBwYWNrYWdlLgoCFBNFQ2Fubm90UmVuZXdTdWJuYW1lCgIxMENhbm5vdCByZW5ldyBhIHN1Ym5hbWUgdXNpbmcgdGhlIHBheW1lbnQgc3lzdGVtLgoCFhVFQ2Fubm90RXhjZWVkTWF4WWVhcnMKAisqQ2Fubm90IGV4Y2VlZCB0aGUgbWF4aW11bSBudW1iZXIgb2YgeWVhcnMuCgIVFEVZZWFyc011c3RCZVBvc2l0aXZlCgIhIFllYXJzIG11c3QgYmUgZ3JlYXRlciB0aGFuIHplcm8uAAIFVwI8CAtZAhwDOgsIAggSCBICAgkXCBM8CAtZAkwCHAM6CwgCCBIIEjUBJQgTJgMAAQAAGDUOAA4DOAA4ATgCCwELAgsDOAM4BAsADAYOBgwFCgVWAAsFUQABCwZQAAwHDgcQABQOBxABFA4HEAIUTgEMBAUzCwVRAgELBlACDAgOCBAAFA4IEAEUDggQAhROAwwECwQCAQACARAiAQEAACAeCwERHwwFCgAuOAUKAC4OBREoCwAuOAYKBREjDAYLBQwCCwYMAzgHDAQxAQsCMQELAwsEEgBOAAIAAgEAACtNCgIxACQEBQUJCwABBg8ADgCcAP/AJwoCMQEhBBELAAsBEQECCwERHwwHCgAuOAUKAC4OBxEoCgIKAC44BREYJQQjBScLAAEGDQAMAKMA/8AnCgAuOAYKBxEjDAgLAC44CBEkCgcRIwwJCwgLCQoCMQEXNBgWDAoLBwwDCwIMBAsKDAU4BwwGMQELAwsECwULBhIATgACAAMBAAAwOwsBESIMBw4HER4gBAgFDAsAAQYLAAoAwQD/wCcKAjEAJAQRBRULAAEGDwAOAMIA/8AnCgIKAC44BREYJQQdBSELAAEGDQAMAMMA/8AnCwAuOAgRJAoHESMMCAsHDAMKAgwECwgLAjQYDAU4BwwGMQELAwsECwULBhIATgICAAQBAAAzRwoBLjgFDAgLAAwFDgUMBAoEVgALBFEBAQEBCwVQAQwGDAcMCQsHDAoLBgoIERkhBBwFOgsBAQsDAQsIAQsCAQYJAAgA3wD/wCcLAQELAwELCAELAgELBFEDAQEBCwVQAwEBAQYBAAAA5AD/wCcLCAoBLg4JESgLATgJCwkLCgsCCwMRJQIBAQIBCiYFAQAAOG0LAAwGDgYMBQoFVgALAgELAQELAwELBVEBAQEBCwZQAQEBAQYBAAAAEgH/wCcLBVEDAQEBCwZQAwwHDAgMCwsIDA8LBwwOCgEuOAUMCQoJERgMCgsOCwkRGSEEMwU7CwIBCwEBCwMBBgkACAD3AP/AJwoCLhEiCgshBEIFSgsCAQsBAQsDAQYHAAYA+AD/wCcLATgJDAwKDC4KCwoDCw8REQwNCg0LAxESCwoxARY0ERcYFiUEYQVnCwwBCwIBBg0ADAAIAf/AJwsMCwILCwsNEScCAQECAQYYBgEAADsVCwAMAwoDDAIKAlYACwJRAAELA1EADAEFEwsCUQIBCwNRAgwBCwECAQACAQYNBwEAADwYCwE4CgsADAUKBS4MBAoEVgALBFEAAQsFUgAMAwUWCwRRAgELBVICDAMLAwIBAAIBCRAIAQAACQMLABADAgAJAQAACQMLAA8DAgAKAQAACQQLABEGEQwCAAsBAAAJBAsAEAEUAgAMAQAACQQLABAEFAIADQEAAAkDCwAPBAIADgEAAAkDCwAQAAIADwEAAD0RCwAQBBQMAwoDNQsBNRgyZAAAAAAAAAAAAAAAAAAAABo0DAILAwsCFwIAEAAAAD4pCgARBgwECwAMAwoDVgALA1EAAQkMAgUSCwNRAgEIDAILAgwFOAsKBBAAFAoEEAEUCgQQAhQKBBAEFAsEEAMUCwU4DAsBEgECAQACAQcNEQAAAEAfCwALAREmDAUOBTgNBAgFDAsCAQYDAAIAYwH/wCcLBTgODAQOBAsCESEgBBUFFwYFAAQAaQH/wCcOBBEgCwM0ERcYFgIAAAEAAgAAAAQAAwECAgwBRAgADgFECAADAgIMAzwIC1kCVwIOAzwIC1kCVwIAAAEAAAEBAQA="],"dependencies":["0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000001"],"digest":[131,29,1,9,120,43,123,254,72,188,71,120,87,180,130,193,154,165,189,15,178,167,55,165,100,164,50,192,230,71,158,125]} -"#; diff --git a/crates/iota-graphql-client/examples/publish_upgrade.rs b/crates/iota-graphql-client/examples/publish_upgrade.rs new file mode 100644 index 000000000..c4285d52a --- /dev/null +++ b/crates/iota-graphql-client/examples/publish_upgrade.rs @@ -0,0 +1,161 @@ +// Copyright (c) 2025 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +//! This example requires running a localnet. +//! ``` +//! iota start --with-faucet --with-graphql --committee-size 1 --force-regenesis +//! ``` + +use eyre::{Result, bail}; +use iota_crypto::{IotaSigner, ed25519::Ed25519PrivateKey}; +use iota_graphql_client::{Client, faucet::FaucetClient, pagination::PaginationFilter}; +use iota_transaction_builder::{MovePackageData, TransactionBuilder}; +use iota_types::{ObjectId, ObjectOut, StructTag}; +use rand::rngs::OsRng; + +#[tokio::main] +async fn main() -> Result<()> { + // Parse the compiled `first_package` example from the monorepo created with + // `iota move build --dump-bytecode-as-base64` + let data = serde_json::from_str::(SERIALIZED_FIRST_PACKAGE)?; + let Some(digest) = data.digest else { + bail!("Invalid move package"); + }; + println!("Digest={digest}"); + + // Create a random private key to derive a sender address and for signing + let private_key = Ed25519PrivateKey::generate(OsRng); + let public_key = private_key.public_key(); + let sender = public_key.derive_address(); + println!("Sender={sender}"); + + // Fund the sender address for gas payment + let faucet = FaucetClient::new_localnet(); + let Some(receipt) = faucet.request_and_wait(sender).await? else { + bail!("Failed to request coins from faucet"); + }; + println!( + "Balance={}", + receipt.sent.iter().map(|coin| coin.amount).sum::() + ); + + // Get a gas coin id + let client = Client::new_localnet(); + let gas = *client + .coins(sender, None, PaginationFilter::default()) + .await? + .data[0] + .id(); + + // Build the `publish` transaction + let mut builder = TransactionBuilder::new(sender).with_client(client.clone()); + builder.gas_budget(50_000_000); + builder.gas(gas); + builder.publish(data.clone()); + let tx = builder.finish().await?; + + // Perform a dry-run to check if everything is fine + let res = client.dry_run_tx(&tx, false).await?; + if let Some(err) = res.error { + bail!("Dry run failed: {err}"); + } + println!("Dry run succeeded"); + + // Check on the dry-run effects + let Some(effects) = res.effects else { + bail!("Missing transaction effects"); + }; + println!("Effects status (dry run): {:?}", effects.status()); + + // Sign and execute the transaction (publish the package) + let sig = private_key.sign_transaction(&tx)?; + let Some(effects) = client.execute_tx(&[sig], &tx).await? else { + bail!("Missing transaction effects"); + }; + println!("Effects status: {:?}", effects.status()); + + // Wait some time for the indexer to process the tx + tokio::time::sleep(std::time::Duration::from_secs(3)).await; + + // Resolve UpgradeCap and PackageId via the client + let mut upgrade_cap = None::; + let mut package_id = None::; + let effects_v1 = effects.as_v1(); + for changed_obj in effects_v1.changed_objects.iter() { + match changed_obj.output_state { + ObjectOut::ObjectWrite { owner, .. } => { + let object_id = changed_obj.object_id; + let Some(obj) = client.object(object_id, None).await? else { + bail!("Missing object {object_id}"); + }; + if obj.as_struct().type_ == StructTag::upgrade_cap() { + println!("UpgradeCap={object_id}"); + println!("Owner: {owner}"); + upgrade_cap.replace(object_id); + } + } + ObjectOut::PackageWrite { version, .. } => { + let pkg_id = changed_obj.object_id; + println!("PackageId={pkg_id}"); + println!("Package version: {version}"); + package_id.replace(pkg_id); + } + _ => continue, + } + } + + let Some(upgrade_cap) = upgrade_cap else { + bail!("Missing upgrade cap") + }; + let Some(package_id) = package_id else { + bail!("Missing package id") + }; + + // Build the `upgrade` transaction + let mut builder = TransactionBuilder::new(sender).with_client(client.clone()); + builder.gas_budget(50_000_000); + builder.gas(gas); + builder.upgrade(package_id, upgrade_cap, data); + let tx = builder.finish().await?; + + // Perform a dry-run to check if everything is fine + let res = client.dry_run_tx(&tx, false).await?; + if let Some(err) = res.error { + bail!("Dry run failed: {err}"); + } + println!("Dry run succeeded"); + + // Check on the dry-run effects + let Some(effects) = res.effects else { + bail!("Missing transaction effects"); + }; + println!("Effects status (dry run): {:?}", effects.status()); + + // Sign and execute the transaction (upgrade the package) + let sig = private_key.sign_transaction(&tx)?; + let Some(effects) = client.execute_tx(&[sig], &tx).await? else { + bail!("Missing transaction effects"); + }; + println!("Effects status: {:?}", effects.status()); + + // Wait some time for the indexer to process the tx + tokio::time::sleep(std::time::Duration::from_secs(3)).await; + + // Print the new package version (should now be 2) + let effects_v1 = effects.as_v1(); + for changed_obj in effects_v1.changed_objects.iter() { + match changed_obj.output_state { + ObjectOut::PackageWrite { version, .. } => { + let pkg_id = changed_obj.object_id; + println!("PackageId={pkg_id}"); + println!("Package version: {version}") + } + _ => continue, + } + } + + Ok(()) +} + +// Compiled `first_package` example +const SERIALIZED_FIRST_PACKAGE: &str = r#"{"modules":["oRzrCwYAAAAKAQAIAggUAxw+BFoGBWBBB6EBwQEI4gJACqIDGgy8A5cBDdMEBgAKAQ0BEwEUAAIMAAABCAAAAAgAAQQEAAMDAgAACAABAAAJAgMAABACAwAAEgQDAAAMBQYAAAYHAQAAEQgBAAAFCQoAAQsACwACDg8BAQwCEw8BAQgDDwwNAAoOCgYJBgEHCAQAAQYIAAEDAQYIAQQHCAEDAwcIBAEIAAQDAwUHCAQDCAAFBwgEAgMHCAQBCAIBCAMBBggEAQUBCAECCQAFBkNvbmZpZwVGb3JnZQVTd29yZAlUeENvbnRleHQDVUlEDWNyZWF0ZV9jb25maWcMY3JlYXRlX3N3b3JkAmlkBGluaXQFbWFnaWMJbXlfbW9kdWxlA25ldwluZXdfc3dvcmQGb2JqZWN0D3B1YmxpY190cmFuc2ZlcgZzZW5kZXIIc3RyZW5ndGgOc3dvcmRfdHJhbnNmZXIOc3dvcmRzX2NyZWF0ZWQIdHJhbnNmZXIKdHhfY29udGV4dAV2YWx1ZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAgMHCAMJAxADAQICBwgDEgMCAgIHCAMVAwAAAAABCQoAEQgGAAAAAAAAAAASAQsALhELOAACAQEAAAEECwAQABQCAgEAAAEECwAQARQCAwEAAAEECwAQAhQCBAEAAAEOCgAQAhQGAQAAAAAAAAAWCwAPAhULAxEICwELAhIAAgUBAAABCAsDEQgLAAsBEgALAjgBAgYBAAABBAsACwE4AgIHAQAAAQULAREICwASAgIAAQACAQEA"],"dependencies":["0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000001"],"digest":[246,127,102,77,186,19,68,12,161,181,56,248,210,0,91,211,245,251,165,152,0,197,250,135,171,37,177,240,133,76,122,124]}"#; diff --git a/crates/iota-sdk-types/src/type_tag/mod.rs b/crates/iota-sdk-types/src/type_tag/mod.rs index bfdf2c6a8..d42f4f7a3 100644 --- a/crates/iota-sdk-types/src/type_tag/mod.rs +++ b/crates/iota-sdk-types/src/type_tag/mod.rs @@ -453,6 +453,15 @@ impl StructTag { } } + pub fn upgrade_cap() -> Self { + Self { + address: Address::TWO, + module: Identifier::new("package").unwrap(), + name: Identifier::new("UpgradeCap").unwrap(), + type_params: vec![], + } + } + pub fn address(&self) -> Address { self.address } diff --git a/crates/iota-transaction-builder/src/publish_type.rs b/crates/iota-transaction-builder/src/publish_type.rs index 75638a4bf..edf544cc9 100644 --- a/crates/iota-transaction-builder/src/publish_type.rs +++ b/crates/iota-transaction-builder/src/publish_type.rs @@ -39,7 +39,7 @@ impl From for PublishType { /// Type corresponding to the output of `iota move build /// --dump-bytecode-as-base64` -#[derive(serde::Deserialize, Debug)] +#[derive(serde::Deserialize, Debug, Clone)] pub struct MovePackageData { /// The package modules as a series of bytes #[serde(deserialize_with = "bcs_from_str")] From 62f12437c337a8da0203cc60fae4ad3b6ab5bf69 Mon Sep 17 00:00:00 2001 From: /alex/ Date: Tue, 14 Oct 2025 17:29:28 +0200 Subject: [PATCH 03/10] fixes --- crates/iota-sdk/examples/publish_upgrade.rs | 83 +++++++++++++------ .../src/builder/mod.rs | 4 +- 2 files changed, 61 insertions(+), 26 deletions(-) diff --git a/crates/iota-sdk/examples/publish_upgrade.rs b/crates/iota-sdk/examples/publish_upgrade.rs index c4285d52a..32cb1f7ec 100644 --- a/crates/iota-sdk/examples/publish_upgrade.rs +++ b/crates/iota-sdk/examples/publish_upgrade.rs @@ -9,8 +9,8 @@ use eyre::{Result, bail}; use iota_crypto::{IotaSigner, ed25519::Ed25519PrivateKey}; use iota_graphql_client::{Client, faucet::FaucetClient, pagination::PaginationFilter}; -use iota_transaction_builder::{MovePackageData, TransactionBuilder}; -use iota_types::{ObjectId, ObjectOut, StructTag}; +use iota_transaction_builder::{MovePackageData, TransactionBuilder, res}; +use iota_types::{Address, Digest, Input, ObjectId, ObjectOut, StructTag}; use rand::rngs::OsRng; #[tokio::main] @@ -18,10 +18,10 @@ async fn main() -> Result<()> { // Parse the compiled `first_package` example from the monorepo created with // `iota move build --dump-bytecode-as-base64` let data = serde_json::from_str::(SERIALIZED_FIRST_PACKAGE)?; - let Some(digest) = data.digest else { - bail!("Invalid move package"); + let Some(compiled_package_digest) = data.digest else { + bail!("Missing compiled package digest"); }; - println!("Digest={digest}"); + println!("Compiled Package Digest={compiled_package_digest}"); // Create a random private key to derive a sender address and for signing let private_key = Ed25519PrivateKey::generate(OsRng); @@ -49,20 +49,26 @@ async fn main() -> Result<()> { // Build the `publish` transaction let mut builder = TransactionBuilder::new(sender).with_client(client.clone()); - builder.gas_budget(50_000_000); - builder.gas(gas); - builder.publish(data.clone()); + builder + .gas_budget(50_000_000) + .gas(gas) + .publish(data.clone()) + .name("publish"); + + // Transfer the `UpgradeCap` to the `sender` + builder.transfer_objects(sender, [res("publish")]); + let tx = builder.finish().await?; // Perform a dry-run to check if everything is fine - let res = client.dry_run_tx(&tx, false).await?; - if let Some(err) = res.error { + let result = client.dry_run_tx(&tx, false).await?; + if let Some(err) = result.error { bail!("Dry run failed: {err}"); } println!("Dry run succeeded"); // Check on the dry-run effects - let Some(effects) = res.effects else { + let Some(effects) = result.effects else { bail!("Missing transaction effects"); }; println!("Effects status (dry run): {:?}", effects.status()); @@ -80,10 +86,12 @@ async fn main() -> Result<()> { // Resolve UpgradeCap and PackageId via the client let mut upgrade_cap = None::; let mut package_id = None::; - let effects_v1 = effects.as_v1(); - for changed_obj in effects_v1.changed_objects.iter() { + let mut package_digest = None::; + let mut upgrade_cap_digest = None::; + + for changed_obj in effects.as_v1().changed_objects.iter() { match changed_obj.output_state { - ObjectOut::ObjectWrite { owner, .. } => { + ObjectOut::ObjectWrite { digest, owner } => { let object_id = changed_obj.object_id; let Some(obj) = client.object(object_id, None).await? else { bail!("Missing object {object_id}"); @@ -92,30 +100,58 @@ async fn main() -> Result<()> { println!("UpgradeCap={object_id}"); println!("Owner: {owner}"); upgrade_cap.replace(object_id); + upgrade_cap_digest.replace(digest); } } - ObjectOut::PackageWrite { version, .. } => { + ObjectOut::PackageWrite { version, digest } => { let pkg_id = changed_obj.object_id; println!("PackageId={pkg_id}"); println!("Package version: {version}"); + println!("Package digest: {digest}"); package_id.replace(pkg_id); + package_digest.replace(digest); } _ => continue, } } - let Some(upgrade_cap) = upgrade_cap else { - bail!("Missing upgrade cap") + let Some(upgrade_cap_id) = upgrade_cap else { + bail!("Missing upgrade cap"); }; let Some(package_id) = package_id else { - bail!("Missing package id") + bail!("Missing package id"); + }; + // let Some(package_digest) = package_digest else { + // bail!("Missing package digest"); + // }; + // let Some(upgrade_cap_digest) = upgrade_cap_digest else { + // bail!("Missing upgrade cap digest"); + // }; + + let Some(obj_ref) = client + .object(upgrade_cap_id, None) + .await? + .map(|obj| obj.object_ref()) + else { + bail!("Missing object"); }; - // Build the `upgrade` transaction + // Make a `move_call` to create the `UpgradeTicket` let mut builder = TransactionBuilder::new(sender).with_client(client.clone()); - builder.gas_budget(50_000_000); - builder.gas(gas); - builder.upgrade(package_id, upgrade_cap, data); + + let upgrade_arg = builder.input(Input::ImmutableOrOwned(obj_ref)); + let policy_arg = builder.pure(255); + let digest_arg = builder.pure(compiled_package_digest); + + // Build the `upgrade` transaction + builder + .gas_budget(50_000_000) + .gas(gas) + .move_call(Address::TWO, "package", "authorize_upgrade") + .arguments([upgrade_arg, policy_arg, digest_arg]) + .name("upgrade_ticket"); + + builder.upgrade(package_id, res("upgrade_ticket"), data); let tx = builder.finish().await?; // Perform a dry-run to check if everything is fine @@ -142,8 +178,7 @@ async fn main() -> Result<()> { tokio::time::sleep(std::time::Duration::from_secs(3)).await; // Print the new package version (should now be 2) - let effects_v1 = effects.as_v1(); - for changed_obj in effects_v1.changed_objects.iter() { + for changed_obj in effects.as_v1().changed_objects.iter() { match changed_obj.output_state { ObjectOut::PackageWrite { version, .. } => { let pkg_id = changed_obj.object_id; diff --git a/crates/iota-transaction-builder/src/builder/mod.rs b/crates/iota-transaction-builder/src/builder/mod.rs index b49d8ba59..1770570ae 100644 --- a/crates/iota-transaction-builder/src/builder/mod.rs +++ b/crates/iota-transaction-builder/src/builder/mod.rs @@ -452,14 +452,14 @@ impl TransactionBuilder { pub fn upgrade( &mut self, package_id: ObjectId, - upgrade_cap: U, + upgrade_ticket: U, kind: impl Into, ) -> &mut TransactionBuilder { let module = match kind.into() { PublishType::Path(_path) => todo!("load the package from the path"), PublishType::Compiled(m) => m, }; - let ticket = self.apply_argument(upgrade_cap); + let ticket = self.apply_argument(upgrade_ticket); self.cmd_state_change(Upgrade { modules: module.modules, dependencies: module.dependencies, From cb7d9300fe8a2c3d038abb7fc052c00f8e213288 Mon Sep 17 00:00:00 2001 From: /alex/ Date: Tue, 14 Oct 2025 17:39:22 +0200 Subject: [PATCH 04/10] clean up --- crates/iota-sdk-types/src/type_tag/mod.rs | 2 +- crates/iota-sdk/examples/publish_upgrade.rs | 29 +++++++-------------- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/crates/iota-sdk-types/src/type_tag/mod.rs b/crates/iota-sdk-types/src/type_tag/mod.rs index 651e635a9..628349aed 100644 --- a/crates/iota-sdk-types/src/type_tag/mod.rs +++ b/crates/iota-sdk-types/src/type_tag/mod.rs @@ -467,7 +467,7 @@ impl StructTag { pub fn upgrade_cap() -> Self { Self { - address: Address::TWO, + address: Address::FRAMEWORK, module: Identifier::new("package").unwrap(), name: Identifier::new("UpgradeCap").unwrap(), type_params: vec![], diff --git a/crates/iota-sdk/examples/publish_upgrade.rs b/crates/iota-sdk/examples/publish_upgrade.rs index 32cb1f7ec..d7299fc67 100644 --- a/crates/iota-sdk/examples/publish_upgrade.rs +++ b/crates/iota-sdk/examples/publish_upgrade.rs @@ -65,20 +65,18 @@ async fn main() -> Result<()> { if let Some(err) = result.error { bail!("Dry run failed: {err}"); } - println!("Dry run succeeded"); - - // Check on the dry-run effects let Some(effects) = result.effects else { - bail!("Missing transaction effects"); + bail!("Dry run failed: no effects"); }; println!("Effects status (dry run): {:?}", effects.status()); // Sign and execute the transaction (publish the package) + println!("Publishing package"); let sig = private_key.sign_transaction(&tx)?; let Some(effects) = client.execute_tx(&[sig], &tx).await? else { - bail!("Missing transaction effects"); + bail!("Transaction failed: no effects"); }; - println!("Effects status: {:?}", effects.status()); + println!("Effects status (publish): {:?}", effects.status()); // Wait some time for the indexer to process the tx tokio::time::sleep(std::time::Duration::from_secs(3)).await; @@ -107,7 +105,6 @@ async fn main() -> Result<()> { let pkg_id = changed_obj.object_id; println!("PackageId={pkg_id}"); println!("Package version: {version}"); - println!("Package digest: {digest}"); package_id.replace(pkg_id); package_digest.replace(digest); } @@ -121,12 +118,6 @@ async fn main() -> Result<()> { let Some(package_id) = package_id else { bail!("Missing package id"); }; - // let Some(package_digest) = package_digest else { - // bail!("Missing package digest"); - // }; - // let Some(upgrade_cap_digest) = upgrade_cap_digest else { - // bail!("Missing upgrade cap digest"); - // }; let Some(obj_ref) = client .object(upgrade_cap_id, None) @@ -147,7 +138,7 @@ async fn main() -> Result<()> { builder .gas_budget(50_000_000) .gas(gas) - .move_call(Address::TWO, "package", "authorize_upgrade") + .move_call(Address::FRAMEWORK, "package", "authorize_upgrade") .arguments([upgrade_arg, policy_arg, digest_arg]) .name("upgrade_ticket"); @@ -159,20 +150,18 @@ async fn main() -> Result<()> { if let Some(err) = res.error { bail!("Dry run failed: {err}"); } - println!("Dry run succeeded"); - - // Check on the dry-run effects let Some(effects) = res.effects else { - bail!("Missing transaction effects"); + bail!("Dry run failed: no effects"); }; println!("Effects status (dry run): {:?}", effects.status()); // Sign and execute the transaction (upgrade the package) + println!("Upgrading package"); let sig = private_key.sign_transaction(&tx)?; let Some(effects) = client.execute_tx(&[sig], &tx).await? else { - bail!("Missing transaction effects"); + bail!("Transaction failed: no effects"); }; - println!("Effects status: {:?}", effects.status()); + println!("Effects status (upgrade): {:?}", effects.status()); // Wait some time for the indexer to process the tx tokio::time::sleep(std::time::Duration::from_secs(3)).await; From f0b7aea5ede09bad608ece2e888aa71934d95ad0 Mon Sep 17 00:00:00 2001 From: /alex/ Date: Tue, 14 Oct 2025 17:58:29 +0200 Subject: [PATCH 05/10] more clean up --- crates/iota-sdk/examples/publish_upgrade.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/crates/iota-sdk/examples/publish_upgrade.rs b/crates/iota-sdk/examples/publish_upgrade.rs index d7299fc67..db83ab48d 100644 --- a/crates/iota-sdk/examples/publish_upgrade.rs +++ b/crates/iota-sdk/examples/publish_upgrade.rs @@ -10,7 +10,7 @@ use eyre::{Result, bail}; use iota_crypto::{IotaSigner, ed25519::Ed25519PrivateKey}; use iota_graphql_client::{Client, faucet::FaucetClient, pagination::PaginationFilter}; use iota_transaction_builder::{MovePackageData, TransactionBuilder, res}; -use iota_types::{Address, Digest, Input, ObjectId, ObjectOut, StructTag}; +use iota_types::{Address, Input, ObjectId, ObjectOut, StructTag}; use rand::rngs::OsRng; #[tokio::main] @@ -84,12 +84,10 @@ async fn main() -> Result<()> { // Resolve UpgradeCap and PackageId via the client let mut upgrade_cap = None::; let mut package_id = None::; - let mut package_digest = None::; - let mut upgrade_cap_digest = None::; for changed_obj in effects.as_v1().changed_objects.iter() { match changed_obj.output_state { - ObjectOut::ObjectWrite { digest, owner } => { + ObjectOut::ObjectWrite { owner, .. } => { let object_id = changed_obj.object_id; let Some(obj) = client.object(object_id, None).await? else { bail!("Missing object {object_id}"); @@ -98,15 +96,13 @@ async fn main() -> Result<()> { println!("UpgradeCap={object_id}"); println!("Owner: {owner}"); upgrade_cap.replace(object_id); - upgrade_cap_digest.replace(digest); } } - ObjectOut::PackageWrite { version, digest } => { + ObjectOut::PackageWrite { version, .. } => { let pkg_id = changed_obj.object_id; println!("PackageId={pkg_id}"); println!("Package version: {version}"); package_id.replace(pkg_id); - package_digest.replace(digest); } _ => continue, } @@ -144,6 +140,7 @@ async fn main() -> Result<()> { builder.upgrade(package_id, res("upgrade_ticket"), data); let tx = builder.finish().await?; + println!("{tx:#?}"); // Perform a dry-run to check if everything is fine let res = client.dry_run_tx(&tx, false).await?; From 81703b341cfb9657e5999f85b6a3befb82cfdbd8 Mon Sep 17 00:00:00 2001 From: /alex/ Date: Wed, 15 Oct 2025 10:33:13 +0200 Subject: [PATCH 06/10] commit upgrade --- crates/iota-sdk/examples/publish_upgrade.rs | 78 +++++++++++++-------- 1 file changed, 49 insertions(+), 29 deletions(-) diff --git a/crates/iota-sdk/examples/publish_upgrade.rs b/crates/iota-sdk/examples/publish_upgrade.rs index db83ab48d..439dd518d 100644 --- a/crates/iota-sdk/examples/publish_upgrade.rs +++ b/crates/iota-sdk/examples/publish_upgrade.rs @@ -21,13 +21,13 @@ async fn main() -> Result<()> { let Some(compiled_package_digest) = data.digest else { bail!("Missing compiled package digest"); }; - println!("Compiled Package Digest={compiled_package_digest}"); + println!("Compiled Package Digest: {compiled_package_digest}"); // Create a random private key to derive a sender address and for signing let private_key = Ed25519PrivateKey::generate(OsRng); let public_key = private_key.public_key(); let sender = public_key.derive_address(); - println!("Sender={sender}"); + println!("Sender: {sender}"); // Fund the sender address for gas payment let faucet = FaucetClient::new_localnet(); @@ -35,7 +35,7 @@ async fn main() -> Result<()> { bail!("Failed to request coins from faucet"); }; println!( - "Balance={}", + "Available Balance: {}", receipt.sent.iter().map(|coin| coin.amount).sum::() ); @@ -47,18 +47,22 @@ async fn main() -> Result<()> { .data[0] .id(); - // Build the `publish` transaction + // Build the `publish` PTB, that consists of 2 steps let mut builder = TransactionBuilder::new(sender).with_client(client.clone()); - builder - .gas_budget(50_000_000) - .gas(gas) - .publish(data.clone()) - .name("publish"); - // Transfer the `UpgradeCap` to the `sender` - builder.transfer_objects(sender, [res("publish")]); + // 1. Create the upgrade cap + builder.publish(data.clone()).name("upgrade_cap"); - let tx = builder.finish().await?; + // 2. Transfer the upgrade cap to the sender address + builder.transfer_objects(sender, [res("upgrade_cap")]); + + // Finalize the PTB + let tx = builder + .gas_budget(50_000_000) + .gas(gas) + .clone() + .finish() + .await?; // Perform a dry-run to check if everything is fine let result = client.dry_run_tx(&tx, false).await?; @@ -93,14 +97,14 @@ async fn main() -> Result<()> { bail!("Missing object {object_id}"); }; if obj.as_struct().type_ == StructTag::upgrade_cap() { - println!("UpgradeCap={object_id}"); - println!("Owner: {owner}"); + println!("UpgradeCap: {object_id}"); + println!("UpgradeCapOwner: {}", owner.into_address()); upgrade_cap.replace(object_id); } } ObjectOut::PackageWrite { version, .. } => { let pkg_id = changed_obj.object_id; - println!("PackageId={pkg_id}"); + println!("PackageId: {pkg_id}"); println!("Package version: {version}"); package_id.replace(pkg_id); } @@ -115,32 +119,48 @@ async fn main() -> Result<()> { bail!("Missing package id"); }; - let Some(obj_ref) = client + let Some(upgrade_cap_ref) = client .object(upgrade_cap_id, None) .await? .map(|obj| obj.object_ref()) else { - bail!("Missing object"); + bail!("Missing upgrade cap object"); }; - // Make a `move_call` to create the `UpgradeTicket` + // Build the `upgrade` PTB, that consists of 3 steps let mut builder = TransactionBuilder::new(sender).with_client(client.clone()); - let upgrade_arg = builder.input(Input::ImmutableOrOwned(obj_ref)); - let policy_arg = builder.pure(255); - let digest_arg = builder.pure(compiled_package_digest); + let upgrade_cap_arg = builder.input(Input::ImmutableOrOwned(upgrade_cap_ref)); + let upgrade_policy_arg = builder.pure(0); + let compiled_package_digest_arg = builder.pure(compiled_package_digest); - // Build the `upgrade` transaction + // 1. Create the upgrade ticket builder - .gas_budget(50_000_000) - .gas(gas) .move_call(Address::FRAMEWORK, "package", "authorize_upgrade") - .arguments([upgrade_arg, policy_arg, digest_arg]) + .arguments([ + upgrade_cap_arg, + upgrade_policy_arg, + compiled_package_digest_arg, + ]) .name("upgrade_ticket"); - builder.upgrade(package_id, res("upgrade_ticket"), data); - let tx = builder.finish().await?; - println!("{tx:#?}"); + // 2. Get the upgrade receipt + builder + .upgrade(package_id, res("upgrade_ticket"), data) + .name("upgrade_receipt"); + + // 3. Finalize the upgrade + builder + .move_call(Address::FRAMEWORK, "package", "commit_upgrade") + .arguments((upgrade_cap_arg, res("upgrade_receipt"))); + + // Finalize the PTB + let tx = builder + .gas_budget(50_000_000) + .gas(gas) + .clone() + .finish() + .await?; // Perform a dry-run to check if everything is fine let res = client.dry_run_tx(&tx, false).await?; @@ -168,7 +188,7 @@ async fn main() -> Result<()> { match changed_obj.output_state { ObjectOut::PackageWrite { version, .. } => { let pkg_id = changed_obj.object_id; - println!("PackageId={pkg_id}"); + println!("PackageId: {pkg_id}"); println!("Package version: {version}") } _ => continue, From 5505619b0e1da976e64b32bcc47244b9d85464ec Mon Sep 17 00:00:00 2001 From: /alex/ Date: Wed, 15 Oct 2025 15:01:03 +0200 Subject: [PATCH 07/10] make it work --- crates/iota-sdk/examples/publish_upgrade.rs | 29 +++++---------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/crates/iota-sdk/examples/publish_upgrade.rs b/crates/iota-sdk/examples/publish_upgrade.rs index 439dd518d..e6730f665 100644 --- a/crates/iota-sdk/examples/publish_upgrade.rs +++ b/crates/iota-sdk/examples/publish_upgrade.rs @@ -8,7 +8,7 @@ use eyre::{Result, bail}; use iota_crypto::{IotaSigner, ed25519::Ed25519PrivateKey}; -use iota_graphql_client::{Client, faucet::FaucetClient, pagination::PaginationFilter}; +use iota_graphql_client::{Client, faucet::FaucetClient}; use iota_transaction_builder::{MovePackageData, TransactionBuilder, res}; use iota_types::{Address, Input, ObjectId, ObjectOut, StructTag}; use rand::rngs::OsRng; @@ -41,11 +41,6 @@ async fn main() -> Result<()> { // Get a gas coin id let client = Client::new_localnet(); - let gas = *client - .coins(sender, None, PaginationFilter::default()) - .await? - .data[0] - .id(); // Build the `publish` PTB, that consists of 2 steps let mut builder = TransactionBuilder::new(sender).with_client(client.clone()); @@ -57,12 +52,7 @@ async fn main() -> Result<()> { builder.transfer_objects(sender, [res("upgrade_cap")]); // Finalize the PTB - let tx = builder - .gas_budget(50_000_000) - .gas(gas) - .clone() - .finish() - .await?; + let tx = builder.finish().await?; // Perform a dry-run to check if everything is fine let result = client.dry_run_tx(&tx, false).await?; @@ -131,7 +121,7 @@ async fn main() -> Result<()> { let mut builder = TransactionBuilder::new(sender).with_client(client.clone()); let upgrade_cap_arg = builder.input(Input::ImmutableOrOwned(upgrade_cap_ref)); - let upgrade_policy_arg = builder.pure(0); + let upgrade_policy_arg = builder.pure(0u8); let compiled_package_digest_arg = builder.pure(compiled_package_digest); // 1. Create the upgrade ticket @@ -155,19 +145,14 @@ async fn main() -> Result<()> { .arguments((upgrade_cap_arg, res("upgrade_receipt"))); // Finalize the PTB - let tx = builder - .gas_budget(50_000_000) - .gas(gas) - .clone() - .finish() - .await?; + let tx = builder.finish().await?; // Perform a dry-run to check if everything is fine - let res = client.dry_run_tx(&tx, false).await?; - if let Some(err) = res.error { + let result = client.dry_run_tx(&tx, false).await?; + if let Some(err) = result.error { bail!("Dry run failed: {err}"); } - let Some(effects) = res.effects else { + let Some(effects) = result.effects else { bail!("Dry run failed: no effects"); }; println!("Effects status (dry run): {:?}", effects.status()); From 9d17e0f6035f799e4dc81bc718725c55f1856808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thoralf=20M=C3=BCller?= Date: Thu, 16 Oct 2025 10:38:09 +0200 Subject: [PATCH 08/10] bindings publish_upgrade examples --- bindings/go/examples/publish_upgrade/main.go | 227 +++++++++++++++++++ bindings/kotlin/examples/PublishUpgrade.kt | 179 +++++++++++++++ bindings/python/examples/publish_upgrade.py | 157 +++++++++++++ crates/iota-sdk/examples/publish_upgrade.rs | 1 - 4 files changed, 563 insertions(+), 1 deletion(-) create mode 100644 bindings/go/examples/publish_upgrade/main.go create mode 100644 bindings/kotlin/examples/PublishUpgrade.kt create mode 100644 bindings/python/examples/publish_upgrade.py diff --git a/bindings/go/examples/publish_upgrade/main.go b/bindings/go/examples/publish_upgrade/main.go new file mode 100644 index 000000000..0b7016d3f --- /dev/null +++ b/bindings/go/examples/publish_upgrade/main.go @@ -0,0 +1,227 @@ +// Copyright (c) 2025 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "encoding/base64" + "fmt" + "log" + "time" + + sdk "bindings/iota_sdk_ffi" +) + +func main() { + // Hardcoded values from the JSON + modules := [][]byte{ + func() []byte { + b, _ := base64.StdEncoding.DecodeString("oRzrCwYAAAAKAQAIAggUAxw+BFoGBWBBB6EBwQEI4gJACqIDGgy8A5cBDdMEBgAKAQ0BEwEUAAIMAAABCAAAAAgAAQQEAAMDAgAACAABAAAJAgMAABACAwAAEgQDAAAMBQYAAAYHAQAAEQgBAAAFCQoAAQsACwACDg8BAQwCEw8BAQgDDwwNAAoOCgYJBgEHCAQAAQYIAAEDAQYIAQQHCAEDAwcIBAEIAAQDAwUHCAQDCAAFBwgEAgMHCAQBCAIBCAMBBggEAQUBCAECCQAFBkNvbmZpZwVGb3JnZQVTd29yZAlUeENvbnRleHQDVUlEDWNyZWF0ZV9jb25maWcMY3JlYXRlX3N3b3JkAmlkBGluaXQFbWFnaWMJbXlfbW9kdWxlA25ldwluZXdfc3dvcmQGb2JqZWN0D3B1YmxpY190cmFuc2ZlcgZzZW5kZXIIc3RyZW5ndGgOc3dvcmRfdHJhbnNmZXIOc3dvcmRzX2NyZWF0ZWQIdHJhbnNmZXIKdHhfY29udGV4dAV2YWx1ZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAgMHCAMJAxADAQICBwgDEgMCAgIHCAMVAwAAAAABCQoAEQgGAAAAAAAAAAASAQsALhELOAACAQEAAAEECwAQABQCAgEAAAEECwAQARQCAwEAAAEECwAQAhQCBAEAAAEOCgAQAhQGAQAAAAAAAAAWCwAPAhULAxEICwELAhIAAgUBAAABCAsDEQgLAAsBEgALAjgBAgYBAAABBAsACwE4AgIHAQAAAQULAREICwASAgIAAQACAQEA") + return b + }(), + } + dependencies := []*sdk.ObjectId{ + func() *sdk.ObjectId { + id, _ := sdk.ObjectIdFromHex("0x0000000000000000000000000000000000000000000000000000000000000002") + return id + }(), + func() *sdk.ObjectId { + id, _ := sdk.ObjectIdFromHex("0x0000000000000000000000000000000000000000000000000000000000000001") + return id + }(), + } + compiledPackageDigest := []byte{246, 127, 102, 77, 186, 19, 68, 12, 161, 181, 56, 248, 210, 0, 91, 211, 245, 251, 165, 152, 0, 197, 250, 135, 171, 37, 177, 240, 133, 76, 122, 124} + fmt.Printf("Compiled Package Digest: %x\n", compiledPackageDigest) + + // Create a random private key to derive a sender address and for signing + privateKey := sdk.Ed25519PrivateKeyGenerate() + publicKey := privateKey.PublicKey() + sender := publicKey.DeriveAddress() + fmt.Printf("Sender: %s\n", sender.ToHex()) + + // Fund the sender address for gas payment + faucet := sdk.FaucetClientNewLocalnet() + faucetReceipt, err := faucet.RequestAndWait(sender) + if err.(*sdk.SdkFfiError) != nil { + log.Fatalf("Failed to request coins from faucet: %v", err) + } + totalBalance := uint64(0) + for _, coin := range faucetReceipt.Sent { + totalBalance += coin.Amount + } + fmt.Printf("Available Balance: %d\n", totalBalance) + + client := sdk.GraphQlClientNewLocalnet() + + // Build the `publish` PTB, that consists of 2 steps + builder := sdk.TransactionBuilderInit(sender, client) + + // 1. Create the upgrade cap + builder.Publish(modules, dependencies, "upgrade_cap") + + // 2. Transfer the upgrade cap to the sender address + builder.TransferObjects(sender, []*sdk.PtbArgument{sdk.PtbArgumentRes("upgrade_cap")}) + + // Finalize the PTB + tx, err := builder.Finish() + if err.(*sdk.SdkFfiError) != nil { + log.Fatalf("Failed to finish transaction: %v", err) + } + + // Perform a dry-run to check if everything is fine + result, err := client.DryRunTx(tx, nil) + if err.(*sdk.SdkFfiError) != nil { + log.Fatalf("Dry run failed: %v", err) + } + if result.Error != nil { + log.Fatalf("Dry run failed: %v", *result.Error) + } + if result.Effects == nil { + log.Fatal("Dry run failed: no effects") + } + fmt.Printf("Effects status (dry run): %s\n", (*result.Effects).AsV1().Status) + + // Sign and execute the transaction (publish the package) + fmt.Println("Publishing package") + signature, err := privateKey.TrySignSimple(tx.SigningDigest()) + if err != nil { + log.Fatalf("Failed to sign: %v", err) + } + userSignature := sdk.UserSignatureNewSimple(signature) + effects, err := client.ExecuteTx([]*sdk.UserSignature{userSignature}, tx) + if err.(*sdk.SdkFfiError) != nil { + log.Fatalf("Transaction failed: %v", err) + } + if effects == nil { + log.Fatal("Transaction failed: no effects") + } + fmt.Printf("Effects status (publish): %s\n", (*effects).AsV1().Status) + + // Wait some time for the indexer to process the tx + time.Sleep(10 * time.Second) + + // Resolve UpgradeCap and PackageId via the client + var upgradeCap *sdk.ObjectId + var packageId *sdk.ObjectId + + for _, changedObj := range (*effects).AsV1().ChangedObjects { + if _, ok := changedObj.OutputState.(sdk.ObjectOutObjectWrite); ok { + objectId := changedObj.ObjectId + objPtr, err := client.Object(objectId, nil) + if err.(*sdk.SdkFfiError) != nil { + log.Fatalf("Failed to get object: %v", err) + } + obj := *objPtr + if obj.AsStructOpt() != nil { + structType := obj.AsStructOpt().StructType + packageIdent, _ := sdk.NewIdentifier("package") + upgradeCapIdent, _ := sdk.NewIdentifier("UpgradeCap") + upgradeCapType := sdk.NewStructTag(sdk.AddressFramework(), packageIdent, upgradeCapIdent, []*sdk.TypeTag{}) + if structType.String() == upgradeCapType.String() { + upgradeCap = objectId + } + } + } else if _, ok := changedObj.OutputState.(sdk.ObjectOutPackageWrite); ok { + pkgId := changedObj.ObjectId + if packageId == nil { + packageId = pkgId + } + } + } + + if upgradeCap == nil { + log.Fatal("Missing upgrade cap") + } + if packageId == nil { + log.Fatal("Missing package id") + } + + // Build the `upgrade` PTB, that consists of 3 steps + builder2 := sdk.TransactionBuilderInit(sender, client) + + upgradeCapArg := sdk.PtbArgumentObjectId(upgradeCap) + + // 1. Create the upgrade ticket + authorizeUpgrade, err := sdk.NewIdentifier("authorize_upgrade") + if err != nil { + log.Fatalf("Failed to create identifier: %v", err) + } + packageIdent, err := sdk.NewIdentifier("package") + if err != nil { + log.Fatalf("Failed to create identifier: %v", err) + } + builder2.MoveCall( + sdk.AddressFramework(), + packageIdent, + authorizeUpgrade, + []*sdk.PtbArgument{upgradeCapArg, sdk.PtbArgumentU8(0), sdk.PtbArgumentU8Vec(compiledPackageDigest)}, + nil, + []string{"upgrade_ticket"}, + ) + + // 2. Get the upgrade receipt + upgradeReceiptName := "upgrade_receipt" + builder2.Upgrade(modules, dependencies, packageId, sdk.PtbArgumentRes("upgrade_ticket"), &upgradeReceiptName) + + // 3. Finalize the upgrade + commitUpgrade, err := sdk.NewIdentifier("commit_upgrade") + if err != nil { + log.Fatalf("Failed to create identifier: %v", err) + } + builder2.MoveCall( + sdk.AddressFramework(), + packageIdent, + commitUpgrade, + []*sdk.PtbArgument{upgradeCapArg, sdk.PtbArgumentRes("upgrade_receipt")}, + nil, + nil, + ) + + // Finalize the PTB + tx2, err := builder2.Finish() + if err.(*sdk.SdkFfiError) != nil { + log.Fatalf("Failed to finish transaction: %v", err) + } + + // Perform a dry-run to check if everything is fine + result2, err := client.DryRunTx(tx2, nil) + if err.(*sdk.SdkFfiError) != nil { + log.Fatalf("Dry run failed: %v", err) + } + if result2.Error != nil { + log.Fatalf("Dry run failed: %v", *result2.Error) + } + if result2.Effects == nil { + log.Fatal("Dry run failed: no effects") + } + fmt.Printf("Effects status (dry run): %s\n", (*result2.Effects).AsV1().Status) + + // Sign and execute the transaction (upgrade the package) + fmt.Println("Upgrading package") + signature2, err := privateKey.TrySignSimple(tx2.SigningDigest()) + if err != nil { + log.Fatalf("Failed to sign: %v", err) + } + userSignature2 := sdk.UserSignatureNewSimple(signature2) + effects2, err := client.ExecuteTx([]*sdk.UserSignature{userSignature2}, tx2) + if err.(*sdk.SdkFfiError) != nil { + log.Fatalf("Transaction failed: %v", err) + } + if effects2 == nil { + log.Fatal("Transaction failed: no effects") + } + fmt.Printf("Effects status (upgrade): %s\n", (*effects2).AsV1().Status) + + // Wait some time for the indexer to process the tx + time.Sleep(10 * time.Second) + + // Print the new package version (should now be 2) + for _, changedObj := range (*effects2).AsV1().ChangedObjects { + if _, ok := changedObj.OutputState.(sdk.ObjectOutPackageWrite); ok { + pkgId := changedObj.ObjectId + version := changedObj.OutputState.(sdk.ObjectOutPackageWrite).Version + fmt.Printf("PackageId: %s\n", pkgId.ToHex()) + fmt.Printf("Package version: %d\n", version) + } + } +} diff --git a/bindings/kotlin/examples/PublishUpgrade.kt b/bindings/kotlin/examples/PublishUpgrade.kt new file mode 100644 index 000000000..b654f25d2 --- /dev/null +++ b/bindings/kotlin/examples/PublishUpgrade.kt @@ -0,0 +1,179 @@ +// Copyright (c) 2025 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import iota_sdk.* +import java.util.Base64 +import kotlinx.coroutines.runBlocking + +fun main() = runBlocking { + try { + // Hardcoded values + val dataString = + "oRzrCwYAAAAKAQAIAggUAxw+BFoGBWBBB6EBwQEI4gJACqIDGgy8A5cBDdMEBgAKAQ0BEwEUAAIMAAABCAAAAAgAAQQEAAMDAgAACAABAAAJAgMAABACAwAAEgQDAAAMBQYAAAYHAQAAEQgBAAAFCQoAAQsACwACDg8BAQwCEw8BAQgDDwwNAAoOCgYJBgEHCAQAAQYIAAEDAQYIAQQHCAEDAwcIBAEIAAQDAwUHCAQDCAAFBwgEAgMHCAQBCAIBCAMBBggEAQUBCAECCQAFBkNvbmZpZwVGb3JnZQVTd29yZAlUeENvbnRleHQDVUlEDWNyZWF0ZV9jb25maWcMY3JlYXRlX3N3b3JkAmlkBGluaXQFbWFnaWMJbXlfbW9kdWxlA25ldwluZXdfc3dvcmQGb2JqZWN0D3B1YmxpY190cmFuc2ZlcgZzZW5kZXIIc3RyZW5ndGgOc3dvcmRfdHJhbnNmZXIOc3dvcmRzX2NyZWF0ZWQIdHJhbnNmZXIKdHhfY29udGV4dAV2YWx1ZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAgMHCAMJAxADAQICBwgDEgMCAgIHCAMVAwAAAAABCQoAEQgGAAAAAAAAAAASAQsALhELOAACAQEAAAEECwAQABQCAgEAAAEECwAQARQCAwEAAAEECwAQAhQCBAEAAAEOCgAQAhQGAQAAAAAAAAAWCwAPAhULAxEICwELAhIAAgUBAAABCAsDEQgLAAsBEgALAjgBAgYBAAABBAsACwE4AgIHAQAAAQULAREICwASAgIAAQACAQEA|f67f664dba13440ca1b538f8d2005bd3f5fba59800c5fa87ab25b1f0854c7a7c" + val parts = dataString.split("|") + val modulesBase64 = parts[0] + val digestHex = parts[1] + val modules = listOf(Base64.getDecoder().decode(modulesBase64)) + val dependencies = + listOf( + ObjectId.fromHex( + "0x0000000000000000000000000000000000000000000000000000000000000002" + ), + ObjectId.fromHex( + "0x0000000000000000000000000000000000000000000000000000000000000001" + ) + ) + val compiledPackageDigest = digestHex.chunked(2).map { it.toInt(16).toByte() }.toByteArray() + println( + "Compiled Package Digest: ${compiledPackageDigest.joinToString("") { "%02x".format(it) }}" + ) + + // Create a random private key to derive a sender address and for signing + val privateKey = Ed25519PrivateKey.generate() + val publicKey = privateKey.publicKey() + val sender = publicKey.deriveAddress() + println("Sender: ${sender.toHex()}") + + // Fund the sender address for gas payment + val faucet = FaucetClient.newLocalnet() + val faucetReceipt = + faucet.requestAndWait(sender) + ?: throw Exception("Failed to request coins from faucet") + val totalBalance = faucetReceipt.sent.sumOf { it.amount.toLong() } + println("Available Balance: $totalBalance") + + val client = GraphQlClient.newLocalnet() + + // Build the `publish` PTB, that consists of 2 steps + val builder = TransactionBuilder.init(sender, client) + + // 1. Create the upgrade cap + builder.publish(modules, dependencies, "upgrade_cap") + + // 2. Transfer the upgrade cap to the sender address + builder.transferObjects(sender, listOf(PtbArgument.res("upgrade_cap"))) + + // Finalize the PTB + val tx = builder.finish() + + // Perform a dry-run to check if everything is fine + val result = client.dryRunTx(tx, false) + result.error?.let { throw Exception("Dry run failed: $it") } + val effectsPublish = result.effects ?: throw Exception("Dry run failed: no effects") + println("Effects status (dry run): ${effectsPublish.asV1().status}") + + // Sign and execute the transaction (publish the package) + println("Publishing package") + val signature = privateKey.trySignSimple(tx.signingDigest()) + val userSignature = UserSignature.newSimple(signature) + val effects = + client.executeTx(listOf(userSignature), tx) + ?: throw Exception("Transaction failed: no effects") + println("Effects status (publish): ${effects.asV1().status}") + + // Wait some time for the indexer to process the tx + kotlinx.coroutines.delay(3000) + + // Resolve UpgradeCap and PackageId via the client + var upgradeCap: ObjectId? = null + var packageId: ObjectId? = null + + for (changedObj in effects.asV1().changedObjects) { + if (changedObj.outputState is ObjectOut.ObjectWrite) { + val obj: Object = + client.`object`(changedObj.objectId, null) + ?: throw Exception("Missing object ${changedObj.objectId.toHex()}") + val upgradeCapType = + StructTag( + address = Address.framework(), + module = Identifier("package"), + name = Identifier("UpgradeCap"), + typeParams = emptyList() + ) + if (obj.asStruct().structType.toString() == upgradeCapType.toString()) { + upgradeCap = changedObj.objectId + } + } else if (changedObj.outputState is ObjectOut.PackageWrite) { + if (packageId == null) { + packageId = changedObj.objectId + } + } + } + + upgradeCap ?: throw Exception("Missing upgrade cap") + packageId ?: throw Exception("Missing package id") + + // Build the `upgrade` PTB, that consists of 3 steps + val builder2 = TransactionBuilder.init(sender, client) + + val packageIdent = Identifier("package") + val authorizeUpgrade = Identifier("authorize_upgrade") + val commitUpgrade = Identifier("commit_upgrade") + + val upgradeCapArg = PtbArgument.objectId(upgradeCap) + val upgradePolicyArg = PtbArgument.u8(0u) + val compiledPackageDigestArg = PtbArgument.u8Vec(compiledPackageDigest) + + // 1. Create the upgrade ticket + builder2.moveCall( + `package` = Address.framework(), + module = packageIdent, + function = authorizeUpgrade, + arguments = listOf(upgradeCapArg, upgradePolicyArg, compiledPackageDigestArg), + typeArgs = listOf(), + names = listOf("upgrade_ticket") + ) + + // 2. Get the upgrade receipt + builder2.upgrade( + modules, + dependencies, + packageId, + PtbArgument.res("upgrade_ticket"), + "upgrade_receipt" + ) + + // 3. Finalize the upgrade + builder2.moveCall( + `package` = Address.framework(), + module = packageIdent, + function = commitUpgrade, + arguments = listOf(upgradeCapArg, PtbArgument.res("upgrade_receipt")), + typeArgs = listOf(), + names = listOf() + ) + + // Finalize the PTB + val tx2 = builder2.finish() + + // Perform a dry-run to check if everything is fine + val result2 = client.dryRunTx(tx, false) + result2.error?.let { throw Exception("Dry run failed: $it") } + val effectsUpgrade = result2.effects ?: throw Exception("Dry run failed: no effects") + println("Effects status (dry run): ${effectsUpgrade.asV1().status}") + + // Sign and execute the transaction (upgrade the package) + println("Upgrading package") + val signature2 = privateKey.trySignSimple(tx2.signingDigest()) + val userSignature2 = UserSignature.newSimple(signature2) + val effectsUpgrade2 = + client.executeTx(listOf(userSignature2), tx2) + ?: throw Exception("Transaction failed: no effects") + println("Effects status (upgrade): ${effectsUpgrade2.asV1().status}") + + // Wait some time for the indexer to process the tx + kotlinx.coroutines.delay(3000) + + // Print the new package version (should now be 2) + for (changedObj in effectsUpgrade2.asV1().changedObjects) { + if (changedObj.outputState is ObjectOut.PackageWrite) { + val pkgId = changedObj.objectId + val version = (changedObj.outputState as ObjectOut.PackageWrite).version + println("PackageId: ${pkgId.toHex()}") + println("Package version: $version") + } + } + } catch (e: Exception) { + e.printStackTrace() + } +} diff --git a/bindings/python/examples/publish_upgrade.py b/bindings/python/examples/publish_upgrade.py new file mode 100644 index 000000000..c2860bda7 --- /dev/null +++ b/bindings/python/examples/publish_upgrade.py @@ -0,0 +1,157 @@ +# Copyright (c) 2025 IOTA Stiftung +# SPDX-License-Identifier: Apache-2.0 + +from lib.iota_sdk_ffi import * + +import asyncio +import json +import base64 + +# Compiled `first_package` example +SERIALIZED_FIRST_PACKAGE = '{"modules":["oRzrCwYAAAAKAQAIAggUAxw+BFoGBWBBB6EBwQEI4gJACqIDGgy8A5cBDdMEBgAKAQ0BEwEUAAIMAAABCAAAAAgAAQQEAAMDAgAACAABAAAJAgMAABACAwAAEgQDAAAMBQYAAAYHAQAAEQgBAAAFCQoAAQsACwACDg8BAQwCEw8BAQgDDwwNAAoOCgYJBgEHCAQAAQYIAAEDAQYIAQQHCAEDAwcIBAEIAAQDAwUHCAQDCAAFBwgEAgMHCAQBCAIBCAMBBggEAQUBCAECCQAFBkNvbmZpZwVGb3JnZQVTd29yZAlUeENvbnRleHQDVUlEDWNyZWF0ZV9jb25maWcMY3JlYXRlX3N3b3JkAmlkBGluaXQFbWFnaWMJbXlfbW9kdWxlA25ldwluZXdfc3dvcmQGb2JqZWN0D3B1YmxpY190cmFuc2ZlcgZzZW5kZXIIc3RyZW5ndGgOc3dvcmRfdHJhbnNmZXIOc3dvcmRzX2NyZWF0ZWQIdHJhbnNmZXIKdHhfY29udGV4dAV2YWx1ZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAgMHCAMJAxADAQICBwgDEgMCAgIHCAMVAwAAAAABCQoAEQgGAAAAAAAAAAASAQsALhELOAACAQEAAAEECwAQABQCAgEAAAEECwAQARQCAwEAAAEECwAQAhQCBAEAAAEOCgAQAhQGAQAAAAAAAAAWCwAPAhULAxEICwELAhIAAgUBAAABCAsDEQgLAAsBEgALAjgBAgYBAAABBAsACwE4AgIHAQAAAQULAREICwASAgIAAQACAQEA"],"dependencies":["0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000001"],"digest":[246,127,102,77,186,19,68,12,161,181,56,248,210,0,91,211,245,251,165,152,0,197,250,135,171,37,177,240,133,76,122,124]}' + + +async def main(): + try: + # Parse the compiled `first_package` example from the monorepo created with + # `iota move build --dump-bytecode-as-base64` + data = json.loads(SERIALIZED_FIRST_PACKAGE) + modules = [base64.b64decode(module) for module in data["modules"]] + dependencies = [ObjectId.from_hex(dep) for dep in data["dependencies"]] + compiled_package_digest = bytes(data["digest"]) + print(f"Compiled Package Digest: {compiled_package_digest.hex()}") + + # Create a random private key to derive a sender address and for signing + private_key = Ed25519PrivateKey.generate() + public_key = private_key.public_key() + sender = public_key.derive_address() + print(f"Sender: {sender.to_hex()}") + + # Fund the sender address for gas payment + faucet = FaucetClient.new_localnet() + faucet_receipt = await faucet.request_and_wait(sender) + if faucet_receipt is None: + raise Exception("Failed to request coins from faucet") + print(f"Available Balance: {sum(coin.amount for coin in faucet_receipt.sent)}") + + client = GraphQlClient.new_localnet() + + # Build the `publish` PTB, that consists of 2 steps + builder = await TransactionBuilder.init(sender, client) + + # 1. Create the upgrade cap + builder.publish(modules, dependencies, "upgrade_cap") + + # 2. Transfer the upgrade cap to the sender address + builder.transfer_objects(sender, [PtbArgument.res("upgrade_cap")]) + + # Finalize the PTB + tx = await builder.finish() + + # Perform a dry-run to check if everything is fine + result = await client.dry_run_tx(tx, False) + if result.error is not None: + raise Exception(f"Dry run failed: {result.error}") + if result.effects is None: + raise Exception("Dry run failed: no effects") + print(f"Effects status (dry run): {result.effects.as_v1().status}") + + # Sign and execute the transaction (publish the package) + print("Publishing package") + signature = private_key.try_sign_simple(tx.signing_digest()) + user_signature = UserSignature.new_simple(signature) + effects = await client.execute_tx([user_signature], tx) + if effects is None: + raise Exception("Transaction failed: no effects") + print(f"Effects status (publish): {effects.as_v1().status}") + + # Wait some time for the indexer to process the tx + await asyncio.sleep(3) + + # Resolve UpgradeCap and PackageId via the client + upgrade_cap = None + package_id = None + + for changed_obj in effects.as_v1().changed_objects: + if hasattr(changed_obj.output_state, 'owner'): + # ObjectWrite + object_id = changed_obj.object_id + obj = await client.object(object_id, None) + if obj is None: + raise Exception(f"Missing object {object_id.to_hex()}") + upgrade_cap_type = StructTag(Address.framework(), Identifier("package"), Identifier("UpgradeCap")) + if str(obj.as_struct().struct_type) == str(upgrade_cap_type): + upgrade_cap = object_id + elif hasattr(changed_obj.output_state, 'version'): + # PackageWrite + pkg_id = changed_obj.object_id + package_id = pkg_id + + if upgrade_cap is None: + raise Exception("Missing upgrade cap") + if package_id is None: + raise Exception("Missing package id") + + # Build the `upgrade` PTB, that consists of 3 steps + builder = await TransactionBuilder.init(sender, client) + + upgrade_cap_arg = PtbArgument.object_id(upgrade_cap) + upgrade_policy_arg = PtbArgument.u8(0) + compiled_package_digest_arg = PtbArgument.u8_vec(compiled_package_digest) + + # 1. Create the upgrade ticket + builder.move_call( + Address.framework(), + Identifier("package"), + Identifier("authorize_upgrade"), + [upgrade_cap_arg, upgrade_policy_arg, compiled_package_digest_arg], + names=["upgrade_ticket"] + ) + + # 2. Get the upgrade receipt + builder.upgrade(modules, dependencies, package_id, PtbArgument.res("upgrade_ticket"), "upgrade_receipt") + + # 3. Finalize the upgrade + builder.move_call( + Address.framework(), + Identifier("package"), + Identifier("commit_upgrade"), + [upgrade_cap_arg, PtbArgument.res("upgrade_receipt")] + ) + + # Finalize the PTB + tx = await builder.finish() + + # Perform a dry-run to check if everything is fine + result = await client.dry_run_tx(tx, False) + if result.error is not None: + raise Exception(f"Dry run failed: {result.error}") + if result.effects is None: + raise Exception("Dry run failed: no effects") + print(f"Effects status (dry run): {result.effects.as_v1().status}") + + # Sign and execute the transaction (upgrade the package) + print("Upgrading package") + signature = private_key.try_sign_simple(tx.signing_digest()) + user_signature = UserSignature.new_simple(signature) + effects = await client.execute_tx([user_signature], tx) + if effects is None: + raise Exception("Transaction failed: no effects") + print(f"Effects status (upgrade): {effects.as_v1().status}") + + # Wait some time for the indexer to process the tx + await asyncio.sleep(3) + + # Print the new package version (should now be 2) + for changed_obj in effects.as_v1().changed_objects: + if hasattr(changed_obj.output_state, 'version'): + pkg_id = changed_obj.object_id + print(f"PackageId: {pkg_id.to_hex()}") + print(f"Package version: {changed_obj.output_state.version}") + + except Exception as e: + print(f"Error: {e}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/crates/iota-sdk/examples/publish_upgrade.rs b/crates/iota-sdk/examples/publish_upgrade.rs index e6730f665..69147c2cd 100644 --- a/crates/iota-sdk/examples/publish_upgrade.rs +++ b/crates/iota-sdk/examples/publish_upgrade.rs @@ -39,7 +39,6 @@ async fn main() -> Result<()> { receipt.sent.iter().map(|coin| coin.amount).sum::() ); - // Get a gas coin id let client = Client::new_localnet(); // Build the `publish` PTB, that consists of 2 steps From c769c4bce91b65caf115f8957497e199e206a497 Mon Sep 17 00:00:00 2001 From: /alex/ Date: Thu, 23 Oct 2025 17:50:17 +0200 Subject: [PATCH 09/10] let user compile first --- crates/iota-sdk-ffi/src/types/struct_tag.rs | 4 +- crates/iota-sdk/examples/publish_upgrade.rs | 90 +++++++++---------- crates/iota-transaction-builder/Cargo.toml | 2 +- .../src/builder/mod.rs | 20 +++++ 4 files changed, 63 insertions(+), 53 deletions(-) diff --git a/crates/iota-sdk-ffi/src/types/struct_tag.rs b/crates/iota-sdk-ffi/src/types/struct_tag.rs index 29a47f7a7..d28d4faf5 100644 --- a/crates/iota-sdk-ffi/src/types/struct_tag.rs +++ b/crates/iota-sdk-ffi/src/types/struct_tag.rs @@ -49,8 +49,8 @@ impl Identifier { /// identifier ; name of the type /// (vector type-tag) ; type parameters /// ``` -#[derive(derive_more::From, derive_more::Display, uniffi::Object)] -#[uniffi::export(Display)] +#[derive(derive_more::From, derive_more::Display, uniffi::Object, PartialEq)] +#[uniffi::export(Display, Eq)] pub struct StructTag(pub iota_types::StructTag); #[uniffi::export] diff --git a/crates/iota-sdk/examples/publish_upgrade.rs b/crates/iota-sdk/examples/publish_upgrade.rs index 69147c2cd..8c8cee5c2 100644 --- a/crates/iota-sdk/examples/publish_upgrade.rs +++ b/crates/iota-sdk/examples/publish_upgrade.rs @@ -1,23 +1,36 @@ // Copyright (c) 2025 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -//! This example requires running a localnet. +//! This example requires you to compile a Move package first. +//! +//! ```bash +//! cd /path/to/your/move/package/Move.toml +//! +//! export COMPILED_PACKAGE=$(iota move build --dump-bytecode-as-base64) //! ``` -//! iota start --with-faucet --with-graphql --committee-size 1 --force-regenesis +//! +//! ```fish +//! cd /path/to/your/move/package/Move.toml +//! +//! set -x COMPILED_PACKAGE (iota move build --dump-bytecode-as-base64) //! ``` +use std::env::var; + use eyre::{Result, bail}; use iota_crypto::{IotaSigner, ed25519::Ed25519PrivateKey}; use iota_graphql_client::{Client, faucet::FaucetClient}; -use iota_transaction_builder::{MovePackageData, TransactionBuilder, res}; -use iota_types::{Address, Input, ObjectId, ObjectOut, StructTag}; +use iota_transaction_builder::{MovePackageData, TransactionBuilder, builder::UpgradePolicy, res}; +use iota_types::{Address, ObjectId, ObjectOut, StructTag}; use rand::rngs::OsRng; #[tokio::main] async fn main() -> Result<()> { + let compiled_package = var("COMPILED_PACKAGE")?; + // Parse the compiled `first_package` example from the monorepo created with // `iota move build --dump-bytecode-as-base64` - let data = serde_json::from_str::(SERIALIZED_FIRST_PACKAGE)?; + let data = serde_json::from_str::(&compiled_package)?; let Some(compiled_package_digest) = data.digest else { bail!("Missing compiled package digest"); }; @@ -25,12 +38,11 @@ async fn main() -> Result<()> { // Create a random private key to derive a sender address and for signing let private_key = Ed25519PrivateKey::generate(OsRng); - let public_key = private_key.public_key(); - let sender = public_key.derive_address(); + let sender = private_key.public_key().derive_address(); println!("Sender: {sender}"); // Fund the sender address for gas payment - let faucet = FaucetClient::new_localnet(); + let faucet = FaucetClient::new_devnet(); let Some(receipt) = faucet.request_and_wait(sender).await? else { bail!("Failed to request coins from faucet"); }; @@ -39,21 +51,20 @@ async fn main() -> Result<()> { receipt.sent.iter().map(|coin| coin.amount).sum::() ); - let client = Client::new_localnet(); - - // Build the `publish` PTB, that consists of 2 steps - let mut builder = TransactionBuilder::new(sender).with_client(client.clone()); - - // 1. Create the upgrade cap - builder.publish(data.clone()).name("upgrade_cap"); + let client = Client::new_devnet(); + // Build the `publish` PTB, that consists of 2 steps; + // 1. Publish the package and receive the upgrade cap in return // 2. Transfer the upgrade cap to the sender address - builder.transfer_objects(sender, [res("upgrade_cap")]); + let mut builder = TransactionBuilder::new(sender).with_client(client.clone()); + builder + .publish(data.clone()) + .name("upgrade_cap") + .transfer_objects(sender, [res("upgrade_cap")]); - // Finalize the PTB let tx = builder.finish().await?; - // Perform a dry-run to check if everything is fine + // Perform a dry-run first let result = client.dry_run_tx(&tx, false).await?; if let Some(err) = result.error { bail!("Dry run failed: {err}"); @@ -77,7 +88,6 @@ async fn main() -> Result<()> { // Resolve UpgradeCap and PackageId via the client let mut upgrade_cap = None::; let mut package_id = None::; - for changed_obj in effects.as_v1().changed_objects.iter() { match changed_obj.output_state { ObjectOut::ObjectWrite { owner, .. } => { @@ -108,40 +118,23 @@ async fn main() -> Result<()> { bail!("Missing package id"); }; - let Some(upgrade_cap_ref) = client - .object(upgrade_cap_id, None) - .await? - .map(|obj| obj.object_ref()) - else { - bail!("Missing upgrade cap object"); - }; - // Build the `upgrade` PTB, that consists of 3 steps - let mut builder = TransactionBuilder::new(sender).with_client(client.clone()); - - let upgrade_cap_arg = builder.input(Input::ImmutableOrOwned(upgrade_cap_ref)); - let upgrade_policy_arg = builder.pure(0u8); - let compiled_package_digest_arg = builder.pure(compiled_package_digest); - // 1. Create the upgrade ticket - builder - .move_call(Address::FRAMEWORK, "package", "authorize_upgrade") - .arguments([ - upgrade_cap_arg, - upgrade_policy_arg, - compiled_package_digest_arg, - ]) - .name("upgrade_ticket"); - // 2. Get the upgrade receipt - builder - .upgrade(package_id, res("upgrade_ticket"), data) - .name("upgrade_receipt"); - // 3. Finalize the upgrade + let mut builder = TransactionBuilder::new(sender).with_client(client.clone()); builder + .move_call(Address::FRAMEWORK, "package", "authorize_upgrade") + .arguments(( + upgrade_cap_id, + UpgradePolicy::Compatible as u8, + compiled_package_digest, + )) + .name("upgrade_ticket") + .upgrade(package_id, res("upgrade_ticket"), data) + .name("upgrade_receipt") .move_call(Address::FRAMEWORK, "package", "commit_upgrade") - .arguments((upgrade_cap_arg, res("upgrade_receipt"))); + .arguments((upgrade_cap_id, res("upgrade_receipt"))); // Finalize the PTB let tx = builder.finish().await?; @@ -181,6 +174,3 @@ async fn main() -> Result<()> { Ok(()) } - -// Compiled `first_package` example -const SERIALIZED_FIRST_PACKAGE: &str = r#"{"modules":["oRzrCwYAAAAKAQAIAggUAxw+BFoGBWBBB6EBwQEI4gJACqIDGgy8A5cBDdMEBgAKAQ0BEwEUAAIMAAABCAAAAAgAAQQEAAMDAgAACAABAAAJAgMAABACAwAAEgQDAAAMBQYAAAYHAQAAEQgBAAAFCQoAAQsACwACDg8BAQwCEw8BAQgDDwwNAAoOCgYJBgEHCAQAAQYIAAEDAQYIAQQHCAEDAwcIBAEIAAQDAwUHCAQDCAAFBwgEAgMHCAQBCAIBCAMBBggEAQUBCAECCQAFBkNvbmZpZwVGb3JnZQVTd29yZAlUeENvbnRleHQDVUlEDWNyZWF0ZV9jb25maWcMY3JlYXRlX3N3b3JkAmlkBGluaXQFbWFnaWMJbXlfbW9kdWxlA25ldwluZXdfc3dvcmQGb2JqZWN0D3B1YmxpY190cmFuc2ZlcgZzZW5kZXIIc3RyZW5ndGgOc3dvcmRfdHJhbnNmZXIOc3dvcmRzX2NyZWF0ZWQIdHJhbnNmZXIKdHhfY29udGV4dAV2YWx1ZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAgMHCAMJAxADAQICBwgDEgMCAgIHCAMVAwAAAAABCQoAEQgGAAAAAAAAAAASAQsALhELOAACAQEAAAEECwAQABQCAgEAAAEECwAQARQCAwEAAAEECwAQAhQCBAEAAAEOCgAQAhQGAQAAAAAAAAAWCwAPAhULAxEICwELAhIAAgUBAAABCAsDEQgLAAsBEgALAjgBAgYBAAABBAsACwE4AgIHAQAAAQULAREICwASAgIAAQACAQEA"],"dependencies":["0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000001"],"digest":[246,127,102,77,186,19,68,12,161,181,56,248,210,0,91,211,245,251,165,152,0,197,250,135,171,37,177,240,133,76,122,124]}"#; diff --git a/crates/iota-transaction-builder/Cargo.toml b/crates/iota-transaction-builder/Cargo.toml index ca2e37f09..191bb5380 100644 --- a/crates/iota-transaction-builder/Cargo.toml +++ b/crates/iota-transaction-builder/Cargo.toml @@ -9,7 +9,7 @@ description = "Transaction API for the IOTA Blockchain Rust SDK" [dependencies] base64ct = { version = "1.6", features = ["std"] } bcs = "0.1" -derive_more = { version = "2.0", features = ["from"] } +derive_more = { version = "2.0", features = ["from", "display"] } iota-crypto = { package = "iota-crypto", path = "../iota-crypto", features = ["ed25519"] } iota-graphql-client = { package = "iota-graphql-client", path = "../iota-graphql-client" } iota-types = { package = "iota-sdk-types", path = "../iota-sdk-types", features = ["serde", "hash"] } diff --git a/crates/iota-transaction-builder/src/builder/mod.rs b/crates/iota-transaction-builder/src/builder/mod.rs index da431397d..db074f278 100644 --- a/crates/iota-transaction-builder/src/builder/mod.rs +++ b/crates/iota-transaction-builder/src/builder/mod.rs @@ -990,3 +990,23 @@ impl TransactionBuilder { self } } + +/// Rust representation of upgrade policy constants in `iota::package`. +#[repr(u8)] +#[derive(derive_more::Display, Debug, Clone, Copy)] +pub enum UpgradePolicy { + /// The least restrictive policy. Permits changes to all function + /// implementations, the removal of ability constraints on generic type + /// parameters in function signatures, and modifications to private, + /// public(friend), and entry function signatures. However, public function + /// signatures and existing types cannot be changed. + #[display("COMPATIBLE")] + Compatible = 0, + /// Allows adding new functionalities (e.g., new public functions or + /// structs) but restricts changes to existing functionalities. + #[display("ADDITIVE")] + Additive = 128, + /// Limits modifications to the package’s dependencies only. + #[display("DEP_ONLY")] + DepOnly = 192, +} From e8ea9e65cb2dcd2dafe60f979724c45085fd51b2 Mon Sep 17 00:00:00 2001 From: /alex/ Date: Thu, 23 Oct 2025 18:29:40 +0200 Subject: [PATCH 10/10] add UpgradePolicy type --- crates/iota-sdk-ffi/src/types/mod.rs | 1 + crates/iota-sdk-ffi/src/types/package.rs | 20 +++++++++++++++++++ crates/iota-sdk-types/src/lib.rs | 2 ++ crates/iota-sdk-types/src/package.rs | 19 ++++++++++++++++++ crates/iota-sdk/examples/publish_upgrade.rs | 19 +++++++++--------- crates/iota-transaction-builder/Cargo.toml | 2 +- .../src/builder/mod.rs | 20 ------------------- 7 files changed, 53 insertions(+), 30 deletions(-) create mode 100644 crates/iota-sdk-ffi/src/types/package.rs create mode 100644 crates/iota-sdk-types/src/package.rs diff --git a/crates/iota-sdk-ffi/src/types/mod.rs b/crates/iota-sdk-ffi/src/types/mod.rs index 5e7f31874..ea86b628e 100644 --- a/crates/iota-sdk-ffi/src/types/mod.rs +++ b/crates/iota-sdk-ffi/src/types/mod.rs @@ -14,6 +14,7 @@ pub mod gas; pub mod graphql; pub mod iota_names; pub mod object; +pub mod package; pub mod signature; pub mod struct_tag; pub mod transaction; diff --git a/crates/iota-sdk-ffi/src/types/package.rs b/crates/iota-sdk-ffi/src/types/package.rs new file mode 100644 index 000000000..a1af41077 --- /dev/null +++ b/crates/iota-sdk-ffi/src/types/package.rs @@ -0,0 +1,20 @@ +// Copyright (c) 2025 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use iota_types::UpgradePolicy; + +/// Rust representation of upgrade policy constants in `iota::package`. +#[uniffi::remote(Enum)] +pub enum UpgradePolicy { + /// The least restrictive policy. Permits changes to all function + /// implementations, the removal of ability constraints on generic type + /// parameters in function signatures, and modifications to private, + /// public(friend), and entry function signatures. However, public function + /// signatures and existing types cannot be changed. + Compatible = 0, + /// Allows adding new functionalities (e.g., new public functions or + /// structs) but restricts changes to existing functionalities. + Additive = 128, + /// Limits modifications to the package’s dependencies only. + DepOnly = 192, +} diff --git a/crates/iota-sdk-types/src/lib.rs b/crates/iota-sdk-types/src/lib.rs index dca4d6210..a018ea532 100644 --- a/crates/iota-sdk-types/src/lib.rs +++ b/crates/iota-sdk-types/src/lib.rs @@ -122,6 +122,7 @@ mod gas; pub mod iota_names; mod object; mod object_id; +mod package; mod transaction; mod type_tag; mod u256; @@ -159,6 +160,7 @@ pub use object::{ TypeOrigin, UpgradeInfo, Version, }; pub use object_id::ObjectId; +pub use package::UpgradePolicy; #[cfg(feature = "serde")] #[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))] pub(crate) use transaction::SignedTransactionWithIntentMessage; diff --git a/crates/iota-sdk-types/src/package.rs b/crates/iota-sdk-types/src/package.rs new file mode 100644 index 000000000..fe29ea958 --- /dev/null +++ b/crates/iota-sdk-types/src/package.rs @@ -0,0 +1,19 @@ +// Copyright (c) 2025 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +/// Rust representation of upgrade policy constants in `iota::package`. +#[repr(u8)] +#[derive(Debug, Clone, Copy)] +pub enum UpgradePolicy { + /// The least restrictive policy. Permits changes to all function + /// implementations, the removal of ability constraints on generic type + /// parameters in function signatures, and modifications to private, + /// public(friend), and entry function signatures. However, public function + /// signatures and existing types cannot be changed. + Compatible = 0, + /// Allows adding new functionalities (e.g., new public functions or + /// structs) but restricts changes to existing functionalities. + Additive = 128, + /// Limits modifications to the package’s dependencies only. + DepOnly = 192, +} diff --git a/crates/iota-sdk/examples/publish_upgrade.rs b/crates/iota-sdk/examples/publish_upgrade.rs index 8c8cee5c2..760149687 100644 --- a/crates/iota-sdk/examples/publish_upgrade.rs +++ b/crates/iota-sdk/examples/publish_upgrade.rs @@ -20,8 +20,8 @@ use std::env::var; use eyre::{Result, bail}; use iota_crypto::{IotaSigner, ed25519::Ed25519PrivateKey}; use iota_graphql_client::{Client, faucet::FaucetClient}; -use iota_transaction_builder::{MovePackageData, TransactionBuilder, builder::UpgradePolicy, res}; -use iota_types::{Address, ObjectId, ObjectOut, StructTag}; +use iota_transaction_builder::{MovePackageData, TransactionBuilder, res}; +use iota_types::{Address, ObjectId, ObjectOut, StructTag, UpgradePolicy}; use rand::rngs::OsRng; #[tokio::main] @@ -53,13 +53,13 @@ async fn main() -> Result<()> { let client = Client::new_devnet(); - // Build the `publish` PTB, that consists of 2 steps; - // 1. Publish the package and receive the upgrade cap in return - // 2. Transfer the upgrade cap to the sender address + // Build the `publish` PTB let mut builder = TransactionBuilder::new(sender).with_client(client.clone()); builder + // Publish the package and receive the upgrade cap .publish(data.clone()) .name("upgrade_cap") + // Transfer the upgrade cap to the sender address .transfer_objects(sender, [res("upgrade_cap")]); let tx = builder.finish().await?; @@ -118,12 +118,11 @@ async fn main() -> Result<()> { bail!("Missing package id"); }; - // Build the `upgrade` PTB, that consists of 3 steps - // 1. Create the upgrade ticket - // 2. Get the upgrade receipt - // 3. Finalize the upgrade + // Build the `upgrade` PTB let mut builder = TransactionBuilder::new(sender).with_client(client.clone()); builder + // Authorize the upgrade by providing the upgrade cap object id to receive an upgrade + // ticket .move_call(Address::FRAMEWORK, "package", "authorize_upgrade") .arguments(( upgrade_cap_id, @@ -131,8 +130,10 @@ async fn main() -> Result<()> { compiled_package_digest, )) .name("upgrade_ticket") + // Upgrade the package .upgrade(package_id, res("upgrade_ticket"), data) .name("upgrade_receipt") + // Commit the upgrade .move_call(Address::FRAMEWORK, "package", "commit_upgrade") .arguments((upgrade_cap_id, res("upgrade_receipt"))); diff --git a/crates/iota-transaction-builder/Cargo.toml b/crates/iota-transaction-builder/Cargo.toml index 191bb5380..ca2e37f09 100644 --- a/crates/iota-transaction-builder/Cargo.toml +++ b/crates/iota-transaction-builder/Cargo.toml @@ -9,7 +9,7 @@ description = "Transaction API for the IOTA Blockchain Rust SDK" [dependencies] base64ct = { version = "1.6", features = ["std"] } bcs = "0.1" -derive_more = { version = "2.0", features = ["from", "display"] } +derive_more = { version = "2.0", features = ["from"] } iota-crypto = { package = "iota-crypto", path = "../iota-crypto", features = ["ed25519"] } iota-graphql-client = { package = "iota-graphql-client", path = "../iota-graphql-client" } iota-types = { package = "iota-sdk-types", path = "../iota-sdk-types", features = ["serde", "hash"] } diff --git a/crates/iota-transaction-builder/src/builder/mod.rs b/crates/iota-transaction-builder/src/builder/mod.rs index db074f278..da431397d 100644 --- a/crates/iota-transaction-builder/src/builder/mod.rs +++ b/crates/iota-transaction-builder/src/builder/mod.rs @@ -990,23 +990,3 @@ impl TransactionBuilder { self } } - -/// Rust representation of upgrade policy constants in `iota::package`. -#[repr(u8)] -#[derive(derive_more::Display, Debug, Clone, Copy)] -pub enum UpgradePolicy { - /// The least restrictive policy. Permits changes to all function - /// implementations, the removal of ability constraints on generic type - /// parameters in function signatures, and modifications to private, - /// public(friend), and entry function signatures. However, public function - /// signatures and existing types cannot be changed. - #[display("COMPATIBLE")] - Compatible = 0, - /// Allows adding new functionalities (e.g., new public functions or - /// structs) but restricts changes to existing functionalities. - #[display("ADDITIVE")] - Additive = 128, - /// Limits modifications to the package’s dependencies only. - #[display("DEP_ONLY")] - DepOnly = 192, -}