From 7f6cee4579e85e6eceb5510d774585d95293f211 Mon Sep 17 00:00:00 2001 From: Foivos Date: Wed, 5 Jun 2024 17:30:16 +0300 Subject: [PATCH 01/47] saving progress --- move/abi/Move.lock | 6 +- move/abi/Move.toml | 3 +- move/axelar/Move.lock | 27 +++++++ move/axelar_gateway/Move.lock | 6 +- move/axelar_gateway/Move.toml | 3 +- move/axelar_gateway/info.json | 1 - move/axelar_gateway/sources/auth.move | 2 +- move/test/Move.lock | 6 +- move/test/Move.toml | 3 +- move/test/sources/test/test.move | 4 + scripts/publish-package.js | 63 +--------------- scripts/test.js | 76 +++++++++++++++++++ scripts/tx-builder.js | 69 +++++++++++++++++ scripts/utils.js | 102 +++++++------------------- 14 files changed, 223 insertions(+), 148 deletions(-) create mode 100644 move/axelar/Move.lock create mode 100644 scripts/test.js create mode 100644 scripts/tx-builder.js diff --git a/move/abi/Move.lock b/move/abi/Move.lock index 285c6b4a..d50f85dc 100644 --- a/move/abi/Move.lock +++ b/move/abi/Move.lock @@ -2,7 +2,7 @@ [move] version = 2 -manifest_digest = "7DED727D47EB51E5059409B19CC373C6D9AF249D837E9153E7368F3898025E41" +manifest_digest = "89B38FFD4D0D8B2DCFE440924446CCF3A347EA904B2657C9CA229BD7BB881131" deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082" dependencies = [ { name = "Sui" }, @@ -21,6 +21,6 @@ dependencies = [ ] [move.toolchain-version] -compiler-version = "1.25.1" -edition = "2024.beta" +compiler-version = "1.22.0" +edition = "legacy" flavor = "sui" diff --git a/move/abi/Move.toml b/move/abi/Move.toml index 7eb23213..6d7ecf1e 100644 --- a/move/abi/Move.toml +++ b/move/abi/Move.toml @@ -1,10 +1,11 @@ [package] name = "Abi" version = "0.1.0" +published-at = "0x41fb7e9c9d8851ecbfd4b89c910c0465de0cd0cf757c4bb261a8a6019ea33390" edition = "2024.beta" [dependencies] Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet-v1.25.3" } [addresses] -abi = "0x103" +abi = "0x0" diff --git a/move/axelar/Move.lock b/move/axelar/Move.lock new file mode 100644 index 00000000..875170d6 --- /dev/null +++ b/move/axelar/Move.lock @@ -0,0 +1,27 @@ +# @generated by Move, please check-in and do not edit manually. + +[move] +version = 0 +manifest_digest = "8B923BAABABD7F78C5ED5E16715CC628AD0DF9E7AF28490F9A625421CE9E384A" +deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082" + +dependencies = [ + { name = "Sui" }, +] + +[[move.package]] +name = "MoveStdlib" +source = { git = "https://github.com/MystenLabs/sui.git", rev = "framework/mainnet", subdir = "crates/sui-framework/packages/move-stdlib" } + +[[move.package]] +name = "Sui" +source = { git = "https://github.com/MystenLabs/sui.git", rev = "framework/mainnet", subdir = "crates/sui-framework/packages/sui-framework" } + +dependencies = [ + { name = "MoveStdlib" }, +] + +[move.toolchain-version] +compiler-version = "1.22.0" +edition = "legacy" +flavor = "sui" diff --git a/move/axelar_gateway/Move.lock b/move/axelar_gateway/Move.lock index 4c88b1b8..281d8e01 100644 --- a/move/axelar_gateway/Move.lock +++ b/move/axelar_gateway/Move.lock @@ -2,7 +2,7 @@ [move] version = 2 -manifest_digest = "11FAF5CFE0A4A2EBCD5E370FAD144FFF14243A85492B718A2B26A15CF7F0B571" +manifest_digest = "10303CE6C59BAA2CE814E3D11BACC8CB24BE0F8D66753B02190E291CA40F0D39" deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082" dependencies = [ { name = "Sui" }, @@ -21,6 +21,6 @@ dependencies = [ ] [move.toolchain-version] -compiler-version = "1.25.1" -edition = "2024.beta" +compiler-version = "1.22.0" +edition = "legacy" flavor = "sui" diff --git a/move/axelar_gateway/Move.toml b/move/axelar_gateway/Move.toml index 59b0a66f..235f55b2 100644 --- a/move/axelar_gateway/Move.toml +++ b/move/axelar_gateway/Move.toml @@ -1,11 +1,12 @@ [package] name = "AxelarGateway" version = "0.1.0" +published-at = "0x2abacf10c39c44760ad2afcfbdf7bc25054d3bd425c520ac770e688fdb74dffd" edition = "2024.beta" [dependencies] Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet-v1.25.3" } [addresses] -axelar_gateway = "0x100" +axelar_gateway = "0x2abacf10c39c44760ad2afcfbdf7bc25054d3bd425c520ac770e688fdb74dffd" clock = "0x6" diff --git a/move/axelar_gateway/info.json b/move/axelar_gateway/info.json index 9cb0d05d..2d9bb195 100644 --- a/move/axelar_gateway/info.json +++ b/move/axelar_gateway/info.json @@ -1,6 +1,5 @@ { "singletons": [ - "gateway::Gateway", "discovery::RelayerDiscovery" ] } \ No newline at end of file diff --git a/move/axelar_gateway/sources/auth.move b/move/axelar_gateway/sources/auth.move index 36a4d247..c0ca7bb0 100644 --- a/move/axelar_gateway/sources/auth.move +++ b/move/axelar_gateway/sources/auth.move @@ -104,7 +104,7 @@ module axelar_gateway::auth { let current_epoch = self.epoch; let is_latest_signers = current_epoch == signers_epoch; - assert!(signers_epoch == 0 || (current_epoch - signers_epoch) >= PREVIOUS_KEY_RETENTION, EInvalidEpoch); + assert!(signers_epoch == 0 || (current_epoch - signers_epoch) <= PREVIOUS_KEY_RETENTION, EInvalidEpoch); let message = MessageToSign { domain_separator: self.domain_separator, diff --git a/move/test/Move.lock b/move/test/Move.lock index 5afaa68d..12a46226 100644 --- a/move/test/Move.lock +++ b/move/test/Move.lock @@ -2,7 +2,7 @@ [move] version = 2 -manifest_digest = "CF736E0717CB61683E6D638E781AA77454AE00BCA196A7FD23E4ACDBD78C0A5A" +manifest_digest = "6DF02196C888A850522C2336E4F8FF37DA00BCBB2240DEBF2500B46D2358E034" deps_digest = "3C4103934B1E040BB6B23F1D610B4EF9F2F1166A50A104EADCF77467C004C600" dependencies = [ { name = "AxelarGateway" }, @@ -30,6 +30,6 @@ dependencies = [ ] [move.toolchain-version] -compiler-version = "1.25.1" -edition = "2024.beta" +compiler-version = "1.22.0" +edition = "legacy" flavor = "sui" diff --git a/move/test/Move.toml b/move/test/Move.toml index a1b50014..83db6e35 100644 --- a/move/test/Move.toml +++ b/move/test/Move.toml @@ -1,6 +1,7 @@ [package] name = "Test" version = "0.1.0" +published-at = "0x5a53377722f36628ee281bcae8b9e8989f198d33f548f1f6e2eb9fcc8ae1c322" edition = "2024.beta" [dependencies] @@ -8,4 +9,4 @@ Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-fram AxelarGateway = { local = "../axelar_gateway" } [addresses] -test = "0x200" +test = "0x5a53377722f36628ee281bcae8b9e8989f198d33f548f1f6e2eb9fcc8ae1c322" diff --git a/move/test/sources/test/test.move b/move/test/sources/test/test.move index 690ceed7..fbea0ed6 100644 --- a/move/test/sources/test/test.move +++ b/move/test/sources/test/test.move @@ -68,4 +68,8 @@ module test::test { event::emit(Executed { data: payload }); } + + public fun test(arg1: vector, arg2: u64, arg3: u256) { + + } } diff --git a/scripts/publish-package.js b/scripts/publish-package.js index 78a3210c..297ae424 100644 --- a/scripts/publish-package.js +++ b/scripts/publish-package.js @@ -1,5 +1,5 @@ require('dotenv').config(); -const { setConfig, getFullObject, requestSuiFromFaucet } = require('./utils'); +const { setConfig, getFullObject, requestSuiFromFaucet, updateMoveToml } = require('./utils'); const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); const { TransactionBlock } = require('@mysten/sui.js/transactions'); const { SuiClient } = require('@mysten/sui.js/client'); @@ -10,8 +10,7 @@ const fs = require('fs'); const path = require('path'); async function publishPackage(packageName, client, keypair) { - const toml = fs.readFileSync(`${__dirname}/../move/${packageName}/Move.toml`, 'utf8'); - fs.writeFileSync(`${__dirname}/../move/${packageName}/Move.toml`, fillAddresses(toml, '0x0', packageName)); + updateMoveToml(packageName, '0x0'); // remove all controlled temporary objects on process exit const address = keypair.getPublicKey().toSuiAddress(); @@ -47,8 +46,7 @@ async function publishPackage(packageName, client, keypair) { showEffects: true, showObjectChanges: true, showContent: true, - }, - requestType: 'WaitForLocalExecution', + } }); if (publishTxn.effects?.status.status !== 'success') throw new Error('Publish Tx failed'); @@ -56,57 +54,6 @@ async function publishPackage(packageName, client, keypair) { console.info(`Published package ${packageId} from address ${address}}`); - return { packageId, publishTxn }; -} - -function updateMoveToml(packageName, packageId) { - const path = `${__dirname}/../move/${packageName}/Move.toml`; - const toml = fs.readFileSync(path, 'utf8'); - fs.writeFileSync(path, fillAddresses(insertPublishedAt(toml, packageId), packageId, packageName)); -} - -function insertPublishedAt(toml, packageId) { - const lines = toml.split('\n'); - const versionLineIndex = lines.findIndex((line) => line.slice(0, 7) === 'version'); - - if (!(lines[versionLineIndex + 1].slice(0, 12) === 'published-at')) { - lines.splice(versionLineIndex + 1, 0, ''); - } - - lines[versionLineIndex + 1] = `published-at = "${packageId}"`; - return lines.join('\n'); -} - -function fillAddresses(toml, address, packageName) { - const lines = toml.split('\n'); - const addressesIndex = lines.findIndex((line) => line.slice(0, 11) === '[addresses]'); - - for (let i = addressesIndex + 1; i < lines.length; i++) { - const line = lines[i]; - const eqIndex = line.indexOf('='); - - if (eqIndex < 0 || line.slice(0, eqIndex - 1) !== packageName) { - continue; - } - - lines[i] = line.slice(0, eqIndex + 1) + ` "${address}"`; - } - - return lines.join('\n'); -} - -async function publishPackageFull(packageName, client, keypair, env) { - const { packageId, publishTxn } = await publishPackage(packageName, client, keypair); - const info = require(`${__dirname}/../move/${packageName}/info.json`); - const config = {}; - config.packageId = packageId; - - for (const singleton of info.singletons) { - const object = publishTxn.objectChanges.find((object) => object.objectType === `${packageId}::${singleton}`); - config[singleton] = await getFullObject(object, client); - } - - setConfig(packageName, env.alias, config); updateMoveToml(packageName, packageId); return { packageId, publishTxn }; @@ -114,8 +61,6 @@ async function publishPackageFull(packageName, client, keypair, env) { module.exports = { publishPackage, - updateMoveToml, - publishPackageFull, }; if (require.main === module) { @@ -134,6 +79,6 @@ if (require.main === module) { await requestSuiFromFaucet(env, address); } - await publishPackageFull(packageName, client, keypair, env); + await publishPackage(packageName, client, keypair, env); })(); } diff --git a/scripts/test.js b/scripts/test.js new file mode 100644 index 00000000..a58f30cf --- /dev/null +++ b/scripts/test.js @@ -0,0 +1,76 @@ +require('dotenv').config(); +const { setConfig, getFullObject, requestSuiFromFaucet, updateMoveToml } = require('./utils'); +const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); +const { TransactionBlock } = require('@mysten/sui.js/transactions'); +const { SuiClient } = require('@mysten/sui.js/client'); +const { execSync } = require('child_process'); +const { parseEnv } = require('./utils'); +const tmp = require('tmp'); +const fs = require('fs'); +const path = require('path'); +const { publishPackage } = require("./publish-package"); +const { bcs } = require('@mysten/bcs'); +const { + utils: { arrayify, hexlify }, +} = require('ethers'); + + +(async () => { + const env = parseEnv('localnet'); + const privKey = Buffer.from(process.env.SUI_PRIVATE_KEY, 'hex'); + const keypair = Ed25519Keypair.fromSecretKey(privKey); + // create a new SuiClient object pointing to the network you want to use + const client = new SuiClient({ url: env.url }); + const {packageId, publishTxn} = await publishPackage('test', client, keypair); + const singleton = publishTxn.objectChanges.find((change) => change.objectType == `${packageId}::test::Singleton`); + + const func = await client.getNormalizedMoveFunction({package: packageId, module: 'test', function: "test"}); + + const types = func.parameters.map(parameter => parameter.toLowerCase()); + const args = [ + "0x9027dcb35b21318572bda38641b394eb33896aa81878a4f0e7066b119a9ea000", + 13453453423423, + 13453453423423, + ]; + bcs.address = () => bcs.fixedArray(32, bcs.u8()).transform({ + input: (id) => arrayify(id), + output: (id) => hexlify(id), + }); + + bcs.vectorU8 = () => bcs.vector(bcs.u8()).transform({ + input: (input) => { + if(typeof(input) === 'string') input = arrayify(input); + return input; + } + }) + + const serialize = (type, arg) => { + const serializer = (type) => { + if (typeof(type) === 'string') { + return bcs[type](); + } else if (type.Vector) { + if(type.Vector === 'U8') { + return bcs.vectorU8(); + } + return bcs.vector(serializer(type.Vector)); + } else { + return null; + } + } + return serializer(type).serialize(arg).toBytes(); + } + + const tx = new TransactionBlock(); + + tx.moveCall({ + target: `${packageId}::test::test`, + arguments: types.map((type, index) => { + return tx.pure(serialize(type, args[index])); + }), + }); + + await client.signAndExecuteTransactionBlock({ + transactionBlock: tx, + signer: keypair + }) +})(); \ No newline at end of file diff --git a/scripts/tx-builder.js b/scripts/tx-builder.js new file mode 100644 index 00000000..7647b74b --- /dev/null +++ b/scripts/tx-builder.js @@ -0,0 +1,69 @@ +const objectCache = {}; + +function updateCache(txResponse) { + for(const change of txResponse.objectChanges) { + objectCache[change.objectId] = change; + } +} + +function getObject(objectId) { + return objectCache[objectId]; +} + +function serialize (type, arg) { + bcs.address = () => bcs.fixedArray(32, bcs.u8()).transform({ + input: (id) => arrayify(id), + output: (id) => hexlify(id), + }); + + const vectorU8 = () => bcs.vector(bcs.u8()).transform({ + input: (input) => { + if(typeof(input) === 'string') input = arrayify(input); + return bcs.vector(bcs.u8()).serialize(input).toBytes(); + } + }) + + const serializer = (type) => { + if (typeof(type) === 'string') { + return bcs[type](); + } else if (type.Vector) { + if(type.Vector === 'U8') { + return vectorU8(); + } + return bcs.vector(serializer(type.Vector)); + } else { + return null; + } + } + return serializer(type).serialize(arg).toBytes(); +} + +function TxBuilder() { + let tx; + let client; + let keypair; + async function moveCall(target, arguments, typeArguments) { + // If target is string, convert to object that `getNormalizedMoveFunction` accepts. + if(typeof(target) === 'string') { + const first = target.indexOf(':'); + const last = target.indexOf(':', first + 2); + const packageId = target.slice(0, first); + const module = target.slice(first + 2, last); + const functionName = target.slice(last + 2); + target = { + packageId, + module, + function: functionName, + } + } + const moveFn = await client.getNormalizedMoveFunction(target); + + } +} + + + +module.exports = { + updateCache, + getObject, +} \ No newline at end of file diff --git a/scripts/utils.js b/scripts/utils.js index b722b17b..5c4239bd 100644 --- a/scripts/utils.js +++ b/scripts/utils.js @@ -5,10 +5,6 @@ const configs = {}; const { requestSuiFromFaucetV0, getFaucetHost } = require('@mysten/sui.js/faucet'); const { getFullnodeUrl } = require('@mysten/sui.js/client'); -function toPure(hexString) { - return String.fromCharCode(...arrayify(hexString)); -} - function getModuleNameFromSymbol(symbol) { function isNumber(char) { return char >= '0' && char <= '9'; @@ -47,41 +43,6 @@ function getModuleNameFromSymbol(symbol) { return moduleName; } -function getConfig(packagePath, envAlias) { - if (!configs[packagePath]) { - configs[packagePath] = fs.existsSync(`${__dirname}/../info/${packagePath}.json`) - ? JSON.parse(fs.readFileSync(`${__dirname}/../info/${packagePath}.json`)) - : {}; - } - - return configs[packagePath][envAlias]; -} - -function setConfig(packagePath, envAlias, config) { - if (!configs[packagePath]) { - try { - configs[packagePath] = require(`${__dirname}/../info/${packagePath}.json`); - } catch (e) { - switch (e.code) { - case 'MODULE_NOT_FOUND': - case undefined: - configs[packagePath] = {}; - break; - default: - throw e; - } - } - } - - configs[packagePath][envAlias] = config; - - if (!fs.existsSync(`${__dirname}/../info`)) { - fs.mkdirSync(`${__dirname}/../info`); - } - - fs.writeFileSync(`${__dirname}/../info/${packagePath}.json`, JSON.stringify(configs[packagePath], null, 4)); -} - async function requestSuiFromFaucet(env, address) { try { await requestSuiFromFaucetV0({ @@ -95,44 +56,38 @@ async function requestSuiFromFaucet(env, address) { } } -async function getFullObject(object, client) { - for (const field of ['type', 'sender', 'owner']) { - if (object[field]) { - delete object[field]; - } +function updateMoveToml(packageName, packageId, moveDir = `${__dirname}/../move`) { + + const path = `${moveDir}/${packageName}/Move.toml`; + + let toml = fs.readFileSync(path, 'utf8'); + + const lines = toml.split('\n'); + + const versionLineIndex = lines.findIndex((line) => line.slice(0, 7) === 'version'); + + if (!(lines[versionLineIndex + 1].slice(0, 12) === 'published-at')) { + lines.splice(versionLineIndex + 1, 0, ''); } - const objectResponce = await client.getObject({ - id: object.objectId, - options: { - showContent: true, - }, - }); - const fields = objectResponce.data.content.fields; - - function decodeFields(fields, object) { - for (const key in fields) { - if (key === 'id') continue; - - if (fields[key].fields) { - if (!fields[key].fields.id) { - object[key] = {}; - decodeFields(fields[key].fields, object[key]); - } else { - object[key] = fields[key].fields.id.id || fields[key].fields.id; - } - } else if (fields[key].id) { - object[key] = fields[key].id; - } else { - object[key] = fields[key]; - } + lines[versionLineIndex + 1] = `published-at = "${packageId}"`; + + const addressesIndex = lines.findIndex((line) => line.slice(0, 11) === '[addresses]'); + + for (let i = addressesIndex + 1; i < lines.length; i++) { + const line = lines[i]; + const eqIndex = line.indexOf('='); + + if (eqIndex < 0 || line.slice(0, packageName.length) !== packageName || line.slice(packageName.length, eqIndex) !== Array(eqIndex - packageName.length + 1).join(' ') ) { + continue; } - return object; + lines[i] = line.slice(0, eqIndex + 1) + ` "${packageId}"`; } - decodeFields(fields, object); - return object; + toml = lines.join('\n'); + + fs.writeFileSync(path, toml); } function parseEnv(arg) { @@ -148,11 +103,8 @@ function parseEnv(arg) { } module.exports = { - toPure, getModuleNameFromSymbol, - getConfig, - setConfig, - getFullObject, parseEnv, requestSuiFromFaucet, + updateMoveToml, }; From 296eece0ad3e6fb86a7a7046dd1217cdf19bab2b Mon Sep 17 00:00:00 2001 From: Foivos Date: Thu, 6 Jun 2024 19:05:20 +0300 Subject: [PATCH 02/47] added the transaction builder --- move/axelar/Move.lock | 27 ------- move/axelar_gateway/Move.toml | 4 +- move/test/Move.toml | 4 +- move/test/sources/test/test.move | 4 -- scripts/test.js | 76 -------------------- scripts/tx-builder.js | 120 ++++++++++++++++++++++++++----- 6 files changed, 105 insertions(+), 130 deletions(-) delete mode 100644 move/axelar/Move.lock delete mode 100644 scripts/test.js diff --git a/move/axelar/Move.lock b/move/axelar/Move.lock deleted file mode 100644 index 875170d6..00000000 --- a/move/axelar/Move.lock +++ /dev/null @@ -1,27 +0,0 @@ -# @generated by Move, please check-in and do not edit manually. - -[move] -version = 0 -manifest_digest = "8B923BAABABD7F78C5ED5E16715CC628AD0DF9E7AF28490F9A625421CE9E384A" -deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082" - -dependencies = [ - { name = "Sui" }, -] - -[[move.package]] -name = "MoveStdlib" -source = { git = "https://github.com/MystenLabs/sui.git", rev = "framework/mainnet", subdir = "crates/sui-framework/packages/move-stdlib" } - -[[move.package]] -name = "Sui" -source = { git = "https://github.com/MystenLabs/sui.git", rev = "framework/mainnet", subdir = "crates/sui-framework/packages/sui-framework" } - -dependencies = [ - { name = "MoveStdlib" }, -] - -[move.toolchain-version] -compiler-version = "1.22.0" -edition = "legacy" -flavor = "sui" diff --git a/move/axelar_gateway/Move.toml b/move/axelar_gateway/Move.toml index 235f55b2..53e54d43 100644 --- a/move/axelar_gateway/Move.toml +++ b/move/axelar_gateway/Move.toml @@ -1,12 +1,12 @@ [package] name = "AxelarGateway" version = "0.1.0" -published-at = "0x2abacf10c39c44760ad2afcfbdf7bc25054d3bd425c520ac770e688fdb74dffd" +published-at = "0x571841ce66dce70e51a123299ed140d6509566c97eb905331b5f28732c707c56" edition = "2024.beta" [dependencies] Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet-v1.25.3" } [addresses] -axelar_gateway = "0x2abacf10c39c44760ad2afcfbdf7bc25054d3bd425c520ac770e688fdb74dffd" +axelar_gateway = "0x571841ce66dce70e51a123299ed140d6509566c97eb905331b5f28732c707c56" clock = "0x6" diff --git a/move/test/Move.toml b/move/test/Move.toml index 83db6e35..cfe2b83d 100644 --- a/move/test/Move.toml +++ b/move/test/Move.toml @@ -1,7 +1,7 @@ [package] name = "Test" version = "0.1.0" -published-at = "0x5a53377722f36628ee281bcae8b9e8989f198d33f548f1f6e2eb9fcc8ae1c322" +published-at = "0x5de4d52cd17c6e0483598bebb3243a886edefeb216e5ecc7c578edfeb8a7b4a9" edition = "2024.beta" [dependencies] @@ -9,4 +9,4 @@ Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-fram AxelarGateway = { local = "../axelar_gateway" } [addresses] -test = "0x5a53377722f36628ee281bcae8b9e8989f198d33f548f1f6e2eb9fcc8ae1c322" +test = "0x5de4d52cd17c6e0483598bebb3243a886edefeb216e5ecc7c578edfeb8a7b4a9" diff --git a/move/test/sources/test/test.move b/move/test/sources/test/test.move index 821265f7..7e9253e9 100644 --- a/move/test/sources/test/test.move +++ b/move/test/sources/test/test.move @@ -68,8 +68,4 @@ module test::test { event::emit(Executed { data: payload }); } - - public fun test(arg1: vector, arg2: u64, arg3: u256) { - - } } diff --git a/scripts/test.js b/scripts/test.js deleted file mode 100644 index a58f30cf..00000000 --- a/scripts/test.js +++ /dev/null @@ -1,76 +0,0 @@ -require('dotenv').config(); -const { setConfig, getFullObject, requestSuiFromFaucet, updateMoveToml } = require('./utils'); -const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); -const { TransactionBlock } = require('@mysten/sui.js/transactions'); -const { SuiClient } = require('@mysten/sui.js/client'); -const { execSync } = require('child_process'); -const { parseEnv } = require('./utils'); -const tmp = require('tmp'); -const fs = require('fs'); -const path = require('path'); -const { publishPackage } = require("./publish-package"); -const { bcs } = require('@mysten/bcs'); -const { - utils: { arrayify, hexlify }, -} = require('ethers'); - - -(async () => { - const env = parseEnv('localnet'); - const privKey = Buffer.from(process.env.SUI_PRIVATE_KEY, 'hex'); - const keypair = Ed25519Keypair.fromSecretKey(privKey); - // create a new SuiClient object pointing to the network you want to use - const client = new SuiClient({ url: env.url }); - const {packageId, publishTxn} = await publishPackage('test', client, keypair); - const singleton = publishTxn.objectChanges.find((change) => change.objectType == `${packageId}::test::Singleton`); - - const func = await client.getNormalizedMoveFunction({package: packageId, module: 'test', function: "test"}); - - const types = func.parameters.map(parameter => parameter.toLowerCase()); - const args = [ - "0x9027dcb35b21318572bda38641b394eb33896aa81878a4f0e7066b119a9ea000", - 13453453423423, - 13453453423423, - ]; - bcs.address = () => bcs.fixedArray(32, bcs.u8()).transform({ - input: (id) => arrayify(id), - output: (id) => hexlify(id), - }); - - bcs.vectorU8 = () => bcs.vector(bcs.u8()).transform({ - input: (input) => { - if(typeof(input) === 'string') input = arrayify(input); - return input; - } - }) - - const serialize = (type, arg) => { - const serializer = (type) => { - if (typeof(type) === 'string') { - return bcs[type](); - } else if (type.Vector) { - if(type.Vector === 'U8') { - return bcs.vectorU8(); - } - return bcs.vector(serializer(type.Vector)); - } else { - return null; - } - } - return serializer(type).serialize(arg).toBytes(); - } - - const tx = new TransactionBlock(); - - tx.moveCall({ - target: `${packageId}::test::test`, - arguments: types.map((type, index) => { - return tx.pure(serialize(type, args[index])); - }), - }); - - await client.signAndExecuteTransactionBlock({ - transactionBlock: tx, - signer: keypair - }) -})(); \ No newline at end of file diff --git a/scripts/tx-builder.js b/scripts/tx-builder.js index 7647b74b..12200c68 100644 --- a/scripts/tx-builder.js +++ b/scripts/tx-builder.js @@ -1,16 +1,62 @@ -const objectCache = {}; +const { TransactionBlock } = require('@mysten/sui.js/transactions'); +const { bcs } = require('@mysten/bcs'); +const { + utils: { arrayify, hexlify }, +} = require('ethers'); -function updateCache(txResponse) { - for(const change of txResponse.objectChanges) { - objectCache[change.objectId] = change; +function getObject(tx, object) { + if( typeof(object) === 'string' || Array.isArray(object) ) + return tx.object(object); + return object; +} + +function getTypeName(type) { + function get(type) { + const name = `${type.address}::${type.module}::${type.name}`; + if(type.typeArguments.length > 0) { + name += `<${type.typeArguments[0]}`; + for(let i = 1; i < type.typeArguments.length; i++) { + name += `,${type.typeArguments[i]}`; + } + name += '>'; + } + return name; + } + if ( type.Struct ) { + return get(type.Struct); + } else if ( type.Reference ) { + return getTypeName(type.Reference); + } else if ( type.MutableReference ) { + return getTypeName(type.MutableReference); + } else if (type.Vector) { + return `vector<${getTypeName(type.Vector)}>` + } else { + return type.toLowerCase(); } } -function getObject(objectId) { - return objectCache[objectId]; +function getNestedStruct(tx, type, arg) { + if ( type.Struct || type.Reference || type.MutableReference ) { + return getObject(tx, arg); + } + + if(!type.Vector) return null; + nested = arg.map(arg => getNestedStruct(tx, type.Vector, arg)); + if(!nested) return null; + const typeName = getTypeName(type.Vector); + + return tx.makeMoveVec({ + type: typeName, + objects: nested, + }); } -function serialize (type, arg) { +function serialize (tx, type, arg) { + let struct = getNestedStruct(tx, type, arg) + if(struct) { + return struct; + } + bcs.address = () => bcs.fixedArray(32, bcs.u8()).transform({ input: (id) => arrayify(id), output: (id) => hexlify(id), @@ -25,7 +71,7 @@ function serialize (type, arg) { const serializer = (type) => { if (typeof(type) === 'string') { - return bcs[type](); + return bcs[type.toLowerCase()](); } else if (type.Vector) { if(type.Vector === 'U8') { return vectorU8(); @@ -35,14 +81,26 @@ function serialize (type, arg) { return null; } } - return serializer(type).serialize(arg).toBytes(); + return tx.pure(serializer(type).serialize(arg).toBytes()); } -function TxBuilder() { - let tx; - let client; - let keypair; - async function moveCall(target, arguments, typeArguments) { +function isTxContext(parameter) { + parameter = parameter.MutableReference; + if(!parameter) return false; + parameter = parameter.Struct; + if(!parameter) return false; + return parameter.address === '0x2' && parameter.module === 'tx_context' && parameter.name === 'TxContext'; +} + +class TxBuilder { + constructor(client, keypair) { + this.client = client; + this.keypair = keypair; + this.tx = new TransactionBlock(); + this.tx.object + } + + async moveCall(target, args, typeArguments = []) { // If target is string, convert to object that `getNormalizedMoveFunction` accepts. if(typeof(target) === 'string') { const first = target.indexOf(':'); @@ -51,19 +109,43 @@ function TxBuilder() { const module = target.slice(first + 2, last); const functionName = target.slice(last + 2); target = { - packageId, + package: packageId, module, function: functionName, } } - const moveFn = await client.getNormalizedMoveFunction(target); + const moveFn = await this.client.getNormalizedMoveFunction(target); + + let length = moveFn.parameters.length; + if(isTxContext(moveFn.parameters[length - 1])) length = length - 1; + if(length != args.length) throw new Error(`Function ${target.package}::${target.module}::${target.function} takes ${moveFn.parameters.length} arguments but given ${args.length}`); + const convertedArgs = args.map((arg, index) => serialize(this.tx, moveFn.parameters[index], arg)); + + return this.tx.moveCall({ + target: `${target.package}::${target.module}::${target.function}`, + arguments: convertedArgs, + typeArguments: typeArguments, + }) + } + + async signAndExecute(options) { + const result = await this.client.signAndExecuteTransactionBlock({ + transactionBlock: this.tx, + signer: this.keypair, + options: { + showEffects: true, + showObjectChanges: true, + showContent: true, + ...options + } + }); + return result; } } module.exports = { - updateCache, - getObject, -} \ No newline at end of file + TxBuilder +} From edeeb38d390d2762457498f62d618f94330cdc74 Mon Sep 17 00:00:00 2001 From: Foivos Date: Thu, 6 Jun 2024 19:23:03 +0300 Subject: [PATCH 03/47] lint and prettier --- scripts/publish-package.js | 5 +- scripts/tx-builder.js | 109 ++++++++++++++++++++----------------- scripts/utils.js | 16 +++--- 3 files changed, 70 insertions(+), 60 deletions(-) diff --git a/scripts/publish-package.js b/scripts/publish-package.js index 297ae424..767d0e28 100644 --- a/scripts/publish-package.js +++ b/scripts/publish-package.js @@ -1,12 +1,11 @@ require('dotenv').config(); -const { setConfig, getFullObject, requestSuiFromFaucet, updateMoveToml } = require('./utils'); +const { requestSuiFromFaucet, updateMoveToml } = require('./utils'); const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); const { TransactionBlock } = require('@mysten/sui.js/transactions'); const { SuiClient } = require('@mysten/sui.js/client'); const { execSync } = require('child_process'); const { parseEnv } = require('./utils'); const tmp = require('tmp'); -const fs = require('fs'); const path = require('path'); async function publishPackage(packageName, client, keypair) { @@ -46,7 +45,7 @@ async function publishPackage(packageName, client, keypair) { showEffects: true, showObjectChanges: true, showContent: true, - } + }, }); if (publishTxn.effects?.status.status !== 'success') throw new Error('Publish Tx failed'); diff --git a/scripts/tx-builder.js b/scripts/tx-builder.js index 12200c68..d1f827c4 100644 --- a/scripts/tx-builder.js +++ b/scripts/tx-builder.js @@ -5,90 +5,99 @@ const { } = require('ethers'); function getObject(tx, object) { - if( typeof(object) === 'string' || Array.isArray(object) ) - return tx.object(object); + if (typeof object === 'string' || Array.isArray(object)) return tx.object(object); return object; } function getTypeName(type) { function get(type) { - const name = `${type.address}::${type.module}::${type.name}`; - if(type.typeArguments.length > 0) { + let name = `${type.address}::${type.module}::${type.name}`; + + if (type.typeArguments.length > 0) { name += `<${type.typeArguments[0]}`; - for(let i = 1; i < type.typeArguments.length; i++) { + + for (let i = 1; i < type.typeArguments.length; i++) { name += `,${type.typeArguments[i]}`; } + name += '>'; } + return name; } - if ( type.Struct ) { + + if (type.Struct) { return get(type.Struct); - } else if ( type.Reference ) { + } else if (type.Reference) { return getTypeName(type.Reference); - } else if ( type.MutableReference ) { + } else if (type.MutableReference) { return getTypeName(type.MutableReference); } else if (type.Vector) { - return `vector<${getTypeName(type.Vector)}>` - } else { - return type.toLowerCase(); + return `vector<${getTypeName(type.Vector)}>`; } + + return type.toLowerCase(); } function getNestedStruct(tx, type, arg) { - if ( type.Struct || type.Reference || type.MutableReference ) { + if (type.Struct || type.Reference || type.MutableReference) { return getObject(tx, arg); } - if(!type.Vector) return null; - nested = arg.map(arg => getNestedStruct(tx, type.Vector, arg)); - if(!nested) return null; + if (!type.Vector) return null; + const nested = arg.map((arg) => getNestedStruct(tx, type.Vector, arg)); + if (!nested) return null; const typeName = getTypeName(type.Vector); return tx.makeMoveVec({ - type: typeName, + type: typeName, objects: nested, }); } -function serialize (tx, type, arg) { - let struct = getNestedStruct(tx, type, arg) - if(struct) { +function serialize(tx, type, arg) { + const struct = getNestedStruct(tx, type, arg); + + if (struct) { return struct; } - bcs.address = () => bcs.fixedArray(32, bcs.u8()).transform({ - input: (id) => arrayify(id), - output: (id) => hexlify(id), - }); + bcs.address = () => + bcs.fixedArray(32, bcs.u8()).transform({ + input: (id) => arrayify(id), + output: (id) => hexlify(id), + }); - const vectorU8 = () => bcs.vector(bcs.u8()).transform({ - input: (input) => { - if(typeof(input) === 'string') input = arrayify(input); - return bcs.vector(bcs.u8()).serialize(input).toBytes(); - } - }) + const vectorU8 = () => + bcs.vector(bcs.u8()).transform({ + input(input) { + if (typeof input === 'string') input = arrayify(input); + return bcs.vector(bcs.u8()).serialize(input).toBytes(); + }, + }); const serializer = (type) => { - if (typeof(type) === 'string') { + if (typeof type === 'string') { return bcs[type.toLowerCase()](); } else if (type.Vector) { - if(type.Vector === 'U8') { + if (type.Vector === 'U8') { return vectorU8(); } + return bcs.vector(serializer(type.Vector)); - } else { - return null; } - } + + return null; + }; + return tx.pure(serializer(type).serialize(arg).toBytes()); } function isTxContext(parameter) { parameter = parameter.MutableReference; - if(!parameter) return false; + if (!parameter) return false; parameter = parameter.Struct; - if(!parameter) return false; + if (!parameter) return false; return parameter.address === '0x2' && parameter.module === 'tx_context' && parameter.name === 'TxContext'; } @@ -97,12 +106,12 @@ class TxBuilder { this.client = client; this.keypair = keypair; this.tx = new TransactionBlock(); - this.tx.object + this.tx.object; } async moveCall(target, args, typeArguments = []) { // If target is string, convert to object that `getNormalizedMoveFunction` accepts. - if(typeof(target) === 'string') { + if (typeof target === 'string') { const first = target.indexOf(':'); const last = target.indexOf(':', first + 2); const packageId = target.slice(0, first); @@ -112,21 +121,25 @@ class TxBuilder { package: packageId, module, function: functionName, - } + }; } + const moveFn = await this.client.getNormalizedMoveFunction(target); let length = moveFn.parameters.length; - if(isTxContext(moveFn.parameters[length - 1])) length = length - 1; - if(length != args.length) throw new Error(`Function ${target.package}::${target.module}::${target.function} takes ${moveFn.parameters.length} arguments but given ${args.length}`); + if (isTxContext(moveFn.parameters[length - 1])) length = length - 1; + if (length !== args.length) + throw new Error( + `Function ${target.package}::${target.module}::${target.function} takes ${moveFn.parameters.length} arguments but given ${args.length}`, + ); const convertedArgs = args.map((arg, index) => serialize(this.tx, moveFn.parameters[index], arg)); return this.tx.moveCall({ target: `${target.package}::${target.module}::${target.function}`, arguments: convertedArgs, - typeArguments: typeArguments, - }) + typeArguments, + }); } async signAndExecute(options) { @@ -137,15 +150,13 @@ class TxBuilder { showEffects: true, showObjectChanges: true, showContent: true, - ...options - } + ...options, + }, }); return result; } } - - module.exports = { - TxBuilder -} + TxBuilder, +}; diff --git a/scripts/utils.js b/scripts/utils.js index 5c4239bd..9a7ec6c2 100644 --- a/scripts/utils.js +++ b/scripts/utils.js @@ -1,7 +1,4 @@ -const { arrayify } = require('ethers/lib/utils'); const fs = require('fs'); - -const configs = {}; const { requestSuiFromFaucetV0, getFaucetHost } = require('@mysten/sui.js/faucet'); const { getFullnodeUrl } = require('@mysten/sui.js/client'); @@ -57,9 +54,8 @@ async function requestSuiFromFaucet(env, address) { } function updateMoveToml(packageName, packageId, moveDir = `${__dirname}/../move`) { - const path = `${moveDir}/${packageName}/Move.toml`; - + let toml = fs.readFileSync(path, 'utf8'); const lines = toml.split('\n'); @@ -77,8 +73,12 @@ function updateMoveToml(packageName, packageId, moveDir = `${__dirname}/../move` for (let i = addressesIndex + 1; i < lines.length; i++) { const line = lines[i]; const eqIndex = line.indexOf('='); - - if (eqIndex < 0 || line.slice(0, packageName.length) !== packageName || line.slice(packageName.length, eqIndex) !== Array(eqIndex - packageName.length + 1).join(' ') ) { + + if ( + eqIndex < 0 || + line.slice(0, packageName.length) !== packageName || + line.slice(packageName.length, eqIndex) !== Array(eqIndex - packageName.length + 1).join(' ') + ) { continue; } @@ -86,7 +86,7 @@ function updateMoveToml(packageName, packageId, moveDir = `${__dirname}/../move` } toml = lines.join('\n'); - + fs.writeFileSync(path, toml); } From 974192dcd0f8031679e973d7bcda4f9ad68f82f9 Mon Sep 17 00:00:00 2001 From: Foivos Date: Fri, 7 Jun 2024 12:27:23 +0300 Subject: [PATCH 04/47] added object cache --- move/abi/Move.toml | 4 +- move/axelar_gateway/Move.toml | 4 +- scripts/publish-package.js | 2 +- scripts/tx-builder.js | 80 +++++++++++++++++++++++++++++++---- 4 files changed, 76 insertions(+), 14 deletions(-) diff --git a/move/abi/Move.toml b/move/abi/Move.toml index 6d7ecf1e..0244441f 100644 --- a/move/abi/Move.toml +++ b/move/abi/Move.toml @@ -1,11 +1,11 @@ [package] name = "Abi" version = "0.1.0" -published-at = "0x41fb7e9c9d8851ecbfd4b89c910c0465de0cd0cf757c4bb261a8a6019ea33390" +published-at = "0x09ede88971119f6a4fb5d5f5dd927fb48d1eeb92ba23a6ee696b1f51459354cb" edition = "2024.beta" [dependencies] Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet-v1.25.3" } [addresses] -abi = "0x0" +abi = "0x09ede88971119f6a4fb5d5f5dd927fb48d1eeb92ba23a6ee696b1f51459354cb" diff --git a/move/axelar_gateway/Move.toml b/move/axelar_gateway/Move.toml index 53e54d43..ee14cdc7 100644 --- a/move/axelar_gateway/Move.toml +++ b/move/axelar_gateway/Move.toml @@ -1,12 +1,12 @@ [package] name = "AxelarGateway" version = "0.1.0" -published-at = "0x571841ce66dce70e51a123299ed140d6509566c97eb905331b5f28732c707c56" +published-at = "0xcd391ade5ab55a218f8988df8f3aa38ec019651c217244f7f689616c87d8c289" edition = "2024.beta" [dependencies] Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet-v1.25.3" } [addresses] -axelar_gateway = "0x571841ce66dce70e51a123299ed140d6509566c97eb905331b5f28732c707c56" +axelar_gateway = "0xcd391ade5ab55a218f8988df8f3aa38ec019651c217244f7f689616c87d8c289" clock = "0x6" diff --git a/scripts/publish-package.js b/scripts/publish-package.js index 767d0e28..858a9b4b 100644 --- a/scripts/publish-package.js +++ b/scripts/publish-package.js @@ -49,7 +49,7 @@ async function publishPackage(packageName, client, keypair) { }); if (publishTxn.effects?.status.status !== 'success') throw new Error('Publish Tx failed'); - const packageId = (publishTxn.objectChanges?.filter((a) => a.type === 'published') ?? [])[0].packageId; + const packageId = (publishTxn.objectChanges?.find((a) => a.type === 'published') ?? []).packageId; console.info(`Published package ${packageId} from address ${address}}`); diff --git a/scripts/tx-builder.js b/scripts/tx-builder.js index d1f827c4..34d3fb87 100644 --- a/scripts/tx-builder.js +++ b/scripts/tx-builder.js @@ -4,8 +4,30 @@ const { utils: { arrayify, hexlify }, } = require('ethers'); +const objectCache = {}; + +function updateCache(objectChanges) { + for (const change of objectChanges) { + if (!change.objectId) continue; + objectCache[change.objectId] = change; + } +} + function getObject(tx, object) { - if (typeof object === 'string' || Array.isArray(object)) return tx.object(object); + if (Array.isArray(object)) { + object = hexlify(object); + } + + if (typeof object === 'string') { + const cached = objectCache[object]; + + if (cached) { + return tx.object(cached); + } + + return tx.object(object); + } + return object; } @@ -40,15 +62,27 @@ function getTypeName(type) { } function getNestedStruct(tx, type, arg) { + let inside = type; + + while (inside.Vector) { + inside = inside.Vector; + } + + if (!inside.Struct && !inside.Reference && !inside.MutableReference) { + return null; + } + + if (isString(inside)) { + return null; + } + if (type.Struct || type.Reference || type.MutableReference) { return getObject(tx, arg); } if (!type.Vector) return null; const nested = arg.map((arg) => getNestedStruct(tx, type.Vector, arg)); - if (!nested) return null; const typeName = getTypeName(type.Vector); - return tx.makeMoveVec({ type: typeName, objects: nested, @@ -72,11 +106,15 @@ function serialize(tx, type, arg) { bcs.vector(bcs.u8()).transform({ input(input) { if (typeof input === 'string') input = arrayify(input); - return bcs.vector(bcs.u8()).serialize(input).toBytes(); + return input; }, }); const serializer = (type) => { + if (isString(type)) { + return bcs.string(); + } + if (typeof type === 'string') { return bcs[type.toLowerCase()](); } else if (type.Vector) { @@ -101,12 +139,20 @@ function isTxContext(parameter) { return parameter.address === '0x2' && parameter.module === 'tx_context' && parameter.name === 'TxContext'; } +function isString(parameter) { + if (parameter.MutableReference) parameter = parameter.MutableReference; + if (parameter.Reference) parameter = parameter.Reference; + parameter = parameter.Struct; + if (!parameter) return false; + const isAsciiString = parameter.address === '0x1' && parameter.module === 'ascii' && parameter.name === 'String'; + const isStringString = parameter.address === '0x1' && parameter.module === 'string' && parameter.name === 'String'; + return isAsciiString || isStringString; +} + class TxBuilder { - constructor(client, keypair) { + constructor(client) { this.client = client; - this.keypair = keypair; this.tx = new TransactionBlock(); - this.tx.object; } async moveCall(target, args, typeArguments = []) { @@ -142,10 +188,26 @@ class TxBuilder { }); } - async signAndExecute(options) { + async signAndExecute(keypair, options) { const result = await this.client.signAndExecuteTransactionBlock({ transactionBlock: this.tx, - signer: this.keypair, + signer: keypair, + options: { + showEffects: true, + showObjectChanges: true, + showContent: true, + ...options, + }, + }); + updateCache(result.objectChanges); + return result; + } + + async devInspect(sender, options) { + const result = await this.client.devInspectTransactionBlock({ + transactionBlock: this.tx, + sender, + options: { showEffects: true, showObjectChanges: true, From 5d3543c03c935b8626e90f10c118ea0548eebf72 Mon Sep 17 00:00:00 2001 From: Foivos Date: Fri, 7 Jun 2024 12:28:19 +0300 Subject: [PATCH 05/47] fixed some bugs --- scripts/tx-builder.js | 64 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 9 deletions(-) diff --git a/scripts/tx-builder.js b/scripts/tx-builder.js index d1f827c4..1c129394 100644 --- a/scripts/tx-builder.js +++ b/scripts/tx-builder.js @@ -5,7 +5,14 @@ const { } = require('ethers'); function getObject(tx, object) { - if (typeof object === 'string' || Array.isArray(object)) return tx.object(object); + if (Array.isArray(object)) { + object = hexlify(object); + } + + if (typeof object === 'string') { + return tx.object(object); + } + return object; } @@ -40,15 +47,27 @@ function getTypeName(type) { } function getNestedStruct(tx, type, arg) { + let inside = type; + + while (inside.Vector) { + inside = inside.Vector; + } + + if (!inside.Struct && !inside.Reference && !inside.MutableReference) { + return null; + } + + if (isString(inside)) { + return null; + } + if (type.Struct || type.Reference || type.MutableReference) { return getObject(tx, arg); } if (!type.Vector) return null; const nested = arg.map((arg) => getNestedStruct(tx, type.Vector, arg)); - if (!nested) return null; const typeName = getTypeName(type.Vector); - return tx.makeMoveVec({ type: typeName, objects: nested, @@ -72,11 +91,15 @@ function serialize(tx, type, arg) { bcs.vector(bcs.u8()).transform({ input(input) { if (typeof input === 'string') input = arrayify(input); - return bcs.vector(bcs.u8()).serialize(input).toBytes(); + return input; }, }); const serializer = (type) => { + if (isString(type)) { + return bcs.string(); + } + if (typeof type === 'string') { return bcs[type.toLowerCase()](); } else if (type.Vector) { @@ -101,12 +124,20 @@ function isTxContext(parameter) { return parameter.address === '0x2' && parameter.module === 'tx_context' && parameter.name === 'TxContext'; } +function isString(parameter) { + if (parameter.MutableReference) parameter = parameter.MutableReference; + if (parameter.Reference) parameter = parameter.Reference; + parameter = parameter.Struct; + if (!parameter) return false; + const isAsciiString = parameter.address === '0x1' && parameter.module === 'ascii' && parameter.name === 'String'; + const isStringString = parameter.address === '0x1' && parameter.module === 'string' && parameter.name === 'String'; + return isAsciiString || isStringString; +} + class TxBuilder { - constructor(client, keypair) { + constructor(client) { this.client = client; - this.keypair = keypair; this.tx = new TransactionBlock(); - this.tx.object; } async moveCall(target, args, typeArguments = []) { @@ -142,10 +173,25 @@ class TxBuilder { }); } - async signAndExecute(options) { + async signAndExecute(keypair, options) { const result = await this.client.signAndExecuteTransactionBlock({ transactionBlock: this.tx, - signer: this.keypair, + signer: keypair, + options: { + showEffects: true, + showObjectChanges: true, + showContent: true, + ...options, + }, + }); + return result; + } + + async devInspect(sender, options) { + const result = await this.client.devInspectTransactionBlock({ + transactionBlock: this.tx, + sender, + options: { showEffects: true, showObjectChanges: true, From 9b6be0f3d4aac18b5073a4508c66ac3d9f640669 Mon Sep 17 00:00:00 2001 From: Foivos Date: Fri, 7 Jun 2024 15:36:07 +0300 Subject: [PATCH 06/47] added some structs, adding squid structs next --- .../squid/types/deepbook_v2_swap_data.move | 26 ++++++ scripts/bcs.js | 85 +++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 move/squid/sources/squid/types/deepbook_v2_swap_data.move create mode 100644 scripts/bcs.js diff --git a/move/squid/sources/squid/types/deepbook_v2_swap_data.move b/move/squid/sources/squid/types/deepbook_v2_swap_data.move new file mode 100644 index 00000000..7e069c4a --- /dev/null +++ b/move/squid/sources/squid/types/deepbook_v2_swap_data.move @@ -0,0 +1,26 @@ +module squid::deepbook_v2_swap_data { + public struct DeepbookV2SwapData { + swap_type: u8, + pool_id: address, + has_base: bool, + min_output: u64, + base_type: String, + quote_type: String, + lot_size: u64, + should_sweep: bool, + } + + entry fun new(data: vector): DeepbookV2SwapData { + let bcs = bcs::new(data); + DeepbookV2SwapData { + swap_type: bcs.peel_u8(), + pool_id: address(), + has_base: bcs.peel_bool(), + min_output: bcs.peel_u64(), + base_type: ascii::string(bcs.peel_vec_u8()), + quote_type: ascii::string(bcs.peel_vec_u8()), + lot_size: bcs.peel_u64(), + should_sweep: bcs.peel_bool(), + } + } +} \ No newline at end of file diff --git a/scripts/bcs.js b/scripts/bcs.js new file mode 100644 index 00000000..0dd290ae --- /dev/null +++ b/scripts/bcs.js @@ -0,0 +1,85 @@ +const { bcs } = require('@mysten/sui.js/bcs'); + + +function getAxelarStructs() { + const Bytes32 = bcs.struct('Bytes32', { + bytes: bcs.Address, + }); + + const Message = bcs.struct('Message', { + source_chain: bcs.String, + message_id: bcs.String, + source_address: bcs.String, + destination_id: Address, + payload_hash: Bytes32, + }); + + const WeightedSigner = bcs.struct('WeightedSigner', { + pubkey: bcs.vector(bcs.U8), + weight: bcs.U128, + }); + + const WeightedSigners = bcs.struct('WeightedSigners', { + signers: bcs.vector(WeightedSigner), + threshold: bcs.U128, + nonce: Bytes32, + }); + + const Signature = bcs.struct('Signature', { + bytes: bcs.vector(bcs.U8), + }) + + const Proof = bcs.struct('Proof', { + signers: WeightedSigners, + signatures: bcs.vector(Signature), + }) + + const MessageToSign = bcs.struct('MessageToSign', { + domain_separator: Bytes32, + signers_hash: Bytes32, + data_hash: Bytes32, + }); + + const Function = bcs.struct('Function', { + package_id: bcs.Address, + module_name: bcs.String, + name: bcs.String, + }); + + /// Arguments are prefixed with: + /// - 0 for objects followed by exactly 32 bytes that cointain the object id + /// - 1 for pures followed by the bcs encoded form of the pure + /// - 2 for the call contract object, followed by nothing (to be passed into the target function) + /// - 3 for the payload of the contract call (to be passed into the intermediate function) + /// - 4 for an argument returned from a previous move call, followed by a u8 specified which call to get the return of (0 for the first transaction AFTER the one that gets ApprovedMessage out), and then another u8 specifying which argument to input. + const MoveCall = bcs.struct('MoveCall', { + function: Function, + arguments: bcs.vector(bcs.vector(bcs.U8)), + type_arguments: bcs.vector(bcs.String), + }); + + const Transaction = bcs.struct('Transaction', { + is_final: bcs.Bool, + move_calls: bcs.vector(MoveCall), + }); + + const EncodedMessage = bcs.struct('EncodedMessage', { + message_type: bcs.U8, + data: bcs.vector(bcs.U8), + }); + return { + Bytes32, + Message, + WeightedSigner, + WeightedSigners, + Signature, + Proof, + MessageToSign, + Function, + MoveCall, + Transaction, + EncodedMessage, + } +}; + + From 54328964d0f81ba89987fe732ed8d1e05c902836 Mon Sep 17 00:00:00 2001 From: Foivos Date: Tue, 11 Jun 2024 16:41:15 +0300 Subject: [PATCH 07/47] added all the move types --- move/abi/Move.lock | 6 +- move/axelar_gateway/Move.lock | 6 +- move/gas_service/Move.lock | 2 +- move/governance/Move.lock | 2 +- move/interchain_token/Move.lock | 2 +- move/its/Move.lock | 2 +- move/squid/Move.lock | 2 +- move/squid/sources/squid/deepbook_v2.move | 62 +++++++++----- move/squid/sources/squid/transfers.move | 81 +++++++++++++------ .../squid/types/deepbook_v2_swap_data.move | 26 ------ move/test/Move.lock | 6 +- scripts/bcs.js | 41 ++++++++++ scripts/publish-package.js | 1 + 13 files changed, 154 insertions(+), 85 deletions(-) delete mode 100644 move/squid/sources/squid/types/deepbook_v2_swap_data.move diff --git a/move/abi/Move.lock b/move/abi/Move.lock index d50f85dc..75dc1a79 100644 --- a/move/abi/Move.lock +++ b/move/abi/Move.lock @@ -2,7 +2,7 @@ [move] version = 2 -manifest_digest = "89B38FFD4D0D8B2DCFE440924446CCF3A347EA904B2657C9CA229BD7BB881131" +manifest_digest = "1250E6948210D730AADA7F51BB7CEA2D4A337A6A3D982567112494E70CC7F7BA" deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082" dependencies = [ { name = "Sui" }, @@ -21,6 +21,6 @@ dependencies = [ ] [move.toolchain-version] -compiler-version = "1.22.0" -edition = "legacy" +compiler-version = "1.26.1" +edition = "2024.beta" flavor = "sui" diff --git a/move/axelar_gateway/Move.lock b/move/axelar_gateway/Move.lock index 281d8e01..64806bad 100644 --- a/move/axelar_gateway/Move.lock +++ b/move/axelar_gateway/Move.lock @@ -2,7 +2,7 @@ [move] version = 2 -manifest_digest = "10303CE6C59BAA2CE814E3D11BACC8CB24BE0F8D66753B02190E291CA40F0D39" +manifest_digest = "CA371CB4070828EC012CA6D0738C0BDB1C6F855975C764AB0D480873887AB680" deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082" dependencies = [ { name = "Sui" }, @@ -21,6 +21,6 @@ dependencies = [ ] [move.toolchain-version] -compiler-version = "1.22.0" -edition = "legacy" +compiler-version = "1.26.1" +edition = "2024.beta" flavor = "sui" diff --git a/move/gas_service/Move.lock b/move/gas_service/Move.lock index 3b8e9178..04215722 100644 --- a/move/gas_service/Move.lock +++ b/move/gas_service/Move.lock @@ -21,6 +21,6 @@ dependencies = [ ] [move.toolchain-version] -compiler-version = "1.25.1" +compiler-version = "1.26.1" edition = "2024.beta" flavor = "sui" diff --git a/move/governance/Move.lock b/move/governance/Move.lock index 92609743..096fd921 100644 --- a/move/governance/Move.lock +++ b/move/governance/Move.lock @@ -39,6 +39,6 @@ dependencies = [ ] [move.toolchain-version] -compiler-version = "1.25.1" +compiler-version = "1.26.1" edition = "2024.beta" flavor = "sui" diff --git a/move/interchain_token/Move.lock b/move/interchain_token/Move.lock index e724791e..8b658462 100644 --- a/move/interchain_token/Move.lock +++ b/move/interchain_token/Move.lock @@ -21,6 +21,6 @@ dependencies = [ ] [move.toolchain-version] -compiler-version = "1.25.1" +compiler-version = "1.26.1" edition = "2024.beta" flavor = "sui" diff --git a/move/its/Move.lock b/move/its/Move.lock index 06cc4987..d45ae8ec 100644 --- a/move/its/Move.lock +++ b/move/its/Move.lock @@ -49,6 +49,6 @@ dependencies = [ ] [move.toolchain-version] -compiler-version = "1.25.1" +compiler-version = "1.26.1" edition = "2024.beta" flavor = "sui" diff --git a/move/squid/Move.lock b/move/squid/Move.lock index d9e2d31f..f7bcfa21 100644 --- a/move/squid/Move.lock +++ b/move/squid/Move.lock @@ -69,6 +69,6 @@ dependencies = [ ] [move.toolchain-version] -compiler-version = "1.25.1" +compiler-version = "1.26.1" edition = "2024.beta" flavor = "sui" diff --git a/move/squid/sources/squid/deepbook_v2.move b/move/squid/sources/squid/deepbook_v2.move index 99604f14..55a3868e 100644 --- a/move/squid/sources/squid/deepbook_v2.move +++ b/move/squid/sources/squid/deepbook_v2.move @@ -1,6 +1,6 @@ module squid::deepbook_v2 { use std::type_name; - use std::ascii; + use std::ascii::{Self, String}; use sui::coin::{Self, Coin}; use sui::clock::Clock; @@ -25,7 +25,32 @@ module squid::deepbook_v2 { const EWrongCoinType: u64 = 2; const ENotEnoughOutput: u64 = 3; - public fun swap_base(pool: &mut Pool, coin: Coin, clock: &Clock, ctx: &mut TxContext): (Coin, Coin) { + public struct DeepbookV2SwapData has drop{ + swap_type: u8, + pool_id: address, + has_base: bool, + min_output: u64, + base_type: String, + quote_type: String, + lot_size: u64, + should_sweep: bool, + } + + fun new(data: vector): DeepbookV2SwapData { + let mut bcs = bcs::new(data); + DeepbookV2SwapData { + swap_type: bcs.peel_u8(), + pool_id: bcs.peel_address(), + has_base: bcs.peel_bool(), + min_output: bcs.peel_u64(), + base_type: ascii::string(bcs.peel_vec_u8()), + quote_type: ascii::string(bcs.peel_vec_u8()), + lot_size: bcs.peel_u64(), + should_sweep: bcs.peel_bool(), + } + } + + fun swap_base(pool: &mut Pool, coin: Coin, clock: &Clock, ctx: &mut TxContext): (Coin, Coin) { let account = clob::create_account(ctx); let (base_coin, quote_coin, _) = pool.swap_exact_base_for_quote( 0, @@ -40,7 +65,7 @@ module squid::deepbook_v2 { (base_coin, quote_coin) } - public fun swap_quote(pool: &mut Pool, coin: Coin, clock: &Clock, ctx: &mut TxContext): (Coin, Coin) { + fun swap_quote(pool: &mut Pool, coin: Coin, clock: &Clock, ctx: &mut TxContext): (Coin, Coin) { let account = clob::create_account(ctx); let (base_coin, quote_coin, _) = pool.swap_exact_quote_for_base( 0, @@ -149,7 +174,7 @@ module squid::deepbook_v2 { (filled_quote_quantity, filled_base_quantity) } - public fun predict_base_for_quote(pool: &Pool, amount: u64, lot_size: u64, clock: &Clock): (u64, u64) { + fun predict_base_for_quote(pool: &Pool, amount: u64, lot_size: u64, clock: &Clock): (u64, u64) { let max_price = (1u128 << 64 - 1 as u64); let (prices, depths) = clob::get_level2_book_status_bid_side(pool, 0, max_price, clock); let mut amount_left = amount; @@ -171,7 +196,7 @@ module squid::deepbook_v2 { } - public fun predict_quote_for_base(pool: &Pool, amount: u64, lot_size: u64, clock: &Clock): (u64, u64) { + fun predict_quote_for_base(pool: &Pool, amount: u64, lot_size: u64, clock: &Clock): (u64, u64) { let max_price = (1u128 << 64 - 1 as u64); let (prices, depths) = clob::get_level2_book_status_ask_side(pool, 0, max_price, clock); @@ -257,32 +282,27 @@ module squid::deepbook_v2 { public fun swap(self: &mut SwapInfo, pool: &mut Pool, squid: &mut Squid, clock: &Clock, ctx: &mut TxContext) { let data = self.get_data_swapping(); if(data.length() == 0) return; - let mut bcs = bcs::new(data); + let swap_data = new(data); - assert!(bcs.peel_u8() == SWAP_TYPE, EWrongSwapType); + assert!(swap_data.swap_type == SWAP_TYPE, EWrongSwapType); - assert!(bcs.peel_address() == object::id_address(pool), EWrongPool); - - let has_base = bcs.peel_bool(); - let min_output = bcs.peel_u64(); + assert!(swap_data.pool_id == object::id_address(pool), EWrongPool); assert!( - &bcs.peel_vec_u8() == &type_name::get().into_string().into_bytes(), + &swap_data.base_type == &type_name::get().into_string(), EWrongCoinType, ); assert!( - &bcs.peel_vec_u8() == &type_name::get().into_string().into_bytes(), + &swap_data.quote_type == &type_name::get().into_string(), EWrongCoinType, ); - let lot_size = bcs.peel_u64(); - let should_sweep = bcs.peel_bool(); - if(has_base) { + if(swap_data.has_base) { let mut base_balance = self.coin_bag().get_balance().destroy_some(); - let leftover = base_balance.value() % lot_size; + let leftover = base_balance.value() % swap_data.lot_size; if(leftover > 0) { - if(should_sweep) { + if(swap_data.should_sweep) { squid.coin_bag().store_balance( base_balance.split(leftover) ); @@ -298,7 +318,7 @@ module squid::deepbook_v2 { clock, ctx, ); - assert!(min_output <= quote_coin.value(), ENotEnoughOutput); + assert!(swap_data.min_output <= quote_coin.value(), ENotEnoughOutput); base_coin.destroy_zero(); self.coin_bag().store_balance(quote_coin.into_balance()); } else { @@ -309,9 +329,9 @@ module squid::deepbook_v2 { clock, ctx, ); - assert!(min_output <= base_coin.value(), ENotEnoughOutput); + assert!(swap_data.min_output <= base_coin.value(), ENotEnoughOutput); self.coin_bag().store_balance(base_coin.into_balance()); - if(should_sweep) { + if(swap_data.should_sweep) { squid.coin_bag().store_balance(quote_coin.into_balance()); } else { self.coin_bag().store_balance(quote_coin.into_balance()); diff --git a/move/squid/sources/squid/transfers.move b/move/squid/sources/squid/transfers.move index a362d38b..10ce3711 100644 --- a/move/squid/sources/squid/transfers.move +++ b/move/squid/sources/squid/transfers.move @@ -1,6 +1,6 @@ module squid::transfers { use std::type_name; - use std::ascii; + use std::ascii::{Self, String}; use sui::bcs::{Self, BCS}; use sui::coin; @@ -9,7 +9,7 @@ module squid::transfers { use its::service; use its::its::ITS; - use its::token_id; + use its::token_id::{Self, TokenId}; use squid::swap_info::{SwapInfo}; @@ -19,15 +19,51 @@ module squid::transfers { const EWrongSwapType: u64 = 0; const EWrongCoinType: u64 = 1; + public struct SuiTransferSwapData has drop { + swap_type: u8, + coin_type: String, + recipient: address, + } + + public struct ItsTransferSwapData has drop { + swap_type: u8, + coin_type: String, + token_id: TokenId, + destination_chain: String, + destination_address: vector, + metadata: vector, + } + + fun new_sui_transfer_swap_data(data: vector): SuiTransferSwapData { + let mut bcs = bcs::new(data); + SuiTransferSwapData { + swap_type: bcs.peel_u8(), + coin_type: ascii::string(bcs.peel_vec_u8()), + recipient: bcs.peel_address(), + } + } + + fun new_its_transfer_swap_data(data: vector): ItsTransferSwapData { + let mut bcs = bcs::new(data); + ItsTransferSwapData { + swap_type: bcs.peel_u8(), + coin_type: ascii::string(bcs.peel_vec_u8()), + token_id: token_id::from_address(bcs.peel_address()), + destination_chain: ascii::string(bcs.peel_vec_u8()), + destination_address: bcs.peel_vec_u8(), + metadata: bcs.peel_vec_u8(), + } + } + public fun sui_estimate(swap_info: &mut SwapInfo) { let data = swap_info.get_data_estimating(); if (data.length() == 0) return; - let mut bcs = bcs::new(data); + let swap_data = new_sui_transfer_swap_data(data); - assert!(bcs.peel_u8() == SWAP_TYPE_SUI_TRANSFER, EWrongSwapType); + assert!(swap_data.swap_type == SWAP_TYPE_SUI_TRANSFER, EWrongSwapType); assert!( - &bcs.peel_vec_u8() == &type_name::get().into_string().into_bytes(), + &swap_data.coin_type == &type_name::get().into_string(), EWrongCoinType, ); @@ -37,12 +73,12 @@ module squid::transfers { public fun its_estimate(swap_info: &mut SwapInfo) { let data = swap_info.get_data_estimating(); if (data.length() == 0) return; - let mut bcs = bcs::new(data); + let swap_data = new_its_transfer_swap_data(data); - assert!(bcs.peel_u8() == SWAP_TYPE_ITS_TRANSFER, EWrongSwapType); + assert!(swap_data.swap_type == SWAP_TYPE_ITS_TRANSFER, EWrongSwapType); assert!( - &bcs.peel_vec_u8() == &type_name::get().into_string().into_bytes(), + &swap_data.coin_type == &type_name::get().into_string(), EWrongCoinType, ); @@ -52,12 +88,12 @@ module squid::transfers { public fun sui_transfer(swap_info: &mut SwapInfo, ctx: &mut TxContext) { let data = swap_info.get_data_swapping(); if (data.length() == 0) return; - let mut bcs = bcs::new(data); + let swap_data = new_sui_transfer_swap_data(data); - assert!(bcs.peel_u8() == SWAP_TYPE_SUI_TRANSFER, EWrongSwapType); + assert!(swap_data.swap_type == SWAP_TYPE_SUI_TRANSFER, EWrongSwapType); assert!( - &bcs.peel_vec_u8() == &type_name::get().into_string().into_bytes(), + &swap_data.coin_type == &type_name::get().into_string(), EWrongCoinType, ); @@ -66,19 +102,19 @@ module squid::transfers { option.destroy_none(); return }; - let address = bcs.peel_address(); - transfer::public_transfer(coin::from_balance(option.destroy_some(), ctx), address); + + transfer::public_transfer(coin::from_balance(option.destroy_some(), ctx), swap_data.recipient); } public fun its_transfer(swap_info: &mut SwapInfo, its: &mut ITS, ctx: &mut TxContext) { let data = swap_info.get_data_swapping(); if (data.length() == 0) return; - let mut bcs = bcs::new(data); + let swap_data = new_its_transfer_swap_data(data); - assert!(bcs.peel_u8() == SWAP_TYPE_SUI_TRANSFER, EWrongSwapType); + assert!(swap_data.swap_type == SWAP_TYPE_SUI_TRANSFER, EWrongSwapType); assert!( - &bcs.peel_vec_u8() == &type_name::get().into_string().into_bytes(), + &swap_data.coin_type == &type_name::get().into_string(), EWrongCoinType, ); @@ -87,17 +123,14 @@ module squid::transfers { option.destroy_none(); return }; - let token_id = token_id::from_address(bcs.peel_address()); - let destination_chain = ascii::string(bcs.peel_vec_u8()); - let destination_address = bcs.peel_vec_u8(); - let metadata = bcs.peel_vec_u8(); + service::interchain_transfer( its, - token_id, + swap_data.token_id, coin::from_balance(option.destroy_some(), ctx), - destination_chain, - destination_address, - metadata, + swap_data.destination_chain, + swap_data.destination_address, + swap_data.metadata, ctx, ); } diff --git a/move/squid/sources/squid/types/deepbook_v2_swap_data.move b/move/squid/sources/squid/types/deepbook_v2_swap_data.move deleted file mode 100644 index 7e069c4a..00000000 --- a/move/squid/sources/squid/types/deepbook_v2_swap_data.move +++ /dev/null @@ -1,26 +0,0 @@ -module squid::deepbook_v2_swap_data { - public struct DeepbookV2SwapData { - swap_type: u8, - pool_id: address, - has_base: bool, - min_output: u64, - base_type: String, - quote_type: String, - lot_size: u64, - should_sweep: bool, - } - - entry fun new(data: vector): DeepbookV2SwapData { - let bcs = bcs::new(data); - DeepbookV2SwapData { - swap_type: bcs.peel_u8(), - pool_id: address(), - has_base: bcs.peel_bool(), - min_output: bcs.peel_u64(), - base_type: ascii::string(bcs.peel_vec_u8()), - quote_type: ascii::string(bcs.peel_vec_u8()), - lot_size: bcs.peel_u64(), - should_sweep: bcs.peel_bool(), - } - } -} \ No newline at end of file diff --git a/move/test/Move.lock b/move/test/Move.lock index 12a46226..ed1e8c31 100644 --- a/move/test/Move.lock +++ b/move/test/Move.lock @@ -2,7 +2,7 @@ [move] version = 2 -manifest_digest = "6DF02196C888A850522C2336E4F8FF37DA00BCBB2240DEBF2500B46D2358E034" +manifest_digest = "E39FD071E9EFD0729A4D15C389E9E5EF831FB1E0DB9B2A6E35AFD0DC302863A1" deps_digest = "3C4103934B1E040BB6B23F1D610B4EF9F2F1166A50A104EADCF77467C004C600" dependencies = [ { name = "AxelarGateway" }, @@ -30,6 +30,6 @@ dependencies = [ ] [move.toolchain-version] -compiler-version = "1.22.0" -edition = "legacy" +compiler-version = "1.26.1" +edition = "2024.beta" flavor = "sui" diff --git a/scripts/bcs.js b/scripts/bcs.js index 0dd290ae..d327c56b 100644 --- a/scripts/bcs.js +++ b/scripts/bcs.js @@ -67,6 +67,7 @@ function getAxelarStructs() { message_type: bcs.U8, data: bcs.vector(bcs.U8), }); + return { Bytes32, Message, @@ -82,4 +83,44 @@ function getAxelarStructs() { } }; +function getSquidStructs() { + + const DeepbookV2SwapData = bcs.struct('DeepbookV2SwapData', { + swap_type: bcs.U8, + pool_id: bcs.Address, + has_base: bcs.Bool, + min_output: bcs.U64, + base_type: bcs.String, + quote_type: bcs.String, + lot_size: bcs.U64, + should_sweep: bcs.Bool, + }); + + const SuiTransferSwapData = bcs.struct('SuiTransferSwapData', { + swap_type: bcs.U8, + coin_type: bcs.String, + recipient: bcs.Address, + }); + + const ItsTransferSwapData = bcs.struct('ItsTransferSwapData', { + swap_type: bcs.U8, + coin_type: bcs.String, + token_id: bcs.Address, + destination_chain: bcs.String, + destination_address: bcs.vector(bcs.U8), + metadata: bcs.vector(bcs.U8), + }); + + return { + DeepbookV2SwapData, + SuiTransferSwapData, + ItsTransferSwapData, + } +} + +module.exports = { + axelarStructs: getAxelarStructs(), + squidStructs: getSquidStructs(), +} + diff --git a/scripts/publish-package.js b/scripts/publish-package.js index 858a9b4b..9c5e7046 100644 --- a/scripts/publish-package.js +++ b/scripts/publish-package.js @@ -71,6 +71,7 @@ if (require.main === module) { const privKey = Buffer.from(process.env.SUI_PRIVATE_KEY, 'hex'); const keypair = Ed25519Keypair.fromSecretKey(privKey); const address = keypair.getPublicKey().toSuiAddress(); + console.log(address); // create a new SuiClient object pointing to the network you want to use const client = new SuiClient({ url: env.url }); From 6a8d79b9b21f85f1fbe1b52824a7e8ee7c41b06c Mon Sep 17 00:00:00 2001 From: Foivos Date: Tue, 11 Jun 2024 18:13:58 +0300 Subject: [PATCH 08/47] fix an error --- scripts/bcs.js | 19 +++++++------------ scripts/tx-builder.js | 2 +- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/scripts/bcs.js b/scripts/bcs.js index d327c56b..a5eab8f4 100644 --- a/scripts/bcs.js +++ b/scripts/bcs.js @@ -1,6 +1,4 @@ const { bcs } = require('@mysten/sui.js/bcs'); - - function getAxelarStructs() { const Bytes32 = bcs.struct('Bytes32', { bytes: bcs.Address, @@ -10,7 +8,7 @@ function getAxelarStructs() { source_chain: bcs.String, message_id: bcs.String, source_address: bcs.String, - destination_id: Address, + destination_id: bcs.Address, payload_hash: Bytes32, }); @@ -27,12 +25,12 @@ function getAxelarStructs() { const Signature = bcs.struct('Signature', { bytes: bcs.vector(bcs.U8), - }) + }); const Proof = bcs.struct('Proof', { signers: WeightedSigners, signatures: bcs.vector(Signature), - }) + }); const MessageToSign = bcs.struct('MessageToSign', { domain_separator: Bytes32, @@ -80,11 +78,10 @@ function getAxelarStructs() { MoveCall, Transaction, EncodedMessage, - } -}; + }; +} function getSquidStructs() { - const DeepbookV2SwapData = bcs.struct('DeepbookV2SwapData', { swap_type: bcs.U8, pool_id: bcs.Address, @@ -115,12 +112,10 @@ function getSquidStructs() { DeepbookV2SwapData, SuiTransferSwapData, ItsTransferSwapData, - } + }; } module.exports = { axelarStructs: getAxelarStructs(), squidStructs: getSquidStructs(), -} - - +}; diff --git a/scripts/tx-builder.js b/scripts/tx-builder.js index bc3e4f1f..34d3fb87 100644 --- a/scripts/tx-builder.js +++ b/scripts/tx-builder.js @@ -221,4 +221,4 @@ class TxBuilder { module.exports = { TxBuilder, -}; \ No newline at end of file +}; From 36c43a777138bd7f836ced6834dccde4f4078a3f Mon Sep 17 00:00:00 2001 From: Foivos Date: Tue, 11 Jun 2024 18:16:44 +0300 Subject: [PATCH 09/47] prettier --- scripts/bcs.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/bcs.js b/scripts/bcs.js index a5eab8f4..a3148e5a 100644 --- a/scripts/bcs.js +++ b/scripts/bcs.js @@ -1,4 +1,5 @@ const { bcs } = require('@mysten/sui.js/bcs'); + function getAxelarStructs() { const Bytes32 = bcs.struct('Bytes32', { bytes: bcs.Address, From 8ba2aa9baaf6183829036200928bbfbe337b8bac Mon Sep 17 00:00:00 2001 From: Foivos Date: Wed, 12 Jun 2024 14:47:11 +0300 Subject: [PATCH 10/47] adding publish options in TxBuilder --- move/axelar_gateway/Move.lock | 2 +- move/axelar_gateway/Move.toml | 4 +-- scripts/tx-builder.js | 60 ++++++++++++++++++++++++++++++++++- 3 files changed, 62 insertions(+), 4 deletions(-) diff --git a/move/axelar_gateway/Move.lock b/move/axelar_gateway/Move.lock index 64806bad..1242c5d3 100644 --- a/move/axelar_gateway/Move.lock +++ b/move/axelar_gateway/Move.lock @@ -2,7 +2,7 @@ [move] version = 2 -manifest_digest = "CA371CB4070828EC012CA6D0738C0BDB1C6F855975C764AB0D480873887AB680" +manifest_digest = "10303CE6C59BAA2CE814E3D11BACC8CB24BE0F8D66753B02190E291CA40F0D39" deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082" dependencies = [ { name = "Sui" }, diff --git a/move/axelar_gateway/Move.toml b/move/axelar_gateway/Move.toml index ee14cdc7..f1edb35d 100644 --- a/move/axelar_gateway/Move.toml +++ b/move/axelar_gateway/Move.toml @@ -1,12 +1,12 @@ [package] name = "AxelarGateway" version = "0.1.0" -published-at = "0xcd391ade5ab55a218f8988df8f3aa38ec019651c217244f7f689616c87d8c289" +published-at = "0x8f0ff604b968c87932c2fb8defbe5ad9f5af095d7df12d687f4b25321800faa8" edition = "2024.beta" [dependencies] Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet-v1.25.3" } [addresses] -axelar_gateway = "0xcd391ade5ab55a218f8988df8f3aa38ec019651c217244f7f689616c87d8c289" +axelar_gateway = "0x8f0ff604b968c87932c2fb8defbe5ad9f5af095d7df12d687f4b25321800faa8" clock = "0x6" diff --git a/scripts/tx-builder.js b/scripts/tx-builder.js index 34d3fb87..aa535aa2 100644 --- a/scripts/tx-builder.js +++ b/scripts/tx-builder.js @@ -3,6 +3,8 @@ const { bcs } = require('@mysten/bcs'); const { utils: { arrayify, hexlify }, } = require('ethers'); +const tmp = require('tmp'); +const path = require('path'); const objectCache = {}; @@ -155,7 +157,7 @@ class TxBuilder { this.tx = new TransactionBlock(); } - async moveCall(target, args, typeArguments = []) { + async moveCall({target, args, typeArguments = []}) { // If target is string, convert to object that `getNormalizedMoveFunction` accepts. if (typeof target === 'string') { const first = target.indexOf(':'); @@ -188,6 +190,62 @@ class TxBuilder { }); } + async publishPackage(packageName, moveDir = `${__dirname}/../move`) { + updateMoveToml(packageName, '0x0', moveDir); + + tmp.setGracefulCleanup(); + + const tmpobj = tmp.dirSync({ unsafeCleanup: true }); + + const { modules, dependencies } = JSON.parse( + execSync( + `sui move build --dump-bytecode-as-base64 --path ${path.join(moveDir, packageName)} --install-dir ${ + tmpobj.name + }`, + { + encoding: 'utf-8', + stdio: 'pipe', // silent the output + }, + ), + ); + + + const tx = new TransactionBlock(); + return tx.publish({ + modules, + dependencies, + }); + } + + async publishPackageAndTransferCap(packageName, to, moveDir = `${__dirname}/../move`) { + updateMoveToml(packageName, '0x0', moveDir); + + tmp.setGracefulCleanup(); + + const tmpobj = tmp.dirSync({ unsafeCleanup: true }); + + const { modules, dependencies } = JSON.parse( + execSync( + `sui move build --dump-bytecode-as-base64 --path ${path.join(moveDir, packageName)} --install-dir ${ + tmpobj.name + }`, + { + encoding: 'utf-8', + stdio: 'pipe', // silent the output + }, + ), + ); + + + const tx = new TransactionBlock(); + const cap = tx.publish({ + modules, + dependencies, + }); + + tx.transferObjects([cap], to); + } + async signAndExecute(keypair, options) { const result = await this.client.signAndExecuteTransactionBlock({ transactionBlock: this.tx, From 17600af7a670cf5cf867d3a2c1a853efe55fdb38 Mon Sep 17 00:00:00 2001 From: Foivos Date: Fri, 14 Jun 2024 14:28:40 +0300 Subject: [PATCH 11/47] fixed some issues after testing --- move/axelar_gateway/Move.toml | 4 +- move/test/Move.lock | 2 +- move/test/Move.toml | 4 +- scripts/bcs.js | 8 +-- scripts/tx-builder.js | 95 +++++++++++++++++------------------ 5 files changed, 54 insertions(+), 59 deletions(-) diff --git a/move/axelar_gateway/Move.toml b/move/axelar_gateway/Move.toml index f1edb35d..1e6bf58a 100644 --- a/move/axelar_gateway/Move.toml +++ b/move/axelar_gateway/Move.toml @@ -1,12 +1,12 @@ [package] name = "AxelarGateway" version = "0.1.0" -published-at = "0x8f0ff604b968c87932c2fb8defbe5ad9f5af095d7df12d687f4b25321800faa8" +published-at = "0xdd3b165835ec3d510016f8492519feb74a631f235f0126f44fec079c8aa81186" edition = "2024.beta" [dependencies] Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet-v1.25.3" } [addresses] -axelar_gateway = "0x8f0ff604b968c87932c2fb8defbe5ad9f5af095d7df12d687f4b25321800faa8" +axelar_gateway = "0xdd3b165835ec3d510016f8492519feb74a631f235f0126f44fec079c8aa81186" clock = "0x6" diff --git a/move/test/Move.lock b/move/test/Move.lock index ed1e8c31..d5ba2f1e 100644 --- a/move/test/Move.lock +++ b/move/test/Move.lock @@ -2,7 +2,7 @@ [move] version = 2 -manifest_digest = "E39FD071E9EFD0729A4D15C389E9E5EF831FB1E0DB9B2A6E35AFD0DC302863A1" +manifest_digest = "6DF02196C888A850522C2336E4F8FF37DA00BCBB2240DEBF2500B46D2358E034" deps_digest = "3C4103934B1E040BB6B23F1D610B4EF9F2F1166A50A104EADCF77467C004C600" dependencies = [ { name = "AxelarGateway" }, diff --git a/move/test/Move.toml b/move/test/Move.toml index cfe2b83d..2beb8b56 100644 --- a/move/test/Move.toml +++ b/move/test/Move.toml @@ -1,7 +1,7 @@ [package] name = "Test" version = "0.1.0" -published-at = "0x5de4d52cd17c6e0483598bebb3243a886edefeb216e5ecc7c578edfeb8a7b4a9" +published-at = "0x3416821971d670acd3a1b8556d2df99bda3cd35c49d581c7ece89aca0137af4d" edition = "2024.beta" [dependencies] @@ -9,4 +9,4 @@ Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-fram AxelarGateway = { local = "../axelar_gateway" } [addresses] -test = "0x5de4d52cd17c6e0483598bebb3243a886edefeb216e5ecc7c578edfeb8a7b4a9" +test = "0x3416821971d670acd3a1b8556d2df99bda3cd35c49d581c7ece89aca0137af4d" diff --git a/scripts/bcs.js b/scripts/bcs.js index a3148e5a..6bf6e3a2 100644 --- a/scripts/bcs.js +++ b/scripts/bcs.js @@ -1,9 +1,7 @@ const { bcs } = require('@mysten/sui.js/bcs'); function getAxelarStructs() { - const Bytes32 = bcs.struct('Bytes32', { - bytes: bcs.Address, - }); + const Bytes32 = bcs.Address; const Message = bcs.struct('Message', { source_chain: bcs.String, @@ -24,9 +22,7 @@ function getAxelarStructs() { nonce: Bytes32, }); - const Signature = bcs.struct('Signature', { - bytes: bcs.vector(bcs.U8), - }); + const Signature = bcs.vector(bcs.U8); const Proof = bcs.struct('Proof', { signers: WeightedSigners, diff --git a/scripts/tx-builder.js b/scripts/tx-builder.js index aa535aa2..98ca787f 100644 --- a/scripts/tx-builder.js +++ b/scripts/tx-builder.js @@ -5,6 +5,8 @@ const { } = require('ethers'); const tmp = require('tmp'); const path = require('path'); +const { updateMoveToml } = require('./utils'); +const { execSync } = require('child_process'); const objectCache = {}; @@ -24,7 +26,9 @@ function getObject(tx, object) { const cached = objectCache[object]; if (cached) { - return tx.object(cached); + // TODO: figure out how to load the object version/digest into the TransactionBlock because it seems impossible for non gas payment objects + const txObject = tx.object(object); + return txObject; } return tx.object(object); @@ -134,10 +138,15 @@ function serialize(tx, type, arg) { } function isTxContext(parameter) { - parameter = parameter.MutableReference; - if (!parameter) return false; - parameter = parameter.Struct; - if (!parameter) return false; + if(parameter.MutableReference) { + parameter = parameter.MutableReference.Struct; + if (!parameter) return false; + } else if (parameter.Reference) { + parameter = parameter.Reference.Struct; + if (!parameter) return false; + } else { + return false; + } return parameter.address === '0x2' && parameter.module === 'tx_context' && parameter.name === 'TxContext'; } @@ -157,7 +166,8 @@ class TxBuilder { this.tx = new TransactionBlock(); } - async moveCall({target, args, typeArguments = []}) { + async moveCall(moveCallInfo) { + let target = moveCallInfo.target; // If target is string, convert to object that `getNormalizedMoveFunction` accepts. if (typeof target === 'string') { const first = target.indexOf(':'); @@ -176,17 +186,17 @@ class TxBuilder { let length = moveFn.parameters.length; if (isTxContext(moveFn.parameters[length - 1])) length = length - 1; - if (length !== args.length) + if (length !== moveCallInfo.arguments.length) throw new Error( - `Function ${target.package}::${target.module}::${target.function} takes ${moveFn.parameters.length} arguments but given ${args.length}`, + `Function ${target.package}::${target.module}::${target.function} takes ${moveFn.parameters.length} arguments but given ${moveCallInfo.arguments.length}`, ); - const convertedArgs = args.map((arg, index) => serialize(this.tx, moveFn.parameters[index], arg)); + const convertedArgs = moveCallInfo.arguments.map((arg, index) => serialize(this.tx, moveFn.parameters[index], arg)); return this.tx.moveCall({ target: `${target.package}::${target.module}::${target.function}`, arguments: convertedArgs, - typeArguments, + typeArguments: moveCallInfo.typeArguments, }); } @@ -198,56 +208,26 @@ class TxBuilder { const tmpobj = tmp.dirSync({ unsafeCleanup: true }); const { modules, dependencies } = JSON.parse( - execSync( - `sui move build --dump-bytecode-as-base64 --path ${path.join(moveDir, packageName)} --install-dir ${ - tmpobj.name - }`, - { - encoding: 'utf-8', - stdio: 'pipe', // silent the output - }, - ), + execSync(`sui move build --dump-bytecode-as-base64 --path ${path.join(moveDir, packageName)} --install-dir ${tmpobj.name}`, { + encoding: 'utf-8', + stdio: 'pipe', // silent the output + }), ); - - const tx = new TransactionBlock(); - return tx.publish({ + return this.tx.publish({ modules, dependencies, }); } async publishPackageAndTransferCap(packageName, to, moveDir = `${__dirname}/../move`) { - updateMoveToml(packageName, '0x0', moveDir); - - tmp.setGracefulCleanup(); - - const tmpobj = tmp.dirSync({ unsafeCleanup: true }); + const cap = await this.publishPackage(packageName, moveDir); - const { modules, dependencies } = JSON.parse( - execSync( - `sui move build --dump-bytecode-as-base64 --path ${path.join(moveDir, packageName)} --install-dir ${ - tmpobj.name - }`, - { - encoding: 'utf-8', - stdio: 'pipe', // silent the output - }, - ), - ); - - - const tx = new TransactionBlock(); - const cap = tx.publish({ - modules, - dependencies, - }); - - tx.transferObjects([cap], to); + this.tx.transferObjects([cap], to); } async signAndExecute(keypair, options) { - const result = await this.client.signAndExecuteTransactionBlock({ + let result = await this.client.signAndExecuteTransactionBlock({ transactionBlock: this.tx, signer: keypair, options: { @@ -257,6 +237,25 @@ class TxBuilder { ...options, }, }); + if(!result.confirmedLocalExecution) { + while(true) { + try { + result = await this.client.getTransactionBlock({ + digest: result.digest, + options: { + showEffects: true, + showObjectChanges: true, + showContent: true, + ...options, + } + }); + break; + } catch(e) { + console.log(e); + await new Promise((resolve) => setTimeout(resolve, 1000)); + } + } + } updateCache(result.objectChanges); return result; } From fc0acac192a45997089e9c4bedd570767d04e069 Mon Sep 17 00:00:00 2001 From: Foivos Date: Fri, 14 Jun 2024 16:45:42 +0300 Subject: [PATCH 12/47] add ts of relevant utils --- .gitignore | 3 + package-lock.json | 4 +- package.json | 9 +- src/bcs.ts | 118 ++++++++++++++++++++ src/tx-builder.ts | 279 ++++++++++++++++++++++++++++++++++++++++++++++ src/utils.ts | 89 +++++++++++++++ tsconfig.json | 34 ++++++ 7 files changed, 531 insertions(+), 5 deletions(-) create mode 100644 src/bcs.ts create mode 100644 src/tx-builder.ts create mode 100644 src/utils.ts create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore index 3ddb2f7c..dc19c0ef 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,6 @@ target/ # MSVC Windows builds of rustc generate these, which store debugging information *.pdb + +# dist +dist \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 83a65f0c..c552853c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,8 @@ "ethers": "^5.0.0", "fs": "^0.0.1-security", "secp256k1": "^5.0.0", - "tmp": "^0.2.1" + "tmp": "^0.2.1", + "typescript": "^5.3.3" }, "devDependencies": { "@ianvs/prettier-plugin-sort-imports": "^4.2.1", @@ -5011,7 +5012,6 @@ "version": "5.4.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/package.json b/package.json index e18a409f..00c0bb93 100644 --- a/package.json +++ b/package.json @@ -5,13 +5,15 @@ "type": "git", "url": "https://github.com/axelarnetwork/axelar-cgp-sui" }, - "main": "index.js", + "main": "dist", "scripts": { "build": "./scripts/run.sh build", "test": "./scripts/run.sh test", "coverage": "./scripts/coverage.sh", "lint": "eslint --fix './scripts/*.js'", - "prettier": "prettier --write './scripts/*.js'" + "prettier": "prettier --write './scripts/*.js'", + "compile": "tsc", + "postinstall": "npx run compile" }, "keywords": [ "axelar", @@ -29,7 +31,8 @@ "ethers": "^5.0.0", "fs": "^0.0.1-security", "secp256k1": "^5.0.0", - "tmp": "^0.2.1" + "tmp": "^0.2.1", + "typescript": "^5.3.3" }, "devDependencies": { "@ianvs/prettier-plugin-sort-imports": "^4.2.1", diff --git a/src/bcs.ts b/src/bcs.ts new file mode 100644 index 00000000..a2ed68f0 --- /dev/null +++ b/src/bcs.ts @@ -0,0 +1,118 @@ +import { bcs } from '@mysten/sui.js/bcs'; + +function getAxelarStructs() { + const Bytes32 = bcs.Address; + + const Message = bcs.struct('Message', { + source_chain: bcs.String, + message_id: bcs.String, + source_address: bcs.String, + destination_id: bcs.Address, + payload_hash: Bytes32, + }); + + const WeightedSigner = bcs.struct('WeightedSigner', { + pubkey: bcs.vector(bcs.U8), + weight: bcs.U128, + }); + + const WeightedSigners = bcs.struct('WeightedSigners', { + signers: bcs.vector(WeightedSigner), + threshold: bcs.U128, + nonce: Bytes32, + }); + + const Signature = bcs.vector(bcs.U8); + + const Proof = bcs.struct('Proof', { + signers: WeightedSigners, + signatures: bcs.vector(Signature), + }); + + const MessageToSign = bcs.struct('MessageToSign', { + domain_separator: Bytes32, + signers_hash: Bytes32, + data_hash: Bytes32, + }); + + const Function = bcs.struct('Function', { + package_id: bcs.Address, + module_name: bcs.String, + name: bcs.String, + }); + + /// Arguments are prefixed with: + /// - 0 for objects followed by exactly 32 bytes that cointain the object id + /// - 1 for pures followed by the bcs encoded form of the pure + /// - 2 for the call contract object, followed by nothing (to be passed into the target function) + /// - 3 for the payload of the contract call (to be passed into the intermediate function) + /// - 4 for an argument returned from a previous move call, followed by a u8 specified which call to get the return of (0 for the first transaction AFTER the one that gets ApprovedMessage out), and then another u8 specifying which argument to input. + const MoveCall = bcs.struct('MoveCall', { + function: Function, + arguments: bcs.vector(bcs.vector(bcs.U8)), + type_arguments: bcs.vector(bcs.String), + }); + + const Transaction = bcs.struct('Transaction', { + is_final: bcs.Bool, + move_calls: bcs.vector(MoveCall), + }); + + const EncodedMessage = bcs.struct('EncodedMessage', { + message_type: bcs.U8, + data: bcs.vector(bcs.U8), + }); + + return { + Bytes32, + Message, + WeightedSigner, + WeightedSigners, + Signature, + Proof, + MessageToSign, + Function, + MoveCall, + Transaction, + EncodedMessage, + }; +} + +function getSquidStructs() { + const DeepbookV2SwapData = bcs.struct('DeepbookV2SwapData', { + swap_type: bcs.U8, + pool_id: bcs.Address, + has_base: bcs.Bool, + min_output: bcs.U64, + base_type: bcs.String, + quote_type: bcs.String, + lot_size: bcs.U64, + should_sweep: bcs.Bool, + }); + + const SuiTransferSwapData = bcs.struct('SuiTransferSwapData', { + swap_type: bcs.U8, + coin_type: bcs.String, + recipient: bcs.Address, + }); + + const ItsTransferSwapData = bcs.struct('ItsTransferSwapData', { + swap_type: bcs.U8, + coin_type: bcs.String, + token_id: bcs.Address, + destination_chain: bcs.String, + destination_address: bcs.vector(bcs.U8), + metadata: bcs.vector(bcs.U8), + }); + + return { + DeepbookV2SwapData, + SuiTransferSwapData, + ItsTransferSwapData, + }; +} + +export const bcsStructs = { + axelarStructs: getAxelarStructs(), + squidStructs: getSquidStructs(), +}; diff --git a/src/tx-builder.ts b/src/tx-builder.ts new file mode 100644 index 00000000..edbbe174 --- /dev/null +++ b/src/tx-builder.ts @@ -0,0 +1,279 @@ +import { TransactionArgument, TransactionBlock, TransactionObjectInput } from '@mysten/sui.js/transactions'; +import { SuiObjectChange, SuiMoveNormalizedType, SuiClient, SuiTransactionBlockResponseOptions } from '@mysten/sui.js/client'; +import { bcs, BcsType, SerializedBcs } from '@mysten/bcs'; +import ethers from 'ethers'; +const { utils: { arrayify, hexlify }} = ethers; +const tmp = require('tmp'); +import path from 'path'; +import { updateMoveToml } from './utils'; +import { execSync } from 'child_process'; +import { Keypair } from '@mysten/sui.js/dist/cjs/cryptography'; + +const objectCache: {[id in string]: SuiObjectChange} = {}; + +function updateCache(objectChanges: SuiObjectChange[]) { + for (const change of objectChanges) { + if (!(change as any).objectId) continue; + objectCache[(change as any).objectId] = change; + } +} + +function getObject(tx: TransactionBlock, object: TransactionObjectInput) { + if (Array.isArray(object)) { + object = hexlify(object); + } + + if (typeof object === 'string') { + const cached = objectCache[object]; + + if (cached) { + // TODO: figure out how to load the object version/digest into the TransactionBlock because it seems impossible for non gas payment objects + const txObject = tx.object(object); + return txObject; + } + + return tx.object(object); + } + + return object; +} + +function getTypeName(type: SuiMoveNormalizedType): string { + function get(type: {address: string, module: string, name: string, typeArguments: string[]}) { + let name = `${type.address}::${type.module}::${type.name}`; + + if (type.typeArguments.length > 0) { + name += `<${type.typeArguments[0]}`; + + for (let i = 1; i < type.typeArguments.length; i++) { + name += `,${type.typeArguments[i]}`; + } + + name += '>'; + } + + return name; + } + + if ((type as any).Struct) { + return get((type as any).Struct); + } else if ((type as any).Reference) { + return getTypeName((type as any).Reference); + } else if ((type as any).MutableReference) { + return getTypeName((type as any).MutableReference); + } else if ((type as any).Vector) { + return `vector<${getTypeName((type as any).Vector)}>`; + } + + return (type as string).toLowerCase(); +} + +function getNestedStruct(tx: TransactionBlock, type: SuiMoveNormalizedType, arg: TransactionObjectInput) { + let inside = type as any; + + while (inside.Vector) { + inside = inside.Vector; + } + + if (!inside.Struct && !inside.Reference && !inside.MutableReference) { + return null; + } + + if (isString(inside)) { + return null; + } + + if ((type as any).Struct || (type as any).Reference || (type as any).MutableReference) { + return getObject(tx, arg); + } + + if (!(type as any).Vector) return null; + const nested = (arg as any).map((arg: any) => getNestedStruct(tx, (type as any).Vector, arg)); + const typeName = getTypeName((type as any).Vector); + return tx.makeMoveVec({ + type: typeName, + objects: nested, + }); +} + +function serialize(tx: TransactionBlock, type: SuiMoveNormalizedType, arg: TransactionObjectInput ) { + const struct = getNestedStruct(tx, type, arg); + + if (struct) { + return struct; + } + + const vectorU8 = () => + bcs.vector(bcs.u8()).transform({ + input: (val: unknown) => { + if (typeof val === 'string') val = arrayify(val); + return val as Iterable & { length: number; }; + }, + output: (value: number[]) => { + return hexlify(value); + } + }); + + const serializer = (type: SuiMoveNormalizedType): BcsType => { + if (isString(type)) { + return bcs.string() as any; + } + + if (typeof type === 'string') { + return (bcs as any)[(type as string).toLowerCase()](); + } else if ((type as any).Vector) { + if ((type as any).Vector === 'U8') { + return vectorU8() as any; + } + + return bcs.vector(serializer((type as any).Vector) as BcsType) as any; + } + + throw new Error(`Type ${JSON.stringify(type)} cannot be serialized`); + }; + + return tx.pure(serializer(type).serialize(arg).toBytes()); +} + +function isTxContext(parameter: SuiMoveNormalizedType) { + let inside = parameter as any; + if(inside.MutableReference) { + inside = inside.MutableReference.Struct; + if (!inside) return false; + } else if (inside.Reference) { + inside = inside.Reference.Struct; + if (!inside) return false; + } else { + return false; + } + return inside.address === '0x2' && inside.module === 'tx_context' && inside.name === 'TxContext'; +} + +function isString(parameter: SuiMoveNormalizedType) { + let asAny = parameter as any; + if (asAny.MutableReference) parameter = asAny.MutableReference; + if (asAny.Reference) asAny = asAny.Reference; + asAny = asAny.Struct; + if (!asAny) return false; + const isAsciiString = asAny.address === '0x1' && asAny.module === 'ascii' && asAny.name === 'String'; + const isStringString = asAny.address === '0x1' && asAny.module === 'string' && asAny.name === 'String'; + return isAsciiString || isStringString; +} + +class TxBuilder { + client: SuiClient; + tx: TransactionBlock; + constructor(client: SuiClient) { + this.client = client; + this.tx = new TransactionBlock(); + } + + async moveCall(moveCallInfo: { + arguments?: TransactionObjectInput[]; + typeArguments?: string[]; + target: `${string}::${string}::${string}` | {package: string, module: string, function: string}; + }) { + let target = moveCallInfo.target; + // If target is string, convert to object that `getNormalizedMoveFunction` accepts. + if (typeof target === 'string') { + const first = target.indexOf(':'); + const last = target.indexOf(':', first + 2); + const packageId = target.slice(0, first); + const module = target.slice(first + 2, last); + const functionName = target.slice(last + 2); + target = { + package: packageId, + module, + function: functionName, + }; + } + + const moveFn = await this.client.getNormalizedMoveFunction(target); + + let length = moveFn.parameters.length; + if (isTxContext(moveFn.parameters[length - 1])) length = length - 1; + if(!moveCallInfo.arguments) moveCallInfo.arguments = []; + if (length !== moveCallInfo.arguments.length) + throw new Error( + `Function ${target.package}::${target.module}::${target.function} takes ${moveFn.parameters.length} arguments but given ${moveCallInfo.arguments.length}`, + ); + + const convertedArgs = moveCallInfo.arguments.map((arg, index) => serialize(this.tx, moveFn.parameters[index], arg)); + + return this.tx.moveCall({ + target: `${target.package}::${target.module}::${target.function}`, + arguments: convertedArgs as any, + typeArguments: moveCallInfo.typeArguments, + }); + } + + async publishPackage(packageName: string, moveDir: string = `${__dirname}/../move`) { + updateMoveToml(packageName, '0x0', moveDir); + + tmp.setGracefulCleanup(); + + const tmpobj = tmp.dirSync({ unsafeCleanup: true }); + + const { modules, dependencies } = JSON.parse( + execSync(`sui move build --dump-bytecode-as-base64 --path ${path.join(moveDir, packageName)} --install-dir ${tmpobj.name}`, { + encoding: 'utf-8', + stdio: 'pipe', // silent the output + }), + ); + + return this.tx.publish({ + modules, + dependencies, + }); + } + + async publishPackageAndTransferCap(packageName: string, to: string, moveDir = `${__dirname}/../move`) { + const cap = await this.publishPackage(packageName, moveDir); + + this.tx.transferObjects([cap], to); + } + + async signAndExecute(keypair: Keypair, options: SuiTransactionBlockResponseOptions) { + let result = await this.client.signAndExecuteTransactionBlock({ + transactionBlock: this.tx, + signer: keypair, + options: { + showEffects: true, + showObjectChanges: true, + ...options, + }, + }); + if(!result.confirmedLocalExecution) { + while(true) { + try { + result = await this.client.getTransactionBlock({ + digest: result.digest, + options: { + showEffects: true, + showObjectChanges: true, + ...options, + } + }); + break; + } catch(e) { + console.log(e); + await new Promise((resolve) => setTimeout(resolve, 1000)); + } + } + } + updateCache(result.objectChanges as SuiObjectChange[]); + return result; + } + + async devInspect(sender: string) { + const result = await this.client.devInspectTransactionBlock({ + transactionBlock: this.tx, + sender, + }); + return result; + } +} + +module.exports = { + TxBuilder, +}; diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 00000000..73c371dc --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,89 @@ +import fs from 'fs'; +import { getFullnodeUrl } from '@mysten/sui.js/client'; + +export function getModuleNameFromSymbol(symbol: string) { + function isNumber(char: string) { + return char >= '0' && char <= '9'; + } + + function isLowercase(char: string) { + return char >= 'a' && char <= 'z'; + } + + function isUppercase(char: string) { + return char >= 'A' && char <= 'Z'; + } + + let i = 0; + const length = symbol.length; + let moduleName = ''; + + while (isNumber(symbol[i])) { + i++; + } + + while (i < length) { + const char = symbol[i]; + + if (isLowercase(char) || isNumber(char)) { + moduleName += char; + } else if (isUppercase(char)) { + moduleName += char.toLowerCase(); + } else if (char === '_' || char === ' ') { + moduleName += '_'; + } + + i++; + } + + return moduleName; +} + +export function updateMoveToml(packageName: string, packageId: string, moveDir: string = `${__dirname}/../move`) { + const path = `${moveDir}/${packageName}/Move.toml`; + + let toml = fs.readFileSync(path, 'utf8'); + + const lines = toml.split('\n'); + + const versionLineIndex = lines.findIndex((line: string) => line.slice(0, 7) === 'version'); + + if (!(lines[versionLineIndex + 1].slice(0, 12) === 'published-at')) { + lines.splice(versionLineIndex + 1, 0, ''); + } + + lines[versionLineIndex + 1] = `published-at = "${packageId}"`; + + const addressesIndex = lines.findIndex((line: string) => line.slice(0, 11) === '[addresses]'); + + for (let i = addressesIndex + 1; i < lines.length; i++) { + const line = lines[i]; + const eqIndex = line.indexOf('='); + + if ( + eqIndex < 0 || + line.slice(0, packageName.length) !== packageName || + line.slice(packageName.length, eqIndex) !== Array(eqIndex - packageName.length + 1).join(' ') + ) { + continue; + } + + lines[i] = line.slice(0, eqIndex + 1) + ` "${packageId}"`; + } + + toml = lines.join('\n'); + + fs.writeFileSync(path, toml); +} + +export function parseEnv(arg: string) { + switch (arg?.toLowerCase()) { + case 'localnet': + case 'devnet': + case 'testnet': + case 'mainnet': + return { alias: arg, url: getFullnodeUrl(arg as "localnet" | "devnet" | "testnet" | "mainnet") }; + default: + return JSON.parse(arg); + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..4545c07e --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,34 @@ +{ + "compilerOptions": { + /* Language and Environment */ + "target": "es6" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + "lib": ["es2020", "dom"] /* Specify a set of bundled library declaration files that describe the target runtime environment. */, + + /* Modules */ + "module": "CommonJS" /* Specify what module code is generated. */, + + "resolveJsonModule": true, + /* Emit */ + "declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */, + "declarationMap": true /* Create sourcemaps for d.ts files. */, + "sourceMap": true /* Create source map files for emitted JavaScript files. */, + "rootDirs": ["./src", "src/__test__"] /* Specify the root folder within your source files. */, + "outDir": "dist" /* Specify an output folder for all emitted files. */, + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + "strictNullChecks": true /* When type checking, take into account `null` and `undefined`. */, + + /* Completeness */ + "skipDefaultLibCheck": true /* Skip type checking .d.ts files that are included with TypeScript. */, + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + }, + "include": ["src"], + "exclude": ["node_modules", "dist", "src/__tests__/"] +} From 0cc49ca6d99b010a1ecdbc0bf49758970e61da35 Mon Sep 17 00:00:00 2001 From: Foivos Date: Mon, 17 Jun 2024 15:20:32 +0300 Subject: [PATCH 13/47] use npx tsc instead --- package-lock.json | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index c552853c..263cd923 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,7 @@ "": { "name": "@axelar-network/axelar-cgp-sui", "version": "0.1.0", + "hasInstallScript": true, "license": "MIT", "dependencies": { "@cosmjs/cosmwasm-stargate": "^0.32.2", diff --git a/package.json b/package.json index 00c0bb93..0a0f1072 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "coverage": "./scripts/coverage.sh", "lint": "eslint --fix './scripts/*.js'", "prettier": "prettier --write './scripts/*.js'", - "compile": "tsc", + "compile": "npx tsc", "postinstall": "npx run compile" }, "keywords": [ From 6c387bf50a7a4609b973f33efb029f7aa2291c4a Mon Sep 17 00:00:00 2001 From: Foivos Date: Mon, 17 Jun 2024 15:22:08 +0300 Subject: [PATCH 14/47] run compile properly --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0a0f1072..9ab24396 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "lint": "eslint --fix './scripts/*.js'", "prettier": "prettier --write './scripts/*.js'", "compile": "npx tsc", - "postinstall": "npx run compile" + "postinstall": "npm run compile" }, "keywords": [ "axelar", From 372514bcb1704762b622d5f15723b77a740000ac Mon Sep 17 00:00:00 2001 From: Foivos Date: Mon, 17 Jun 2024 15:26:18 +0300 Subject: [PATCH 15/47] remove previous scripts --- scripts/bcs.js | 118 ----- scripts/coverage.sh | 59 --- scripts/gateway.js | 257 ---------- scripts/governance.js | 66 --- scripts/its/discovery.js | 65 --- scripts/its/interchain_token.move | 20 - scripts/its/publish-interchain-token.js | 99 ---- scripts/its/receive-token.js | 103 ---- scripts/its/register-token.js | 140 ------ scripts/its/send-token.js | 125 ----- scripts/its/set-trusted-address.js | 110 ----- scripts/publish-all.js | 73 --- scripts/publish-package.js | 84 ---- scripts/run.sh | 20 - scripts/squid/discovery.js | 57 --- scripts/squid/squid.js | 586 ----------------------- scripts/test-receive-call.js | 190 -------- scripts/test-send-call.js | 60 --- scripts/test-transfer-operatorship.js | 25 - scripts/transfer-genesis-operatorship.js | 27 -- scripts/tx-builder.js | 281 ----------- scripts/utils.js | 110 ----- 22 files changed, 2675 deletions(-) delete mode 100644 scripts/bcs.js delete mode 100755 scripts/coverage.sh delete mode 100644 scripts/gateway.js delete mode 100644 scripts/governance.js delete mode 100644 scripts/its/discovery.js delete mode 100644 scripts/its/interchain_token.move delete mode 100644 scripts/its/publish-interchain-token.js delete mode 100644 scripts/its/receive-token.js delete mode 100644 scripts/its/register-token.js delete mode 100644 scripts/its/send-token.js delete mode 100644 scripts/its/set-trusted-address.js delete mode 100644 scripts/publish-all.js delete mode 100644 scripts/publish-package.js delete mode 100755 scripts/run.sh delete mode 100644 scripts/squid/discovery.js delete mode 100644 scripts/squid/squid.js delete mode 100644 scripts/test-receive-call.js delete mode 100644 scripts/test-send-call.js delete mode 100644 scripts/test-transfer-operatorship.js delete mode 100644 scripts/transfer-genesis-operatorship.js delete mode 100644 scripts/tx-builder.js delete mode 100644 scripts/utils.js diff --git a/scripts/bcs.js b/scripts/bcs.js deleted file mode 100644 index 6bf6e3a2..00000000 --- a/scripts/bcs.js +++ /dev/null @@ -1,118 +0,0 @@ -const { bcs } = require('@mysten/sui.js/bcs'); - -function getAxelarStructs() { - const Bytes32 = bcs.Address; - - const Message = bcs.struct('Message', { - source_chain: bcs.String, - message_id: bcs.String, - source_address: bcs.String, - destination_id: bcs.Address, - payload_hash: Bytes32, - }); - - const WeightedSigner = bcs.struct('WeightedSigner', { - pubkey: bcs.vector(bcs.U8), - weight: bcs.U128, - }); - - const WeightedSigners = bcs.struct('WeightedSigners', { - signers: bcs.vector(WeightedSigner), - threshold: bcs.U128, - nonce: Bytes32, - }); - - const Signature = bcs.vector(bcs.U8); - - const Proof = bcs.struct('Proof', { - signers: WeightedSigners, - signatures: bcs.vector(Signature), - }); - - const MessageToSign = bcs.struct('MessageToSign', { - domain_separator: Bytes32, - signers_hash: Bytes32, - data_hash: Bytes32, - }); - - const Function = bcs.struct('Function', { - package_id: bcs.Address, - module_name: bcs.String, - name: bcs.String, - }); - - /// Arguments are prefixed with: - /// - 0 for objects followed by exactly 32 bytes that cointain the object id - /// - 1 for pures followed by the bcs encoded form of the pure - /// - 2 for the call contract object, followed by nothing (to be passed into the target function) - /// - 3 for the payload of the contract call (to be passed into the intermediate function) - /// - 4 for an argument returned from a previous move call, followed by a u8 specified which call to get the return of (0 for the first transaction AFTER the one that gets ApprovedMessage out), and then another u8 specifying which argument to input. - const MoveCall = bcs.struct('MoveCall', { - function: Function, - arguments: bcs.vector(bcs.vector(bcs.U8)), - type_arguments: bcs.vector(bcs.String), - }); - - const Transaction = bcs.struct('Transaction', { - is_final: bcs.Bool, - move_calls: bcs.vector(MoveCall), - }); - - const EncodedMessage = bcs.struct('EncodedMessage', { - message_type: bcs.U8, - data: bcs.vector(bcs.U8), - }); - - return { - Bytes32, - Message, - WeightedSigner, - WeightedSigners, - Signature, - Proof, - MessageToSign, - Function, - MoveCall, - Transaction, - EncodedMessage, - }; -} - -function getSquidStructs() { - const DeepbookV2SwapData = bcs.struct('DeepbookV2SwapData', { - swap_type: bcs.U8, - pool_id: bcs.Address, - has_base: bcs.Bool, - min_output: bcs.U64, - base_type: bcs.String, - quote_type: bcs.String, - lot_size: bcs.U64, - should_sweep: bcs.Bool, - }); - - const SuiTransferSwapData = bcs.struct('SuiTransferSwapData', { - swap_type: bcs.U8, - coin_type: bcs.String, - recipient: bcs.Address, - }); - - const ItsTransferSwapData = bcs.struct('ItsTransferSwapData', { - swap_type: bcs.U8, - coin_type: bcs.String, - token_id: bcs.Address, - destination_chain: bcs.String, - destination_address: bcs.vector(bcs.U8), - metadata: bcs.vector(bcs.U8), - }); - - return { - DeepbookV2SwapData, - SuiTransferSwapData, - ItsTransferSwapData, - }; -} - -module.exports = { - axelarStructs: getAxelarStructs(), - squidStructs: getSquidStructs(), -}; diff --git a/scripts/coverage.sh b/scripts/coverage.sh deleted file mode 100755 index 1b437ab1..00000000 --- a/scripts/coverage.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/sh - -export SUI=sui-debug - -# Check if sui-debug is available -if ! which "$SUI" >/dev/null 2>&1; then - echo "sui-debug not found. Setting SUI to ./sui/target/debug/sui." - - # Default to a local Sui build - export SUI="./sui/target/debug/sui" - - # Check if the file exists, install it otherwise - if [ ! -f "$SUI" ]; then - echo "Warning: $SUI not found. Installing sui-debug from scratch." - - git clone https://github.com/MystenLabs/sui.git - ( cd sui && cargo build ) - ./sui/target/debug/sui version - fi -fi - -for module in ./move/*/; do - "$SUI" move test --path "$module" --coverage & -done - -wait - -found=0 - -for module in ./move/*/; do - echo "Generating coverage info for package ${module}" - - if [ ! -f "${module}/.coverage_map.mvcov" ]; then - echo "\n NO tests found for module ${module}. Skipped.\n" >> .coverage.info - echo "\n NO tests found for module ${module}. Skipped.\n" >> .coverage.extended.info - continue - fi - - found=1 - - echo "Coverage report for module ${module}\n" >> .coverage.info - echo "Coverage report for module ${module}\n" >> .coverage.extended.info - - "$SUI" move coverage summary --path "${module}" >> .coverage.info - "$SUI" move coverage summary --summarize-functions --path "${module}" >> .coverage.extended.info - - echo "" >> .coverage.info - echo "" >> .coverage.extended.info - - # Display source code with coverage info - # find "$d/sources" -type f -name '*.move' | while IFS= read -r f; do - # "$SUI" move coverage source --path "$d" --module "$(basename "$f" .move)" - # done -done - -if [ $found -eq 0 ]; then - echo "No coverage info found. Coverage failed." - exit 1 -fi diff --git a/scripts/gateway.js b/scripts/gateway.js deleted file mode 100644 index ae54fd74..00000000 --- a/scripts/gateway.js +++ /dev/null @@ -1,257 +0,0 @@ -require('dotenv').config(); -const { TransactionBlock } = require('@mysten/sui.js/transactions'); -const { BCS, fromHEX, getSuiMoveConfig } = require('@mysten/bcs'); -const { CosmWasmClient } = require('@cosmjs/cosmwasm-stargate'); -const { - utils: { keccak256 }, -} = require('ethers'); -const secp256k1 = require('secp256k1'); - -function hashMessage(data) { - // sorry for putting it here... - const messagePrefix = new Uint8Array(Buffer.from('\x19Sui Signed Message:\n', 'ascii')); - const hashed = new Uint8Array(messagePrefix.length + data.length); - hashed.set(messagePrefix); - hashed.set(data, messagePrefix.length); - - return keccak256(hashed); -} - -function getBcsForGateway() { - const bcs = new BCS(getSuiMoveConfig()); - - // input argument for the tx - bcs.registerStructType('Input', { - data: 'vector', - proof: 'vector', - }); - - bcs.registerStructType('Proof', { - // operators is a 33 byte / for now at least - operators: 'vector>', - weights: 'vector', - threshold: 'u128', - signatures: 'vector>', - }); - - // internals of the message - bcs.registerStructType('AxelarMessage', { - chain_id: 'u64', - command_ids: 'vector
', - commands: 'vector', - params: 'vector>', - }); - - // internals of the message - bcs.registerStructType('TransferOperatorshipMessage', { - operators: 'vector>', - weights: 'vector', - threshold: 'u128', - }); - bcs.registerStructType('GenericMessage', { - source_chain: 'string', - source_address: 'string', - target_id: 'address', - payload_hash: 'address', - }); - - return bcs; -} - -function getOperators(axelarInfo) { - if (!axelarInfo.activeOperators) { - return { - privKeys: [], - weights: [], - threshold: 0, - }; - } - - return axelarInfo.activeOperators; -} - -function getRandomOperators(n = 5) { - let privKeys = []; - - for (let i = 0; i < n; i++) { - privKeys.push(keccak256(Math.floor(Math.random() * 10000000)).slice(2)); - } - - let pubKeys = privKeys.map((privKey) => secp256k1.publicKeyCreate(Buffer.from(privKey, 'hex'))); - const indices = Array.from(pubKeys.keys()); - const pubKeyLength = 33; - - indices.sort((a, b) => { - for (let i = 0; i < pubKeyLength; i++) { - const aByte = pubKeys[a][i]; - const bByte = pubKeys[b][i]; - if (aByte !== bByte) return aByte - bByte; - } - - return 0; - }); - pubKeys = indices.map((i) => pubKeys[i]); - privKeys = indices.map((i) => privKeys[i]); - const weights = privKeys.map((privKey) => 3); - const threshold = privKeys.length * 2; - - return { - privKeys, - pubKeys, - weights, - threshold, - }; -} - -function getInputForMessage(info, message) { - const operators = getOperators(info); - // get the public key in a compressed format - const pubKeys = operators.privKeys.map((privKey) => secp256k1.publicKeyCreate(Buffer.from(privKey, 'hex'))); - - const hashed = fromHEX(hashMessage(message)); - const signatures = operators.privKeys.map((privKey) => { - const { signature, recid } = secp256k1.ecdsaSign(hashed, Buffer.from(privKey, 'hex')); - return new Uint8Array([...signature, recid]); - }); - - const bcs = getBcsForGateway(); - const proof = bcs - .ser('Proof', { - operators: pubKeys, - weights: operators.weights, - threshold: operators.threshold, - signatures, - }) - .toBytes(); - - const input = bcs - .ser('Input', { - data: message, - proof, - }) - .toBytes(); - return input; -} - -function approveContractCallInput( - axelarInfo, - sourceChain, - sourceAddress, - destinationAddress, - payloadHash, - commandId = keccak256(new Date().getTime()), -) { - const bcs = getBcsForGateway(); - - const message = bcs - .ser('AxelarMessage', { - chain_id: 1, - command_ids: [commandId], - commands: ['approveContractCall'], - params: [ - bcs - .ser('GenericMessage', { - source_chain: sourceChain, - source_address: sourceAddress, - payload_hash: payloadHash, - target_id: destinationAddress, - }) - .toBytes(), - ], - }) - .toBytes(); - - return getInputForMessage(axelarInfo, message); -} - -function TransferOperatorshipInput(info, newOperators, newWeights, newThreshold, commandId = keccak256(new Date().getTime())) { - const bcs = getBcsForGateway(); - const message = bcs - .ser('AxelarMessage', { - chain_id: 1, - command_ids: [commandId], - commands: ['transferOperatorship'], - params: [ - bcs - .ser('TransferOperatorshipMessage', { - operators: newOperators, - weights: newWeights, - threshold: newThreshold, - }) - .toBytes(), - ], - }) - .toBytes(); - - return getInputForMessage(info, message); -} - -async function approveContractCall(client, keypair, axelarInfo, sourceChain, sourceAddress, destinationAddress, payloadHash) { - const commandId = keccak256(new Date().getTime()); - const input = approveContractCallInput(axelarInfo, sourceChain, sourceAddress, destinationAddress, payloadHash, commandId); - const packageId = axelarInfo.packageId; - const validators = axelarInfo['gateway::Gateway']; - - const tx = new TransactionBlock(); - tx.moveCall({ - target: `${packageId}::gateway::process_commands`, - arguments: [tx.object(validators.objectId), tx.pure(String.fromCharCode(...input))], - typeArguments: [], - }); - await client.signAndExecuteTransactionBlock({ - transactionBlock: tx, - signer: keypair, - options: { - showEffects: true, - showObjectChanges: true, - }, - requestType: 'WaitForLocalExecution', - }); - return commandId; -} - -async function getAmplifierWorkers(rpc, proverAddr) { - const client = await CosmWasmClient.connect(rpc); - const workerSet = await client.queryContractSmart(proverAddr, 'get_worker_set'); - const signers = Object.values(workerSet.signers).sort((a, b) => - a.pub_key.ecdsa.toLowerCase().localeCompare(b.pub_key.ecdsa.toLowerCase()), - ); - - const pubKeys = signers.map((signer) => Buffer.from(signer.pub_key.ecdsa, 'hex')); - const weights = signers.map((signer) => Number(signer.weight)); - const threshold = Number(workerSet.threshold); - - return { pubKeys, weights, threshold }; -} - -async function transferOperatorship(info, client, keypair, newOperators, newWeights, newThreshold) { - const input = TransferOperatorshipInput(info, newOperators, newWeights, newThreshold); - const packageId = info.packageId; - const gateway = info['gateway::Gateway']; - - const tx = new TransactionBlock(); - tx.moveCall({ - target: `${packageId}::gateway::process_commands`, - arguments: [tx.object(gateway.objectId), tx.pure(String.fromCharCode(...input))], - typeArguments: [], - }); - const approveTxn = await client.signAndExecuteTransactionBlock({ - transactionBlock: tx, - signer: keypair, - options: { - showEffects: true, - showObjectChanges: true, - }, - requestType: 'WaitForLocalExecution', - }); - console.log(approveTxn.effects.status); -} - -module.exports = { - approveContractCall, - transferOperatorship, - getRandomOperators, - getAmplifierWorkers, - getBcsForGateway, - hashMessage, -}; diff --git a/scripts/governance.js b/scripts/governance.js deleted file mode 100644 index f52c162d..00000000 --- a/scripts/governance.js +++ /dev/null @@ -1,66 +0,0 @@ -const { TransactionBlock } = require('@mysten/sui.js/transactions'); -const { setConfig, getConfig, getFullObject } = require('./utils'); - -async function initializeGovernance(upgradeCap, client, keypair, env) { - const governanceConfig = getConfig('governance', env.alias); - const packageId = governanceConfig.packageId; - - const tx = new TransactionBlock(); - tx.moveCall({ - target: `${packageId}::governance::new`, - arguments: [ - tx.pure.string('Axelar'), - tx.pure.string('the governance source addresss'), - tx.pure.u256(0), - tx.object(upgradeCap.objectId), - ], - typeArguments: [], - }); - const publishTxn = await client.signAndExecuteTransactionBlock({ - transactionBlock: tx, - signer: keypair, - options: { - showEffects: true, - showObjectChanges: true, - showContent: true, - }, - requestType: 'WaitForLocalExecution', - }); - - const governance = publishTxn.objectChanges.find((obj) => obj.objectType === `${packageId}::governance::Governance`); - - governanceConfig['governance::Governance'] = await getFullObject(governance, client); - setConfig('governance', env.alias, governanceConfig); - - return governance; -} - -async function takeUpgradeCaps(upgradeCaps, client, keypair, env) { - const governanceConfig = getConfig('governance', env.alias); - const packageId = governanceConfig.packageId; - const tx = new TransactionBlock(); - - for (const upgradeCap of upgradeCaps) { - tx.moveCall({ - target: `${packageId}::governance::take_upgrade_cap`, - arguments: [tx.object(governanceConfig['governance::Governance'].objectId), tx.object(upgradeCap.objectId)], - typeArguments: [], - }); - } - - return await client.signAndExecuteTransactionBlock({ - transactionBlock: tx, - signer: keypair, - options: { - showEffects: true, - showObjectChanges: true, - showContent: true, - }, - requestType: 'WaitForLocalExecution', - }); -} - -module.exports = { - initializeGovernance, - takeUpgradeCaps, -}; diff --git a/scripts/its/discovery.js b/scripts/its/discovery.js deleted file mode 100644 index 823aece2..00000000 --- a/scripts/its/discovery.js +++ /dev/null @@ -1,65 +0,0 @@ -require('dotenv').config(); -const { requestSuiFromFaucetV0, getFaucetHost } = require('@mysten/sui.js/faucet'); -const { SuiClient, getFullnodeUrl } = require('@mysten/sui.js/client'); -const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); -const { TransactionBlock } = require('@mysten/sui.js/transactions'); - -const { getConfig } = require('../utils'); - -async function setItsDiscovery(client, keypair, envAlias) { - const axelarInfo = getConfig('axelar', envAlias); - const itsInfo = getConfig('its', envAlias); - const itsPackageId = itsInfo.packageId; - const itsObjectId = itsInfo['its::ITS'].objectId; - const relayerDecovery = axelarInfo['discovery::RelayerDiscovery'].objectId; - - let tx = new TransactionBlock(); - - tx.moveCall({ - target: `${itsPackageId}::discovery::register_transaction`, - arguments: [tx.object(itsObjectId), tx.object(relayerDecovery)], - typeArguments: [], - }); - - await client.signAndExecuteTransactionBlock({ - transactionBlock: tx, - signer: keypair, - options: { - showEffects: true, - showObjectChanges: true, - showContent: true, - }, - requestType: 'WaitForLocalExecution', - }); -} - -module.exports = { - setItsDiscovery, -}; - -if (require.main === module) { - const env = process.argv[2] || 'localnet'; - const chainName = process.argv[3] || 'Ethereum'; - const trustedAddress = process.argv[4] || '0x1234'; - - (async () => { - const privKey = Buffer.from(process.env.SUI_PRIVATE_KEY, 'hex'); - const keypair = Ed25519Keypair.fromSecretKey(privKey); - const address = keypair.getPublicKey().toSuiAddress(); - // create a new SuiClient object pointing to the network you want to use - const client = new SuiClient({ url: getFullnodeUrl(env) }); - - try { - await requestSuiFromFaucetV0({ - // use getFaucetHost to make sure you're using correct faucet address - // you can also just use the address (see Sui Typescript SDK Quick Start for values) - host: getFaucetHost(env), - recipient: address, - }); - } catch (e) { - console.log(e); - } - - await setItsDiscovery(client, keypair, env); - })(); -} diff --git a/scripts/its/interchain_token.move b/scripts/its/interchain_token.move deleted file mode 100644 index 6fbd6a47..00000000 --- a/scripts/its/interchain_token.move +++ /dev/null @@ -1,20 +0,0 @@ -module interchain_token::$module_name { - use sui::coin::{Self}; - use sui::url::{Url}; - - public struct $witness has drop {} - - fun init(witness: $witness, ctx: &mut TxContext) { - let (treasury, metadata) = coin::create_currency<$witness>( - witness, - $decimals, - b"$symbol", - b"$name", - b"", - option::none(), - ctx - ); - transfer::public_transfer(treasury, tx_context::sender(ctx)); - transfer::public_transfer(metadata, tx_context::sender(ctx)); - } -} \ No newline at end of file diff --git a/scripts/its/publish-interchain-token.js b/scripts/its/publish-interchain-token.js deleted file mode 100644 index 99f06c29..00000000 --- a/scripts/its/publish-interchain-token.js +++ /dev/null @@ -1,99 +0,0 @@ -require('dotenv').config(); -const { requestSuiFromFaucetV0, getFaucetHost } = require('@mysten/sui.js/faucet'); -const { SuiClient, getFullnodeUrl } = require('@mysten/sui.js/client'); -const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); -const { TransactionBlock } = require('@mysten/sui.js/transactions'); -const fs = require('fs'); - -const { getModuleNameFromSymbol, getConfig } = require('../utils'); -const { publishPackage } = require('../publish-package'); - -const packagePath = 'interchain_token'; - -async function publishInterchainToken(client, keypair, itsInfo, name, symbol, decimals, skipRegister = false) { - let file = fs.readFileSync(`scripts/its/interchain_token.move`, 'utf8'); - let moduleName = getModuleNameFromSymbol(symbol); - let witness = moduleName.toUpperCase(); - file = file.replaceAll('$module_name', moduleName); - file = file.replaceAll('$witness', witness); - file = file.replaceAll('$name', name); - file = file.replaceAll('$symbol', symbol); - file = file.replaceAll('$decimals', decimals); - fs.writeFileSync(`move/${packagePath}/sources/interchain_token.move`, file); - - const { packageId, publishTxn } = await publishPackage(`../move/${packagePath}`, client, keypair); - - const treasuryCap = publishTxn.objectChanges.find((object) => { - return object.objectType && object.objectType.startsWith('0x2::coin::TreasuryCap'); - }); - const coinMetadata = publishTxn.objectChanges.find((object) => { - return object.objectType && object.objectType.startsWith('0x2::coin::CoinMetadata'); - }); - - coinType = `${packageId}::${moduleName}::${witness}`; - - if (skipRegister) { - return { - coinType, - treasuryCap, - coinMetadata, - }; - } - - const itsPackageId = itsInfo.packageId; - const itsObjectId = itsInfo['its::ITS'].objectId; - - const tx = new TransactionBlock(); - - tx.moveCall({ - target: `${itsPackageId}::service::give_unregistered_coin`, - arguments: [tx.object(itsObjectId), tx.object(treasuryCap.objectId), tx.object(coinMetadata.objectId)], - typeArguments: [`${packageId}::${moduleName}::${witness}`], - }); - - await client.signAndExecuteTransactionBlock({ - transactionBlock: tx, - signer: keypair, - options: { - showEffects: true, - showObjectChanges: true, - showContent: true, - }, - requestType: 'WaitForLocalExecution', - }); - - return { - coinType, - }; -} - -module.exports = { - publishInterchainToken, -}; - -if (require.main === module) { - const symbol = process.argv[2] || 'TT'; - const decimals = process.argv[3] || 6; - const skipRegister = process.argv[4] ? process.argv[4] != 'false' : false; - const env = process.argv[5] || 'localnet'; - - (async () => { - const privKey = Buffer.from(process.env.SUI_PRIVATE_KEY, 'hex'); - const keypair = Ed25519Keypair.fromSecretKey(privKey); - const address = keypair.getPublicKey().toSuiAddress(); - // create a new SuiClient object pointing to the network you want to use - const client = new SuiClient({ url: getFullnodeUrl(env) }); - - try { - await requestSuiFromFaucetV0({ - // use getFaucetHost to make sure you're using correct faucet address - // you can also just use the address (see Sui Typescript SDK Quick Start for values) - host: getFaucetHost(env), - recipient: address, - }); - } catch (e) { - console.log(e); - } - await publishInterchainToken(client, keypair, getConfig('its', env), '', symbol, decimals, skipRegister); - })(); -} diff --git a/scripts/its/receive-token.js b/scripts/its/receive-token.js deleted file mode 100644 index 4f530284..00000000 --- a/scripts/its/receive-token.js +++ /dev/null @@ -1,103 +0,0 @@ -require('dotenv').config(); -const { requestSuiFromFaucetV0, getFaucetHost } = require('@mysten/sui.js/faucet'); -const { SuiClient, getFullnodeUrl } = require('@mysten/sui.js/client'); -const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); -const { TransactionBlock } = require('@mysten/sui.js/transactions'); -const { BCS, getSuiMoveConfig } = require('@mysten/bcs'); - -const { arrayify, defaultAbiCoder } = require('ethers/lib/utils'); -const { registerInterchainToken } = require('./register-token'); -const { receiveCall } = require('../test-receive-call'); -const { getConfig } = require('../utils'); - -async function receiveInterchainToken( - client, - keypair, - axelarInfo, - itsInfo, - tokenId, - sourceChain, - sourceAddress, - destinationAddress, - amount, -) { - const itsPackageId = itsInfo.packageId; - const itsObjectId = itsInfo['its::ITS'].objectId; - const channelId = itsInfo['its::ITS'].channel; - - const selector = 0; - const payload = defaultAbiCoder.encode( - ['uint256', 'bytes32', 'bytes', 'bytes', 'uint256', 'bytes'], - [selector, tokenId, sourceAddress, destinationAddress, amount, '0x'], - ); - - const tx = new TransactionBlock(); - - tx.moveCall({ - target: `${itsPackageId}::its::get_trusted_address`, - arguments: [tx.object(itsObjectId), tx.pure.string(sourceChain)], - }); - - const resp = await client.devInspectTransactionBlock({ - sender: keypair.getPublicKey().toSuiAddress(), - transactionBlock: tx, - }); - - const bcs = new BCS(getSuiMoveConfig()); - - const trustedAddress = bcs.de('string', new Uint8Array(resp.results[0].returnValues[0][0])); - await receiveCall(client, keypair, axelarInfo, sourceChain, trustedAddress, channelId, payload); -} - -if (require.main === module) { - const env = process.argv[2] || 'localnet'; - - const privKey = Buffer.from(process.env.SUI_PRIVATE_KEY, 'hex'); - const keypair = Ed25519Keypair.fromSecretKey(privKey); - const address = keypair.getPublicKey().toSuiAddress(); - // create a new SuiClient object pointing to the network you want to use - const client = new SuiClient({ url: getFullnodeUrl(env) }); - - const sourceChain = process.argv[3] || 'Ethereum'; - const sourceAddress = process.argv[4] || '0x1234'; - const destinationAddress = process.argv[5] || address; - const amount = process.argv[6] || 123467; - const name = process.argv[7] || 'Test Token'; - const symbol = process.argv[8] || 'TT'; - const decimals = process.argv[9] || 6; - - (async () => { - try { - await requestSuiFromFaucetV0({ - // use getFaucetHost to make sure you're using correct faucet address - // you can also just use the address (see Sui Typescript SDK Quick Start for values) - host: getFaucetHost(env), - recipient: address, - }); - } catch (e) { - console.log(e); - } - - const [tokenId, coinType] = await registerInterchainToken(client, keypair, getConfig('its', env), name, symbol, decimals); - - await receiveInterchainToken( - client, - keypair, - getConfig('axelar', env), - getConfig('its', env), - tokenId, - sourceChain, - sourceAddress, - destinationAddress, - amount, - ); - - const coins = await client.getCoins({ - owner: address, - coinType: coinType, - }); - const balance = coins.data[0].balance; - - console.log(balance); - })(); -} diff --git a/scripts/its/register-token.js b/scripts/its/register-token.js deleted file mode 100644 index 7065ca50..00000000 --- a/scripts/its/register-token.js +++ /dev/null @@ -1,140 +0,0 @@ -require('dotenv').config(); -const { requestSuiFromFaucetV0, getFaucetHost } = require('@mysten/sui.js/faucet'); -const { publishInterchainToken } = require('./publish-interchain-token'); -const { SuiClient, getFullnodeUrl } = require('@mysten/sui.js/client'); -const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); -const { TransactionBlock } = require('@mysten/sui.js/transactions'); -const { BCS, getSuiMoveConfig } = require('@mysten/bcs'); -const { getConfig } = require('../utils'); - -async function registerInterchainToken(client, keypair, itsInfo, name, symbol, decimals, mintAmount = false) { - const { coinType, coinMetadata, treasuryCap } = await publishInterchainToken(client, keypair, itsInfo, name, symbol, decimals, true); - - const itsPackageId = itsInfo.packageId; - const itsObjectId = itsInfo['its::ITS'].objectId; - let tx = new TransactionBlock(); - - if (mintAmount) { - tx.moveCall({ - target: `0x2::coin::mint_and_transfer`, - arguments: [tx.object(treasuryCap.objectId), tx.pure(mintAmount), tx.pure.address(keypair.getPublicKey().toSuiAddress())], - typeArguments: [coinType], - }); - } - - const coinInfo = tx.moveCall({ - target: `${itsPackageId}::coin_info::from_metadata`, - arguments: [tx.object(coinMetadata.objectId)], - typeArguments: [coinType], - }); - - const coinManagement = tx.moveCall({ - target: `${itsPackageId}::coin_management::new_with_cap`, - arguments: [tx.object(treasuryCap.objectId)], - typeArguments: [coinType], - }); - - tx.moveCall({ - target: `${itsPackageId}::service::register_coin`, - arguments: [tx.object(itsObjectId), coinInfo, coinManagement], - typeArguments: [coinType], - }); - - const result = await client.signAndExecuteTransactionBlock({ - transactionBlock: tx, - signer: keypair, - options: { - showEffects: true, - showObjectChanges: true, - showContent: true, - }, - requestType: 'WaitForLocalExecution', - }); - const coinObjectId = mintAmount - ? result.objectChanges.find((object) => object.objectType === `0x2::coin::Coin<${coinType}>`).objectId - : null; - - const eventData = await client.queryEvents({ - query: { - MoveEventType: `${itsPackageId}::service::CoinRegistered<${coinType}>`, - }, - }); - const tokenId = eventData.data[0].parsedJson.token_id.id; - - return [tokenId, coinType, coinObjectId]; -} - -module.exports = { - registerInterchainToken, -}; - -if (require.main === module) { - const name = process.argv[2] || 'Test Token'; - const symbol = process.argv[3] || 'TT'; - const decimals = process.argv[4] || 6; - const env = process.argv[5] || 'localnet'; - - (async () => { - const privKey = Buffer.from(process.env.SUI_PRIVATE_KEY, 'hex'); - const keypair = Ed25519Keypair.fromSecretKey(privKey); - const address = keypair.getPublicKey().toSuiAddress(); - // create a new SuiClient object pointing to the network you want to use - const client = new SuiClient({ url: getFullnodeUrl(env) }); - - try { - await requestSuiFromFaucetV0({ - // use getFaucetHost to make sure you're using correct faucet address - // you can also just use the address (see Sui Typescript SDK Quick Start for values) - host: getFaucetHost(env), - recipient: address, - }); - } catch (e) { - console.log(e); - } - const itsInfo = getConfig('its', env); - const [tokenId, coinType] = await registerInterchainToken(client, keypair, itsInfo, name, symbol, decimals); - - const itsPackageId = itsInfo.packageId; - const itsObjectId = itsInfo['its::ITS'].objectId; - - tx = new TransactionBlock(); - - const tokenIdObj = tx.moveCall({ - target: `${itsPackageId}::token_id::from_address`, - arguments: [tx.pure.address(tokenId)], - typeArguments: [], - }); - - tx.moveCall({ - target: `${itsPackageId}::its::token_name`, - arguments: [tx.object(itsObjectId), tokenIdObj], - typeArguments: [coinType], - }); - - tx.moveCall({ - target: `${itsPackageId}::its::token_symbol`, - arguments: [tx.object(itsObjectId), tokenIdObj], - typeArguments: [coinType], - }); - - tx.moveCall({ - target: `${itsPackageId}::its::token_decimals`, - arguments: [tx.object(itsObjectId), tokenIdObj], - typeArguments: [coinType], - }); - - let resp = await client.devInspectTransactionBlock({ - sender: keypair.getPublicKey().toSuiAddress(), - transactionBlock: tx, - }); - - const bcs = new BCS(getSuiMoveConfig()); - - { - const name = bcs.de('string', new Uint8Array(resp.results[1].returnValues[0][0])); - const symbol = bcs.de('string', new Uint8Array(resp.results[2].returnValues[0][0])); - const decimals = bcs.de('u8', new Uint8Array(resp.results[3].returnValues[0][0])); - console.log(name, symbol, decimals); - } - })(); -} diff --git a/scripts/its/send-token.js b/scripts/its/send-token.js deleted file mode 100644 index dcdbc85a..00000000 --- a/scripts/its/send-token.js +++ /dev/null @@ -1,125 +0,0 @@ -require('dotenv').config(); -const { requestSuiFromFaucetV0, getFaucetHost } = require('@mysten/sui.js/faucet'); -const { SuiClient, getFullnodeUrl } = require('@mysten/sui.js/client'); -const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); -const { TransactionBlock } = require('@mysten/sui.js/transactions'); -const { BCS, getSuiMoveConfig } = require('@mysten/bcs'); - -const { arrayify, defaultAbiCoder } = require('ethers/lib/utils'); -const { registerInterchainToken } = require('./register-token'); -const { getConfig } = require('../utils'); - -async function sendInterchainToken(client, keypair, itsInfo, tokenId, coin, destinationChain, destiantionAddress) { - const itsPackageId = itsInfo.packageId; - const itsObjectId = itsInfo['its::ITS'].objectId; - - let tx = new TransactionBlock(); - - let tokenIdObj = tx.moveCall({ - target: `${itsPackageId}::token_id::from_address`, - arguments: [tx.pure(tokenId)], - typeArguments: [], - }); - - tx.moveCall({ - target: `${itsPackageId}::its::get_registered_coin_type`, - arguments: [tx.object(itsObjectId), tokenIdObj], - typeArguments: [], - }); - - let resp = await client.devInspectTransactionBlock({ - sender: keypair.getPublicKey().toSuiAddress(), - transactionBlock: tx, - }); - - const bcs = new BCS(getSuiMoveConfig()); - - const coinType = bcs.de('string', new Uint8Array(resp.results[1].returnValues[0][0])); - - tx = new TransactionBlock(); - - tokenIdObj = tx.moveCall({ - target: `${itsPackageId}::token_id::from_address`, - arguments: [tx.pure(tokenId)], - typeArguments: [], - }); - - tx.moveCall({ - target: `${itsPackageId}::service::interchain_transfer`, - arguments: [ - tx.object(itsObjectId), - tokenIdObj, - tx.object(coin), - tx.pure.string(destinationChain), - tx.pure(String.fromCharCode(...arrayify(destiantionAddress))), - tx.pure(''), - ], - typeArguments: [coinType], - }); - - await client.signAndExecuteTransactionBlock({ - transactionBlock: tx, - signer: keypair, - options: { - showEffects: true, - showObjectChanges: true, - showContent: true, - }, - requestType: 'WaitForLocalExecution', - }); -} - -if (require.main === module) { - const env = process.argv[2] || 'localnet'; - const destinationChain = process.argv[3] || 'Ethereum'; - const destiantionAddress = process.argv[4] || '0x1234'; - const amount = process.argv[5] || 1234; - const name = process.argv[6] || 'Test Token'; - const symbol = process.argv[7] || 'TT'; - const decimals = process.argv[8] || 6; - - (async () => { - const privKey = Buffer.from(process.env.SUI_PRIVATE_KEY, 'hex'); - const keypair = Ed25519Keypair.fromSecretKey(privKey); - const address = keypair.getPublicKey().toSuiAddress(); - // create a new SuiClient object pointing to the network you want to use - const client = new SuiClient({ url: getFullnodeUrl(env) }); - - try { - await requestSuiFromFaucetV0({ - // use getFaucetHost to make sure you're using correct faucet address - // you can also just use the address (see Sui Typescript SDK Quick Start for values) - host: getFaucetHost(env), - recipient: address, - }); - } catch (e) { - console.log(e); - } - const itsInfo = getConfig('its', env); - const axelarInfo = getConfig('axelar', env); - - const [tokenId, coinType] = await registerInterchainToken(client, keypair, itsInfo, name, symbol, decimals, amount); - - let resp = await client.getCoins({ - owner: keypair.getPublicKey().toSuiAddress(), - coinType: coinType, - }); - coin = resp.data[0].coinObjectId; - - await sendInterchainToken(client, keypair, itsInfo, tokenId, coin, destinationChain, destiantionAddress); - - const eventData = await client.queryEvents({ - query: { - MoveEventType: `${axelarInfo.packageId}::gateway::ContractCall`, - }, - }); - const payload = eventData.data[0].parsedJson.payload; - { - const [, tokenId, sourceAddress, destinationAddress, amount, data] = defaultAbiCoder.decode( - ['uint256', 'bytes32', 'bytes', 'bytes', 'uint256', 'bytes'], - payload, - ); - console.log([tokenId, sourceAddress, destinationAddress, Number(amount), data]); - } - })(); -} diff --git a/scripts/its/set-trusted-address.js b/scripts/its/set-trusted-address.js deleted file mode 100644 index 2dadfafb..00000000 --- a/scripts/its/set-trusted-address.js +++ /dev/null @@ -1,110 +0,0 @@ -require('dotenv').config(); -const { requestSuiFromFaucetV0, getFaucetHost } = require('@mysten/sui.js/faucet'); -const { defaultAbiCoder, keccak256, arrayify } = require('ethers/lib/utils'); -const { getBcsForGateway, approveContractCall } = require('../gateway'); -const { SuiClient, getFullnodeUrl } = require('@mysten/sui.js/client'); -const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); -const { TransactionBlock } = require('@mysten/sui.js/transactions'); -const { BCS, getSuiMoveConfig } = require('@mysten/bcs'); -const { getConfig } = require('../utils'); - -async function setTrustedAddresses(client, keypair, envAlias, chainNames, trustedAddresses) { - const itsInfo = getConfig('its', envAlias); - const itsPackageId = itsInfo.packageId; - const itsObjectId = itsInfo['its::ITS'].objectId; - - const axelarInfo = getConfig('axelar', envAlias); - const axelarPackageId = axelarInfo.packageId; - - const governance = getConfig('governance', envAlias)['governance::Governance']; - - const bcs = new BCS(getSuiMoveConfig()); - bcs.registerStructType('TrustedAddressInfo', { - chainNames: 'vector', - trustedAddresses: 'vector', - }); - - const trustedAddressInfo = bcs - .ser('TrustedAddressInfo', { - chainNames: chainNames, - trustedAddresses: trustedAddresses, - }) - .toBytes(); - const payload = defaultAbiCoder.encode( - ['bytes32', 'bytes'], - ['0x2af37a0d5d48850a855b1aaaf57f726c107eb99b40eabf4cc1ba30410cfa2f68', trustedAddressInfo], - ); - - const payloadHash = keccak256(payload); - - const commandId = await approveContractCall( - client, - keypair, - axelarInfo, - governance.trusted_source_chain, - governance.trusted_source_address, - itsInfo['its::ITS'].channel, - payloadHash, - ); - - let tx = new TransactionBlock(); - - const ApprovedMessage = tx.moveCall({ - target: `${axelarPackageId}::gateway::take_approved_message`, - arguments: [ - tx.object(axelarInfo['gateway::Gateway'].objectId), - tx.pure.address(commandId), - tx.pure.string(governance.trusted_source_chain), - tx.pure.string(governance.trusted_source_address), - tx.pure.address(itsInfo['its::ITS'].channel), - tx.pure(bcs.ser('vector', arrayify(payload)).toBytes()), - ], - typeArguments: [], - }); - tx.moveCall({ - target: `${itsPackageId}::service::set_trusted_addresses`, - arguments: [tx.object(itsObjectId), tx.object(governance.objectId), ApprovedMessage], - typeArguments: [], - }); - - await client.signAndExecuteTransactionBlock({ - transactionBlock: tx, - signer: keypair, - options: { - showEffects: true, - showObjectChanges: true, - }, - requestType: 'WaitForLocalExecution', - }); -} - -module.exports = { - setTrustedAddresses, -}; - -if (require.main === module) { - const env = process.argv[2] || 'localnet'; - const chainName = process.argv[3] || 'Ethereum'; - const trustedAddress = process.argv[4] || '0x1234'; - - (async () => { - const privKey = Buffer.from(process.env.SUI_PRIVATE_KEY, 'hex'); - const keypair = Ed25519Keypair.fromSecretKey(privKey); - const address = keypair.getPublicKey().toSuiAddress(); - // create a new SuiClient object pointing to the network you want to use - const client = new SuiClient({ url: getFullnodeUrl(env) }); - - try { - await requestSuiFromFaucetV0({ - // use getFaucetHost to make sure you're using correct faucet address - // you can also just use the address (see Sui Typescript SDK Quick Start for values) - host: getFaucetHost(env), - recipient: address, - }); - } catch (e) { - console.log(e); - } - - await setTrustedAddresses(client, keypair, env, [chainName], [trustedAddress]); - })(); -} diff --git a/scripts/publish-all.js b/scripts/publish-all.js deleted file mode 100644 index 1dcc047f..00000000 --- a/scripts/publish-all.js +++ /dev/null @@ -1,73 +0,0 @@ -require('dotenv').config(); -const { initializeGovernance, takeUpgradeCaps } = require('./governance'); -const { SuiClient, getFullnodeUrl } = require('@mysten/sui.js/client'); -const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); -const { setSquidDiscovery } = require('./squid/discovery.js'); -const { publishPackageFull } = require('./publish-package'); -const { setItsDiscovery } = require('./its/discovery.js'); -const { requestSuiFromFaucet } = require('./utils'); - -async function publishAll(client, keypair, env) { - const upgradeCaps = {}; - const packageIds = {}; - - for (const packagePath of ['abi', 'axelar', 'governance', 'gas_service', 'its', 'squid']) { - console.log(packagePath); - - while (true) - try { - const { packageId, publishTxn } = await publishPackageFull(packagePath, client, keypair, env); - upgradeCaps[packagePath] = publishTxn.objectChanges.find((obj) => obj.objectType === '0x2::package::UpgradeCap'); - packageIds[packagePath] = packageId; - break; - } catch (e) { - console.log(e); - console.log(`Retrying for ${packagePath}`); - } - } - - await initializeGovernance(upgradeCaps.governance, client, keypair, env); - - await takeUpgradeCaps( - ['abi', 'axelar', 'gas_service', 'its'].map((packagePath) => upgradeCaps[packagePath]), - client, - keypair, - env, - ); - - await setItsDiscovery(client, keypair, env.alias); - await setSquidDiscovery(client, keypair, env.alias); -} - -module.exports = { - publishAll, -}; - -if (require.main === module) { - const env = ((arg) => { - switch (arg?.toLowerCase()) { - case 'localnet': - case 'devnet': - case 'testnet': - case 'mainnet': - return { alias: arg, url: getFullnodeUrl(arg) }; - default: - return JSON.parse(arg); - } - })(process.argv[2] || 'localnet'); - const faucet = process.argv[3]?.toLowerCase?.() === 'true'; - - (async () => { - const privKey = Buffer.from(process.env.SUI_PRIVATE_KEY, 'hex'); - const keypair = Ed25519Keypair.fromSecretKey(privKey); - const address = keypair.getPublicKey().toSuiAddress(); - // create a new SuiClient object pointing to the network you want to use - const client = new SuiClient({ url: env.url }); - - if (faucet) { - requestSuiFromFaucet(env, address); - } - - await publishAll(client, keypair, env); - })(); -} diff --git a/scripts/publish-package.js b/scripts/publish-package.js deleted file mode 100644 index 9c5e7046..00000000 --- a/scripts/publish-package.js +++ /dev/null @@ -1,84 +0,0 @@ -require('dotenv').config(); -const { requestSuiFromFaucet, updateMoveToml } = require('./utils'); -const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); -const { TransactionBlock } = require('@mysten/sui.js/transactions'); -const { SuiClient } = require('@mysten/sui.js/client'); -const { execSync } = require('child_process'); -const { parseEnv } = require('./utils'); -const tmp = require('tmp'); -const path = require('path'); - -async function publishPackage(packageName, client, keypair) { - updateMoveToml(packageName, '0x0'); - - // remove all controlled temporary objects on process exit - const address = keypair.getPublicKey().toSuiAddress(); - tmp.setGracefulCleanup(); - - const tmpobj = tmp.dirSync({ unsafeCleanup: true }); - - const { modules, dependencies } = JSON.parse( - execSync( - `sui move build --dump-bytecode-as-base64 --path ${path.join(__dirname, '/../move/', packageName)} --install-dir ${ - tmpobj.name - }`, - { - encoding: 'utf-8', - stdio: 'pipe', // silent the output - }, - ), - ); - - const tx = new TransactionBlock(); - const cap = tx.publish({ - modules, - dependencies, - }); - - // Transfer the upgrade capability to the sender so they can upgrade the package later if they want. - tx.transferObjects([cap], tx.pure(address)); - - const publishTxn = await client.signAndExecuteTransactionBlock({ - transactionBlock: tx, - signer: keypair, - options: { - showEffects: true, - showObjectChanges: true, - showContent: true, - }, - }); - if (publishTxn.effects?.status.status !== 'success') throw new Error('Publish Tx failed'); - - const packageId = (publishTxn.objectChanges?.find((a) => a.type === 'published') ?? []).packageId; - - console.info(`Published package ${packageId} from address ${address}}`); - - updateMoveToml(packageName, packageId); - - return { packageId, publishTxn }; -} - -module.exports = { - publishPackage, -}; - -if (require.main === module) { - const packageName = process.argv[2] || 'axelar'; - const env = parseEnv(process.argv[3] || 'localnet'); - const faucet = process.argv[4]?.toLowerCase?.() === 'true'; - - (async () => { - const privKey = Buffer.from(process.env.SUI_PRIVATE_KEY, 'hex'); - const keypair = Ed25519Keypair.fromSecretKey(privKey); - const address = keypair.getPublicKey().toSuiAddress(); - console.log(address); - // create a new SuiClient object pointing to the network you want to use - const client = new SuiClient({ url: env.url }); - - if (faucet) { - await requestSuiFromFaucet(env, address); - } - - await publishPackage(packageName, client, keypair, env); - })(); -} diff --git a/scripts/run.sh b/scripts/run.sh deleted file mode 100755 index 4f7a90c6..00000000 --- a/scripts/run.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -if [[ ${#} -ne 1 || ( "$1" != "build" && "$1" != "test" ) ]]; then - echo "Usage: $0 [build|test]" - exit 1 -fi - -exit_code=0 - -for module in ./move/*/; do - if ! sui move "$1" --lint --warnings-are-errors --path "$module"; then - exit_code=1 - fi -done - -if [ $exit_code -ne 0 ]; then - echo "" - echo -e "\033[0;31m$1 failed\033[0m" - exit 1 -fi diff --git a/scripts/squid/discovery.js b/scripts/squid/discovery.js deleted file mode 100644 index 9386d668..00000000 --- a/scripts/squid/discovery.js +++ /dev/null @@ -1,57 +0,0 @@ -require('dotenv').config(); -const { requestSuiFromFaucetV0, getFaucetHost } = require('@mysten/sui.js/faucet'); -const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); -const { TransactionBlock } = require('@mysten/sui.js/transactions'); -const { SuiClient } = require('@mysten/sui.js/client'); -const { getConfig } = require('../utils'); -async function setSquidDiscovery(client, keypair, env) { - const squid_info = getConfig('squid', env.alias); - const itsId = getConfig('its', env.alias)['its::ITS'].objectId; - const relayerDiscoveryId = getConfig('axelar', env.alias)['discovery::RelayerDiscovery'].objectId; - const tx = new TransactionBlock(); - console.log(squid_info['squid::Squid'].objectId, itsId, relayerDiscoveryId); - tx.moveCall({ - target: `${squid_info.packageId}::discovery::register_transaction`, - arguments: [tx.object(squid_info['squid::Squid'].objectId), tx.object(itsId), tx.object(relayerDiscoveryId)], - type_arguments: [], - }); - - await client.signAndExecuteTransactionBlock({ - transactionBlock: tx, - signer: keypair, - options: { - showEffects: true, - showObjectChanges: true, - }, - requestType: 'WaitForLocalExecution', - }); -} - -module.exports = { - setSquidDiscovery, -}; - -if (require.main === module) { - const env = process.argv[2] || 'localnet'; - - (async () => { - const privKey = Buffer.from(process.env.SUI_PRIVATE_KEY, 'hex'); - const keypair = Ed25519Keypair.fromSecretKey(privKey); - const address = keypair.getPublicKey().toSuiAddress(); - // create a new SuiClient object pointing to the network you want to use - const client = new SuiClient({ url: getFullnodeUrl(env) }); - - try { - await requestSuiFromFaucetV0({ - // use getFaucetHost to make sure you're using correct faucet address - // you can also just use the address (see Sui Typescript SDK Quick Start for values) - host: getFaucetHost(env), - recipient: address, - }); - } catch (e) { - console.log(e); - } - - await setSquidDiscovery(client, keypair, env); - })(); -} diff --git a/scripts/squid/squid.js b/scripts/squid/squid.js deleted file mode 100644 index b1ba1b4a..00000000 --- a/scripts/squid/squid.js +++ /dev/null @@ -1,586 +0,0 @@ -require('dotenv').config(); -const { requestSuiFromFaucetV0, getFaucetHost } = require('@mysten/sui.js/faucet'); -const { publishInterchainToken } = require('../its/publish-interchain-token'); -const { publishPackageFull, publishPackage } = require('../publish-package'); -const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); -const { setTrustedAddresses } = require('../its/set-trusted-address'); -const { registerInterchainToken } = require('../its/register-token'); -const { TransactionBlock } = require('@mysten/sui.js/transactions'); -const { hexlify, defaultAbiCoder } = require('ethers/lib/utils'); -const { parseEnv, setConfig, getConfig } = require('../utils'); -const { receiveCall } = require('../test-receive-call'); -const { setItsDiscovery } = require('../its/discovery'); -const { SuiClient } = require('@mysten/sui.js/client'); -const { - utils: { arrayify }, -} = require('ethers'); -const { bcs } = require('@mysten/bcs'); - -const deepbook = '0xdee9'; - -const tickSize = 1e6; -const lotSize = 1e3; -const amountBase = 1e6 * 1e9; -const amountQuote = amountBase; -const amount = lotSize * 1000000; -const sourceChain = 'sourceAddress'; -const sourceAddress = 'trustedITsAddress'; - -const SWEEP_DUST_SWAP_TYPE = 0; -const DEEPBOOK_SWAP_TYPE = 1; -const SUI_TRANSFER_SWAP_TYPE = 2; -const ITS_TRANSFER_SWAP_TYPE = 3; - -const MESSAGE_TYPE_INTERCHAIN_TRANSFER = 0; - -async function sleep(ms = 100) { - await new Promise((resolve) => { - setTimeout(resolve, ms); - }); -} - -async function placeLimitOrder(client, keypair, env, isBid, price, amount) { - const { pool, accountCap, base, quote } = getConfig('trading', env.alias); - - const tx = new TransactionBlock(); - if (isBid) { - const coin = tx.moveCall({ - target: `0x2::coin::split`, - arguments: [tx.object(quote.objectId), tx.pure(Math.floor((amount * price) / 1e9))], - typeArguments: [quote.type], - }); - - tx.moveCall({ - target: `0xdee9::clob_v2::deposit_quote`, - arguments: [tx.object(pool), coin, tx.object(accountCap)], - typeArguments: [base.type, quote.type], - }); - } else { - const coin = tx.moveCall({ - target: `0x2::coin::split`, - arguments: [tx.object(base.objectId), tx.pure(amount)], - typeArguments: [base.type], - }); - - tx.moveCall({ - target: `0xdee9::clob_v2::deposit_base`, - arguments: [tx.object(pool), coin, tx.object(accountCap)], - typeArguments: [base.type, quote.type], - }); - } - - tx.moveCall({ - target: `0xdee9::clob_v2::place_limit_order`, - arguments: [ - tx.object(pool), - tx.pure(0), - tx.pure(price), - tx.pure(amount), - tx.pure(0), - tx.pure(isBid), - tx.pure(10000000000000000000), - tx.pure(3), - tx.object('0x6'), - tx.object(accountCap), - ], - typeArguments: [base.type, quote.type], - }); - - await client.signAndExecuteTransactionBlock({ - transactionBlock: tx, - signer: keypair, - options: { - showEffects: true, - showObjectChanges: true, - }, - requestType: 'WaitForLocalExecution', - }); -} - -async function prepare(client, keypair, env) { - const address = keypair.getPublicKey().toSuiAddress(); - try { - await requestSuiFromFaucetV0({ - // use getFaucetHost to make sure you're using correct faucet address - // you can also just use the address (see Sui Typescript SDK Quick Start for values) - host: getFaucetHost(env.alias), - recipient: address, - }); - } catch (e) { - console.log(e); - } - - //await publishPackageFull('trading', client, keypair, env); - - //const config = getConfig('trading', env.alias); - - const [baseId, baseType, baseCoin] = await registerInterchainToken( - client, - keypair, - getConfig('its', env.alias), - 'Base', - 'B', - 9, - amountBase, - ); - - const [quoteId, quoteType, quoteCoin] = await registerInterchainToken( - client, - keypair, - getConfig('its', env.alias), - 'Quote', - 'Q', - 9, - amountQuote, - ); - - let tx = new TransactionBlock(); - - const creationFee = tx.splitCoins(tx.gas, [tx.pure(100 * 1e9)]); - - tx.moveCall({ - target: `${deepbook}::clob_v2::create_pool`, - arguments: [tx.pure(tickSize), tx.pure(lotSize), creationFee], - typeArguments: [baseType, quoteType], - }); - - let account = tx.moveCall({ - target: `${deepbook}::clob_v2::create_account`, - arguments: [], - typeArguments: [], - }); - - tx.moveCall({ - target: `0x2::transfer::public_transfer`, - arguments: [account, tx.pure(keypair.toSuiAddress())], - typeArguments: ['0xdee9::custodian_v2::AccountCap'], - }); - - let result = await client.signAndExecuteTransactionBlock({ - transactionBlock: tx, - signer: keypair, - options: { - showEffects: true, - showObjectChanges: true, - }, - requestType: 'WaitForLocalExecution', - }); - - const pool = result.objectChanges.find((object) => object.objectType.startsWith('0xdee9::clob_v2::Pool<')).objectId; - const poolCap = result.objectChanges.find((object) => object.objectType.startsWith('0xdee9::clob_v2::PoolOwnerCap')).objectId; - const accountCap = result.objectChanges.find((object) => object.objectType.startsWith('0xdee9::custodian_v2::AccountCap')).objectId; - const suiCoin = result.objectChanges.find((object) => object.objectType.startsWith('0x2::coin::Coin<')).objectId; - - setConfig('trading', env.alias, { - pool, - accountCap, - base: { - type: baseType, - tokenId: baseId, - objectId: baseCoin, - }, - quote: { - type: quoteType, - tokenId: quoteId, - objectId: quoteCoin, - }, - suiCoin, - }); - - await sleep(500); - await placeLimitOrder(client, keypair, env, false, 1100e6, amountQuote); - await sleep(500); - await placeLimitOrder(client, keypair, env, true, 990e6, amountBase); - - console.log(`Prepare Done`); -} - -async function postpare(client, keypair, env) { - await setItsDiscovery(client, keypair, env.alias); - await sleep(300); - await setTrustedAddresses(client, keypair, env.alias, [sourceChain], [sourceAddress]); - - console.log(`Postpare Done`); -} - -async function placeLimitOrders(client, keypair, env, isBid, n = 10) { - if (isBid) { - for (let i = 0; i < n; i++) { - console.log(i); - const price = 1e9 - tickSize * Math.floor(1 + Math.random() * 10); - const amount = 1e9 * Math.floor(100 + Math.random() * 100); - try { - await placeLimitOrder(client, keypair, env, true, price, amount); - } catch (e) { - console.log(e); - i--; - } - } - } else { - for (let i = 0; i < n; i++) { - console.log(i); - const price = 1e9 + tickSize * Math.floor(1 + Math.random() * 10); - const amount = 1e9 * Math.floor(100 + Math.random() * 100); - try { - await placeLimitOrder(client, keypair, env, false, price, amount); - } catch (e) { - console.log(e); - i--; - } - } - } -} - -async function testBaseForQuote(client, keypair, env) { - //await placeLimitOrders(client, keypair, env, true, 10); - - const { pool, base, quote } = getConfig('trading', env.alias); - - const { packageId } = await publishPackage('trading', client, keypair); - const tx = new TransactionBlock(); - - tx.moveCall({ - target: `${packageId}::trading::predict_base_for_quote`, - arguments: [tx.object(pool), tx.pure(amount), tx.pure(lotSize), tx.object('0x6')], - typeArguments: [base.type, quote.type], - }); - - const coin = tx.moveCall({ - target: `0x2::coin::split`, - arguments: [tx.object(base.objectId), tx.pure(amount)], - typeArguments: [base.type], - }); - - const accountCap = tx.moveCall({ - target: `${deepbook}::clob_v2::create_account`, - arguments: [], - typeArguments: [], - }); - - const [leftover_base, leftover_quote] = tx.moveCall({ - target: `${deepbook}::clob_v2::swap_exact_base_for_quote`, - arguments: [ - tx.object(pool), - tx.pure(0), - accountCap, - tx.pure(amount), - coin, - tx.moveCall({ target: '0x2::coin::zero', typeArguments: [quote.type] }), - tx.object('0x6'), - ], - typeArguments: [base.type, quote.type], - }); - - tx.moveCall({ - target: `${deepbook}::custodian_v2::delete_account_cap`, - arguments: [accountCap], - typeArguments: [], - }); - - tx.moveCall({ - target: `0x2::transfer::public_transfer`, - arguments: [leftover_base, tx.pure(keypair.toSuiAddress())], - typeArguments: [`0x2::coin::Coin<${base.type}>`], - }); - tx.moveCall({ - target: `0x2::transfer::public_transfer`, - arguments: [leftover_quote, tx.pure(keypair.toSuiAddress())], - typeArguments: [`0x2::coin::Coin<${quote.type}>`], - }); - - const result = await client.signAndExecuteTransactionBlock({ - transactionBlock: tx, - signer: keypair, - options: { - showEffects: true, - showObjectChanges: true, - }, - requestType: 'WaitForLocalExecution', - }); - - const response = await client.queryEvents({ - query: { - MoveEventType: `${packageId}::trading::Event`, - }, - }); - console.log(response.data.map((event) => event.parsedJson)); - - const quoteCoinId = result.objectChanges.find((change) => change.objectType == `0x2::coin::Coin<${quote.type}>`).objectId; - const quoteCoin = await client.getObject({ - id: quoteCoinId, - options: { - showContent: true, - }, - }); - - const baseCoinId = result.objectChanges.find( - (change) => change.objectType == `0x2::coin::Coin<${base.type}>` && change.type === 'created', - ).objectId; - const baseCoin = await client.getObject({ - id: baseCoinId, - options: { - showContent: true, - }, - }); - - console.log({ - amount_left: baseCoin.data.content.fields.balance, - output: quoteCoin.data.content.fields.balance, - }); -} - -async function testQuoteForBase(client, keypair, env) { - await placeLimitOrders(client, keypair, env, false, 10); - - const { pool, base, quote } = getConfig('trading', env.alias); - - const { packageId } = await publishPackage('trading', client, keypair); - const tx = new TransactionBlock(); - - tx.moveCall({ - target: `${packageId}::trading::predict_quote_for_base`, - arguments: [tx.object(pool), tx.pure(amount), tx.pure(lotSize), tx.object('0x6')], - typeArguments: [base.type, quote.type], - }); - - const coin = tx.moveCall({ - target: `0x2::coin::split`, - arguments: [tx.object(quote.objectId), tx.pure(amount)], - typeArguments: [quote.type], - }); - - const accountCap = tx.moveCall({ - target: `${deepbook}::clob_v2::create_account`, - arguments: [], - typeArguments: [], - }); - - const [leftover_base, leftover_quote] = tx.moveCall({ - target: `${deepbook}::clob_v2::swap_exact_quote_for_base`, - arguments: [tx.object(pool), tx.pure(0), accountCap, tx.pure(amount), tx.object('0x6'), coin], - typeArguments: [base.type, quote.type], - }); - - tx.moveCall({ - target: `${deepbook}::custodian_v2::delete_account_cap`, - arguments: [accountCap], - typeArguments: [], - }); - - tx.moveCall({ - target: `0x2::transfer::public_transfer`, - arguments: [leftover_base, tx.pure(keypair.toSuiAddress())], - typeArguments: [`0x2::coin::Coin<${base.type}>`], - }); - tx.moveCall({ - target: `0x2::transfer::public_transfer`, - arguments: [leftover_quote, tx.pure(keypair.toSuiAddress())], - typeArguments: [`0x2::coin::Coin<${quote.type}>`], - }); - - const result = await client.signAndExecuteTransactionBlock({ - transactionBlock: tx, - signer: keypair, - options: { - showEffects: true, - showObjectChanges: true, - }, - requestType: 'WaitForLocalExecution', - }); - - const response = await client.queryEvents({ - query: { - MoveEventType: `${packageId}::trading::Event`, - }, - }); - console.log(response.data.map((event) => event.parsedJson)); - - const quoteCoinId = result.objectChanges.find( - (change) => change.objectType == `0x2::coin::Coin<${quote.type}>` && change.type === 'created', - ).objectId; - const quoteCoin = await client.getObject({ - id: quoteCoinId, - options: { - showContent: true, - }, - }); - - const baseCoinId = result.objectChanges.find( - (change) => change.objectType == `0x2::coin::Coin<${base.type}>` && change.type === 'created', - ).objectId; - const baseCoin = await client.getObject({ - id: baseCoinId, - options: { - showContent: true, - }, - }); - - console.log({ - amount_left: quoteCoin.data.content.fields.balance, - output: baseCoin.data.content.fields.balance, - }); -} - -async function test(client, keypair, env) { - const address = bcs.fixedArray(32, bcs.u8()).transform({ - input: (id) => arrayify(id), - output: (id) => hexlify(id), - }); - - const squid_info = getConfig('squid', env.alias); - const { pool, base, quote } = getConfig('trading', env.alias); - const its_info = getConfig('its', env.alias); - - const swapInfoStruct = bcs.struct('SwapInfo', { - swap_data: bcs.vector(bcs.vector(bcs.u8())), - }); - - const deepbookSwapStruct = bcs.struct('DeepbookSwap', { - swap_type: bcs.u8(), - pool_id: address, - has_base: bcs.bool(), - min_out: bcs.u64(), - base_type: bcs.string(), - quote_type: bcs.string(), - lot_size: bcs.u64(), - should_sweep: bcs.bool(), - }); - - const sweepDust = bcs.struct('SweepDust', { - swap_type: bcs.u8(), - type: bcs.string(), - }); - - const suiTransfer = bcs.struct('SuiTransfer', { - swap_type: bcs.u8(), - type: bcs.string(), - destination: address, - }); - - const itsTransfer = bcs.struct('ItsTransfer', { - swap_type: bcs.u8(), - type: bcs.string(), - token_id: address, - destination_chain: bcs.string(), - destination_address: bcs.string(), - metadata: bcs.vector(bcs.u8()), - }); - - const swapInfoData = swapInfoStruct - .serialize({ - swap_data: [ - deepbookSwapStruct - .serialize({ - swap_type: DEEPBOOK_SWAP_TYPE, - pool_id: pool, - has_base: true, - min_out: 0, - base_type: base.type.substring(2), - quote_type: quote.type.substring(2), - lot_size: lotSize, - should_sweep: true, - }) - .toBytes(), - deepbookSwapStruct - .serialize({ - swap_type: DEEPBOOK_SWAP_TYPE, - pool_id: pool, - has_base: false, - min_out: 0, - base_type: base.type.substring(2), - quote_type: quote.type.substring(2), - lot_size: lotSize, - should_sweep: true, - }) - .toBytes(), - deepbookSwapStruct - .serialize({ - swap_type: DEEPBOOK_SWAP_TYPE, - pool_id: pool, - has_base: true, - min_out: 0, - base_type: base.type.substring(2), - quote_type: quote.type.substring(2), - lot_size: lotSize, - should_sweep: true, - }) - .toBytes(), - suiTransfer - .serialize({ - swap_type: SUI_TRANSFER_SWAP_TYPE, - type: quote.type.substring(2), - destination: keypair.toSuiAddress(), - }) - .toBytes(), - ], - }) - .toBytes(); - - const payload = defaultAbiCoder.encode( - ['uint256', 'bytes32', 'bytes', 'bytes', 'uint256', 'bytes'], - [MESSAGE_TYPE_INTERCHAIN_TRANSFER, base.tokenId, '0x', squid_info['squid::Squid'].channel, amount, swapInfoData], - ); - const receipt = await receiveCall( - client, - keypair, - getConfig('axelar', env.alias), - sourceChain, - sourceAddress, - its_info['its::ITS'].channel, - payload, - ); - - const quoteCoinId = receipt.objectChanges.find( - (change) => change.type === 'created' && change.objectType === `0x2::coin::Coin<${quote.type}>`, - ).objectId; - - const quoteCoin = await client.getObject({ - id: quoteCoinId, - options: { - showContent: true, - }, - }); - - console.log({ - output: quoteCoin.data.content.fields.balance, - }); -} - -async function registerTransaction(client, keypair, env) { - const squid_info = getConfig('squid', env.alias); - const itsId = getConfig('its', env.alias)['its::ITS'].objectId; - const relayerDiscoveryId = getConfig('axelar', env.alias)['discovery::RelayerDiscovery'].objectId; - const tx = new TransactionBlock(); - console.log(squid_info['squid::Squid'].objectId, itsId, relayerDiscoveryId); - tx.moveCall({ - target: `${squid_info.packageId}::discovery::register_transaction`, - arguments: [tx.object(squid_info['squid::Squid'].objectId), tx.object(itsId), tx.object(relayerDiscoveryId)], - type_arguments: [], - }); - - await client.signAndExecuteTransactionBlock({ - transactionBlock: tx, - signer: keypair, - options: { - showEffects: true, - showObjectChanges: true, - }, - requestType: 'WaitForLocalExecution', - }); -} - -(async () => { - const env = parseEnv(process.argv[2] || 'localnet'); - const privKey = Buffer.from(process.env.SUI_PRIVATE_KEY, 'hex'); - - // get the public key in a compressed format - const keypair = Ed25519Keypair.fromSecretKey(privKey); - // create a new SuiClient object pointing to the network you want to use - const client = new SuiClient({ url: env.url }); - - await prepare(client, keypair, env); - await postpare(client, keypair, env); - await publishPackageFull('squid', client, keypair, env); - await registerTransaction(client, keypair, env); - await test(client, keypair, env); -})(); diff --git a/scripts/test-receive-call.js b/scripts/test-receive-call.js deleted file mode 100644 index c805c583..00000000 --- a/scripts/test-receive-call.js +++ /dev/null @@ -1,190 +0,0 @@ -require('dotenv').config(); - -const { BCS, getSuiMoveConfig, bcs: bcsEncoder } = require('@mysten/bcs'); -const { - utils: { keccak256, arrayify, hexlify }, -} = require('ethers'); -const { SuiClient, getFullnodeUrl } = require('@mysten/sui.js/client'); -const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); -const { TransactionBlock } = require('@mysten/sui.js/transactions'); -const { approveContractCall } = require('./gateway'); - -async function receiveCall(client, keypair, axelarInfo, sourceChain, sourceAddress, destinationAddress, payload) { - const axelarPackageId = axelarInfo.packageId; - const gateway = axelarInfo['gateway::Gateway']; - const discovery = axelarInfo['discovery::RelayerDiscovery']; - const payloadHash = keccak256(payload); - - await approveContractCall(client, keypair, axelarInfo, sourceChain, sourceAddress, destinationAddress, payloadHash); - - const eventData = await client.queryEvents({ - query: { - MoveEventType: `${axelarPackageId}::gateway::ContractCallApproved`, - }, - }); - const event = eventData.data[0].parsedJson; - - const discoveryArg = [0]; - discoveryArg.push(...arrayify(discovery.objectId)); - const targetIdArg = [1]; - targetIdArg.push(...arrayify(event.target_id)); - let moveCalls = [ - { - function: { - package_id: axelarPackageId, - module_name: 'discovery', - name: 'get_transaction', - }, - arguments: [discoveryArg, targetIdArg], - type_arguments: [], - }, - ]; - let isFinal = false; - - while (!isFinal) { - const tx = new TransactionBlock(); - makeCalls(tx, moveCalls, payload); - const resp = await client.devInspectTransactionBlock({ - sender: keypair.getPublicKey().toSuiAddress(), - transactionBlock: tx, - }); - - const txData = resp.results[0].returnValues[0][0]; - const nextTx = getTransactionBcs().de('Transaction', new Uint8Array(txData)); - isFinal = nextTx.isFinal; - moveCalls = nextTx.move_calls; - } - - const tx = new TransactionBlock(); - const ApprovedMessage = tx.moveCall({ - target: `${axelarPackageId}::gateway::take_approved_message`, - arguments: [ - tx.object(gateway.objectId), - tx.pure(event.cmd_id), - tx.pure(event.source_chain), - tx.pure(event.source_address), - tx.pure(event.target_id), - tx.pure(String.fromCharCode(...arrayify(payload))), - ], - typeArguments: [], - }); - makeCalls(tx, moveCalls, payload, ApprovedMessage); - return await client.signAndExecuteTransactionBlock({ - transactionBlock: tx, - signer: keypair, - options: { - showEffects: true, - showObjectChanges: true, - }, - requestType: 'WaitForLocalExecution', - }); -} - -function makeCalls(tx, moveCalls, payload, ApprovedMessage) { - const returns = []; - - for (const call of moveCalls) { - let result = tx.moveCall(buildMoveCall(tx, call, payload, ApprovedMessage, returns)); - if (!Array.isArray(result)) result = [result]; - returns.push(result); - } -} - -function getTransactionBcs() { - const bcs = new BCS(getSuiMoveConfig()); - - // input argument for the tx - bcs.registerStructType('Function', { - package_id: 'address', - module_name: 'string', - name: 'string', - }); - bcs.registerStructType('MoveCall', { - function: 'Function', - arguments: 'vector>', - type_arguments: 'vector', - }); - bcs.registerStructType('Transaction', { - isFinal: 'bool', - move_calls: 'vector', - }); - return bcs; -} - -function buildMoveCall(tx, moveCallInfo, payload, callContractObj, previousReturns) { - const decodeArgs = (args, tx) => - args.map((arg) => { - if (arg[0] === 0) { - return tx.object(hexlify(arg.slice(1))); - } else if (arg[0] === 1) { - return tx.pure(new Uint8Array(arg.slice(1))); - } else if (arg[0] === 2) { - return callContractObj; - } else if (arg[0] === 3) { - return tx.pure(bcsEncoder.vector(bcsEncoder.u8()).serialize(arrayify(payload))); - } else if (arg[0] === 4) { - return previousReturns[arg[1]][arg[2]]; - } - - throw new Error(`Invalid argument prefix: ${arg[0]}`); - }); - const decodeDescription = (description) => `${description.package_id}::${description.module_name}::${description.name}`; - return { - target: decodeDescription(moveCallInfo.function), - arguments: decodeArgs(moveCallInfo.arguments, tx), - typeArguments: moveCallInfo.type_arguments, - }; -} - -module.exports = { - receiveCall, - getTransactionBcs, -}; - -if (require.main === module) { - (async () => { - const env = process.argv[2] || 'localnet'; - const axelarInfo = require('../info/axelar.json')[env]; - const testInfo = require('../info/test.json')[env]; - const privKey = Buffer.from(process.env.SUI_PRIVATE_KEY, 'hex'); - - const discovery = axelarInfo['discovery::RelayerDiscovery']; - - // get the public key in a compressed format - const keypair = Ed25519Keypair.fromSecretKey(privKey); - // create a new SuiClient object pointing to the network you want to use - const client = new SuiClient({ url: getFullnodeUrl(env) }); - - const testPackageId = testInfo.packageId; - const test = testInfo['test::Singleton']; - - const payload = '0x1234'; - - const tx = new TransactionBlock(); - tx.moveCall({ - target: `${testPackageId}::test::register_transaction`, - arguments: [tx.object(discovery.objectId), tx.object(test.objectId)], - }); - await client.signAndExecuteTransactionBlock({ - transactionBlock: tx, - signer: keypair, - options: { - showEffects: true, - showObjectChanges: true, - }, - requestType: 'WaitForLocalExecution', - }); - - await receiveCall(client, keypair, axelarInfo, 'Ethereum', '0x0', test.channel, payload); - - const event = ( - await client.queryEvents({ - query: { - MoveEventType: `${testPackageId}::test::Executed`, - }, - }) - ).data[0].parsedJson; - - if (hexlify(event.data) !== payload) throw new Error(`Emmited payload missmatch: ${hexlify(event.data)} != ${payload}`); - })(); -} diff --git a/scripts/test-send-call.js b/scripts/test-send-call.js deleted file mode 100644 index 46849a35..00000000 --- a/scripts/test-send-call.js +++ /dev/null @@ -1,60 +0,0 @@ -require('dotenv').config(); - -const { SuiClient } = require('@mysten/sui.js/client'); - -const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); -const { TransactionBlock } = require('@mysten/sui.js/transactions'); -const { - utils: { hexlify }, -} = require('ethers'); - -const { toPure, parseEnv } = require('./utils'); - -(async () => { - const env = parseEnv(process.argv[2] || 'localnet'); - const destinationChain = process.argv[3] || 'ethereum'; - const destinationAddress = process.argv[4] || '0x68B93045fe7D8794a7cAF327e7f855CD6Cd03BB8'; - const payload = '0x' + Buffer.from(process.argv[5] || 'hello world', 'utf8').toString('hex'); - const axelarInfo = require('../info/axelar.json')[env.alias]; - const testInfo = require('../info/test.json')[env.alias]; - const privKey = Buffer.from(process.env.SUI_PRIVATE_KEY, 'hex'); - - // get the public key in a compressed format - const keypair = Ed25519Keypair.fromSecretKey(privKey); - // create a new SuiClient object pointing to the network you want to use - const client = new SuiClient({ url: env.url }); - - const axlearPackageId = axelarInfo.packageId; - const testPackageId = testInfo.packageId; - const test = testInfo['test::Singleton']; - - const tx = new TransactionBlock(); - - tx.moveCall({ - target: `${testPackageId}::test::send_call`, - arguments: [tx.object(test.objectId), tx.pure(destinationChain), tx.pure(destinationAddress), tx.pure(toPure(payload))], - typeArguments: [], - }); - - await client.signAndExecuteTransactionBlock({ - transactionBlock: tx, - signer: keypair, - options: { - showEffects: true, - showObjectChanges: true, - }, - requestType: 'WaitForLocalExecution', - }); - - const event = ( - await client.queryEvents({ - query: { - MoveEventType: `${axlearPackageId}::gateway::ContractCall`, - }, - }) - ).data[0].parsedJson; - console.log(event); - - if (hexlify(event.source_id) !== test.channel) - throw new Error(`Emmited payload missmatch: ${hexlify(event.source)} != ${test.channel}`); -})(); diff --git a/scripts/test-transfer-operatorship.js b/scripts/test-transfer-operatorship.js deleted file mode 100644 index 31773801..00000000 --- a/scripts/test-transfer-operatorship.js +++ /dev/null @@ -1,25 +0,0 @@ -require('dotenv').config(); -const { transferOperatorship, getRandomOperators } = require('./gateway'); -const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); -const { SuiClient } = require('@mysten/sui.js/client'); -const { parseEnv } = require('./utils'); -const fs = require('fs'); - -(async () => { - const env = parseEnv(process.argv[2] || 'localnet'); - const allInfo = require(`../info/axelar.json`); - const privKey = Buffer.from(process.env.SUI_PRIVATE_KEY, 'hex'); - - // get the public key in a compressed format - const keypair = Ed25519Keypair.fromSecretKey(privKey); - // create a new SuiClient object pointing to the network you want to use - const client = new SuiClient({ url: env.url }); - - const operators = getRandomOperators(5); - - await transferOperatorship(allInfo[env.alias], client, keypair, operators.pubKeys, operators.weights, operators.threshold); - - allInfo[env.alias].activeOperators = operators; - - fs.writeFileSync(`info/axelar.json`, JSON.stringify(allInfo, null, 4)); -})(); diff --git a/scripts/transfer-genesis-operatorship.js b/scripts/transfer-genesis-operatorship.js deleted file mode 100644 index 368b818c..00000000 --- a/scripts/transfer-genesis-operatorship.js +++ /dev/null @@ -1,27 +0,0 @@ -require('dotenv').config(); -const { transferOperatorship, getAmplifierWorkers } = require('./gateway'); -const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); -const { SuiClient } = require('@mysten/sui.js/client'); -const { parseEnv } = require('./utils'); -const fs = require('fs'); - -(async () => { - const env = parseEnv(process.argv[2] || 'localnet'); - const rpc = process.argv[3] || 'http://localhost:26657'; - const proverAddr = process.argv[4]; - const allInfo = require(`../info/axelar.json`); - const privKey = Buffer.from(process.env.SUI_PRIVATE_KEY, 'hex'); - - // get the public key in a compressed format - const keypair = Ed25519Keypair.fromSecretKey(privKey); - // create a new SuiClient object pointing to the network you want to use - const client = new SuiClient({ url: env.url }); - - const operators = await getAmplifierWorkers(rpc, proverAddr); - - await transferOperatorship(allInfo[env.alias], client, keypair, operators.pubKeys, operators.weights, operators.threshold); - - allInfo[env.alias].activeOperators = operators; - - fs.writeFileSync(`info/axelar.json`, JSON.stringify(allInfo, null, 4)); -})(); diff --git a/scripts/tx-builder.js b/scripts/tx-builder.js deleted file mode 100644 index 98ca787f..00000000 --- a/scripts/tx-builder.js +++ /dev/null @@ -1,281 +0,0 @@ -const { TransactionBlock } = require('@mysten/sui.js/transactions'); -const { bcs } = require('@mysten/bcs'); -const { - utils: { arrayify, hexlify }, -} = require('ethers'); -const tmp = require('tmp'); -const path = require('path'); -const { updateMoveToml } = require('./utils'); -const { execSync } = require('child_process'); - -const objectCache = {}; - -function updateCache(objectChanges) { - for (const change of objectChanges) { - if (!change.objectId) continue; - objectCache[change.objectId] = change; - } -} - -function getObject(tx, object) { - if (Array.isArray(object)) { - object = hexlify(object); - } - - if (typeof object === 'string') { - const cached = objectCache[object]; - - if (cached) { - // TODO: figure out how to load the object version/digest into the TransactionBlock because it seems impossible for non gas payment objects - const txObject = tx.object(object); - return txObject; - } - - return tx.object(object); - } - - return object; -} - -function getTypeName(type) { - function get(type) { - let name = `${type.address}::${type.module}::${type.name}`; - - if (type.typeArguments.length > 0) { - name += `<${type.typeArguments[0]}`; - - for (let i = 1; i < type.typeArguments.length; i++) { - name += `,${type.typeArguments[i]}`; - } - - name += '>'; - } - - return name; - } - - if (type.Struct) { - return get(type.Struct); - } else if (type.Reference) { - return getTypeName(type.Reference); - } else if (type.MutableReference) { - return getTypeName(type.MutableReference); - } else if (type.Vector) { - return `vector<${getTypeName(type.Vector)}>`; - } - - return type.toLowerCase(); -} - -function getNestedStruct(tx, type, arg) { - let inside = type; - - while (inside.Vector) { - inside = inside.Vector; - } - - if (!inside.Struct && !inside.Reference && !inside.MutableReference) { - return null; - } - - if (isString(inside)) { - return null; - } - - if (type.Struct || type.Reference || type.MutableReference) { - return getObject(tx, arg); - } - - if (!type.Vector) return null; - const nested = arg.map((arg) => getNestedStruct(tx, type.Vector, arg)); - const typeName = getTypeName(type.Vector); - return tx.makeMoveVec({ - type: typeName, - objects: nested, - }); -} - -function serialize(tx, type, arg) { - const struct = getNestedStruct(tx, type, arg); - - if (struct) { - return struct; - } - - bcs.address = () => - bcs.fixedArray(32, bcs.u8()).transform({ - input: (id) => arrayify(id), - output: (id) => hexlify(id), - }); - - const vectorU8 = () => - bcs.vector(bcs.u8()).transform({ - input(input) { - if (typeof input === 'string') input = arrayify(input); - return input; - }, - }); - - const serializer = (type) => { - if (isString(type)) { - return bcs.string(); - } - - if (typeof type === 'string') { - return bcs[type.toLowerCase()](); - } else if (type.Vector) { - if (type.Vector === 'U8') { - return vectorU8(); - } - - return bcs.vector(serializer(type.Vector)); - } - - return null; - }; - - return tx.pure(serializer(type).serialize(arg).toBytes()); -} - -function isTxContext(parameter) { - if(parameter.MutableReference) { - parameter = parameter.MutableReference.Struct; - if (!parameter) return false; - } else if (parameter.Reference) { - parameter = parameter.Reference.Struct; - if (!parameter) return false; - } else { - return false; - } - return parameter.address === '0x2' && parameter.module === 'tx_context' && parameter.name === 'TxContext'; -} - -function isString(parameter) { - if (parameter.MutableReference) parameter = parameter.MutableReference; - if (parameter.Reference) parameter = parameter.Reference; - parameter = parameter.Struct; - if (!parameter) return false; - const isAsciiString = parameter.address === '0x1' && parameter.module === 'ascii' && parameter.name === 'String'; - const isStringString = parameter.address === '0x1' && parameter.module === 'string' && parameter.name === 'String'; - return isAsciiString || isStringString; -} - -class TxBuilder { - constructor(client) { - this.client = client; - this.tx = new TransactionBlock(); - } - - async moveCall(moveCallInfo) { - let target = moveCallInfo.target; - // If target is string, convert to object that `getNormalizedMoveFunction` accepts. - if (typeof target === 'string') { - const first = target.indexOf(':'); - const last = target.indexOf(':', first + 2); - const packageId = target.slice(0, first); - const module = target.slice(first + 2, last); - const functionName = target.slice(last + 2); - target = { - package: packageId, - module, - function: functionName, - }; - } - - const moveFn = await this.client.getNormalizedMoveFunction(target); - - let length = moveFn.parameters.length; - if (isTxContext(moveFn.parameters[length - 1])) length = length - 1; - if (length !== moveCallInfo.arguments.length) - throw new Error( - `Function ${target.package}::${target.module}::${target.function} takes ${moveFn.parameters.length} arguments but given ${moveCallInfo.arguments.length}`, - ); - - const convertedArgs = moveCallInfo.arguments.map((arg, index) => serialize(this.tx, moveFn.parameters[index], arg)); - - return this.tx.moveCall({ - target: `${target.package}::${target.module}::${target.function}`, - arguments: convertedArgs, - typeArguments: moveCallInfo.typeArguments, - }); - } - - async publishPackage(packageName, moveDir = `${__dirname}/../move`) { - updateMoveToml(packageName, '0x0', moveDir); - - tmp.setGracefulCleanup(); - - const tmpobj = tmp.dirSync({ unsafeCleanup: true }); - - const { modules, dependencies } = JSON.parse( - execSync(`sui move build --dump-bytecode-as-base64 --path ${path.join(moveDir, packageName)} --install-dir ${tmpobj.name}`, { - encoding: 'utf-8', - stdio: 'pipe', // silent the output - }), - ); - - return this.tx.publish({ - modules, - dependencies, - }); - } - - async publishPackageAndTransferCap(packageName, to, moveDir = `${__dirname}/../move`) { - const cap = await this.publishPackage(packageName, moveDir); - - this.tx.transferObjects([cap], to); - } - - async signAndExecute(keypair, options) { - let result = await this.client.signAndExecuteTransactionBlock({ - transactionBlock: this.tx, - signer: keypair, - options: { - showEffects: true, - showObjectChanges: true, - showContent: true, - ...options, - }, - }); - if(!result.confirmedLocalExecution) { - while(true) { - try { - result = await this.client.getTransactionBlock({ - digest: result.digest, - options: { - showEffects: true, - showObjectChanges: true, - showContent: true, - ...options, - } - }); - break; - } catch(e) { - console.log(e); - await new Promise((resolve) => setTimeout(resolve, 1000)); - } - } - } - updateCache(result.objectChanges); - return result; - } - - async devInspect(sender, options) { - const result = await this.client.devInspectTransactionBlock({ - transactionBlock: this.tx, - sender, - - options: { - showEffects: true, - showObjectChanges: true, - showContent: true, - ...options, - }, - }); - return result; - } -} - -module.exports = { - TxBuilder, -}; diff --git a/scripts/utils.js b/scripts/utils.js deleted file mode 100644 index 9a7ec6c2..00000000 --- a/scripts/utils.js +++ /dev/null @@ -1,110 +0,0 @@ -const fs = require('fs'); -const { requestSuiFromFaucetV0, getFaucetHost } = require('@mysten/sui.js/faucet'); -const { getFullnodeUrl } = require('@mysten/sui.js/client'); - -function getModuleNameFromSymbol(symbol) { - function isNumber(char) { - return char >= '0' && char <= '9'; - } - - function isLowercase(char) { - return char >= 'a' && char <= 'z'; - } - - function isUppercase(char) { - return char >= 'A' && char <= 'Z'; - } - - let i = 0; - const length = symbol.length; - let moduleName = ''; - - while (isNumber(symbol[i])) { - i++; - } - - while (i < length) { - const char = symbol[i]; - - if (isLowercase(char) || isNumber(char)) { - moduleName += char; - } else if (isUppercase(char)) { - moduleName += char.toLowerCase(); - } else if (char === '_' || char === ' ') { - moduleName += '_'; - } - - i++; - } - - return moduleName; -} - -async function requestSuiFromFaucet(env, address) { - try { - await requestSuiFromFaucetV0({ - // use getFaucetHost to make sure you're using correct faucet address - // you can also just use the address (see Sui Typescript SDK Quick Start for values) - host: getFaucetHost(env.alias), - recipient: address, - }); - } catch (e) { - console.log(e); - } -} - -function updateMoveToml(packageName, packageId, moveDir = `${__dirname}/../move`) { - const path = `${moveDir}/${packageName}/Move.toml`; - - let toml = fs.readFileSync(path, 'utf8'); - - const lines = toml.split('\n'); - - const versionLineIndex = lines.findIndex((line) => line.slice(0, 7) === 'version'); - - if (!(lines[versionLineIndex + 1].slice(0, 12) === 'published-at')) { - lines.splice(versionLineIndex + 1, 0, ''); - } - - lines[versionLineIndex + 1] = `published-at = "${packageId}"`; - - const addressesIndex = lines.findIndex((line) => line.slice(0, 11) === '[addresses]'); - - for (let i = addressesIndex + 1; i < lines.length; i++) { - const line = lines[i]; - const eqIndex = line.indexOf('='); - - if ( - eqIndex < 0 || - line.slice(0, packageName.length) !== packageName || - line.slice(packageName.length, eqIndex) !== Array(eqIndex - packageName.length + 1).join(' ') - ) { - continue; - } - - lines[i] = line.slice(0, eqIndex + 1) + ` "${packageId}"`; - } - - toml = lines.join('\n'); - - fs.writeFileSync(path, toml); -} - -function parseEnv(arg) { - switch (arg?.toLowerCase()) { - case 'localnet': - case 'devnet': - case 'testnet': - case 'mainnet': - return { alias: arg, url: getFullnodeUrl(arg) }; - default: - return JSON.parse(arg); - } -} - -module.exports = { - getModuleNameFromSymbol, - parseEnv, - requestSuiFromFaucet, - updateMoveToml, -}; From 75397e484c718d3482880d513e63903f13abb18e Mon Sep 17 00:00:00 2001 From: Foivos Date: Mon, 17 Jun 2024 15:28:58 +0300 Subject: [PATCH 16/47] add an index.ts --- package.json | 2 +- src/index.ts | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 src/index.ts diff --git a/package.json b/package.json index 9ab24396..89000bff 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "type": "git", "url": "https://github.com/axelarnetwork/axelar-cgp-sui" }, - "main": "dist", + "main": "dist/index.js", "scripts": { "build": "./scripts/run.sh build", "test": "./scripts/run.sh test", diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 00000000..92d28245 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,3 @@ +export * from './bcs'; +export * from './tx-builder'; +export * from './utils'; \ No newline at end of file From 89205aebfd6f3d5d38b4f2695d38077aadec0c5d Mon Sep 17 00:00:00 2001 From: Foivos Date: Mon, 17 Jun 2024 15:48:09 +0300 Subject: [PATCH 17/47] fix imports --- src/tx-builder.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tx-builder.ts b/src/tx-builder.ts index edbbe174..1235292a 100644 --- a/src/tx-builder.ts +++ b/src/tx-builder.ts @@ -1,8 +1,8 @@ -import { TransactionArgument, TransactionBlock, TransactionObjectInput } from '@mysten/sui.js/transactions'; +import { TransactionBlock, TransactionObjectInput } from '@mysten/sui.js/transactions'; import { SuiObjectChange, SuiMoveNormalizedType, SuiClient, SuiTransactionBlockResponseOptions } from '@mysten/sui.js/client'; -import { bcs, BcsType, SerializedBcs } from '@mysten/bcs'; -import ethers from 'ethers'; -const { utils: { arrayify, hexlify }} = ethers; +import { bcs, BcsType } from '@mysten/bcs'; +import { utils as ethersUtils} from 'ethers'; +const { arrayify, hexlify } = ethersUtils; const tmp = require('tmp'); import path from 'path'; import { updateMoveToml } from './utils'; From 59237d49d33685d93f2929cec2d5e3c3ed783053 Mon Sep 17 00:00:00 2001 From: Foivos Date: Mon, 17 Jun 2024 15:55:14 +0300 Subject: [PATCH 18/47] update bcs pure types --- src/tx-builder.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tx-builder.ts b/src/tx-builder.ts index 1235292a..0e43838b 100644 --- a/src/tx-builder.ts +++ b/src/tx-builder.ts @@ -120,7 +120,7 @@ function serialize(tx: TransactionBlock, type: SuiMoveNormalizedType, arg: Trans } if (typeof type === 'string') { - return (bcs as any)[(type as string).toLowerCase()](); + return (bcs as any)[(type as string)]; } else if ((type as any).Vector) { if ((type as any).Vector === 'U8') { return vectorU8() as any; From cb32ea8b4fc5bdd00c0f42c2cfbc269d3eba25e9 Mon Sep 17 00:00:00 2001 From: Foivos Date: Mon, 17 Jun 2024 16:01:42 +0300 Subject: [PATCH 19/47] remove last change as it does not work --- src/tx-builder.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tx-builder.ts b/src/tx-builder.ts index 0e43838b..1235292a 100644 --- a/src/tx-builder.ts +++ b/src/tx-builder.ts @@ -120,7 +120,7 @@ function serialize(tx: TransactionBlock, type: SuiMoveNormalizedType, arg: Trans } if (typeof type === 'string') { - return (bcs as any)[(type as string)]; + return (bcs as any)[(type as string).toLowerCase()](); } else if ((type as any).Vector) { if ((type as any).Vector === 'U8') { return vectorU8() as any; From f192b36f946a8d65bb5c24ff37069a44a5e3d349 Mon Sep 17 00:00:00 2001 From: Foivos Date: Mon, 17 Jun 2024 16:03:42 +0300 Subject: [PATCH 20/47] add address to bcs --- src/tx-builder.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tx-builder.ts b/src/tx-builder.ts index 1235292a..19dd1f51 100644 --- a/src/tx-builder.ts +++ b/src/tx-builder.ts @@ -120,6 +120,12 @@ function serialize(tx: TransactionBlock, type: SuiMoveNormalizedType, arg: Trans } if (typeof type === 'string') { + if(type === 'Address') { + return bcs.fixedArray(32, bcs.u8()).transform({ + input: (id) => arrayify(id as any), + output: (id) => hexlify(id), + }); + } return (bcs as any)[(type as string).toLowerCase()](); } else if ((type as any).Vector) { if ((type as any).Vector === 'U8') { From bc6ecc20ad5a167ee332e83f90195052c7974f2a Mon Sep 17 00:00:00 2001 From: Foivos Date: Tue, 18 Jun 2024 13:38:45 +0300 Subject: [PATCH 21/47] shorten typeName calculation as per euro's request --- scripts/tx-builder.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/scripts/tx-builder.js b/scripts/tx-builder.js index 1c129394..6b7f1e01 100644 --- a/scripts/tx-builder.js +++ b/scripts/tx-builder.js @@ -19,15 +19,9 @@ function getObject(tx, object) { function getTypeName(type) { function get(type) { let name = `${type.address}::${type.module}::${type.name}`; - + if (type.typeArguments.length > 0) { - name += `<${type.typeArguments[0]}`; - - for (let i = 1; i < type.typeArguments.length; i++) { - name += `,${type.typeArguments[i]}`; - } - - name += '>'; + name += type.typeArguments.join(','); } return name; From 1edfffb492f7638668b1602a8afe6feae02eeb8f Mon Sep 17 00:00:00 2001 From: Foivos Date: Tue, 18 Jun 2024 13:42:15 +0300 Subject: [PATCH 22/47] prettier --- scripts/tx-builder.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/tx-builder.js b/scripts/tx-builder.js index 6b7f1e01..005558f4 100644 --- a/scripts/tx-builder.js +++ b/scripts/tx-builder.js @@ -19,7 +19,7 @@ function getObject(tx, object) { function getTypeName(type) { function get(type) { let name = `${type.address}::${type.module}::${type.name}`; - + if (type.typeArguments.length > 0) { name += type.typeArguments.join(','); } From 8aeee89e2f24fa4433e3a0fbf945810d20ac5ccc Mon Sep 17 00:00:00 2001 From: Foivos Date: Tue, 18 Jun 2024 16:32:14 +0300 Subject: [PATCH 23/47] add run.sh back --- scripts/run.sh | 20 ++++ scripts/tx-builder.js | 218 ------------------------------------------ 2 files changed, 20 insertions(+), 218 deletions(-) create mode 100644 scripts/run.sh delete mode 100644 scripts/tx-builder.js diff --git a/scripts/run.sh b/scripts/run.sh new file mode 100644 index 00000000..4f7a90c6 --- /dev/null +++ b/scripts/run.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +if [[ ${#} -ne 1 || ( "$1" != "build" && "$1" != "test" ) ]]; then + echo "Usage: $0 [build|test]" + exit 1 +fi + +exit_code=0 + +for module in ./move/*/; do + if ! sui move "$1" --lint --warnings-are-errors --path "$module"; then + exit_code=1 + fi +done + +if [ $exit_code -ne 0 ]; then + echo "" + echo -e "\033[0;31m$1 failed\033[0m" + exit 1 +fi diff --git a/scripts/tx-builder.js b/scripts/tx-builder.js deleted file mode 100644 index 0f97120c..00000000 --- a/scripts/tx-builder.js +++ /dev/null @@ -1,218 +0,0 @@ -const { TransactionBlock } = require('@mysten/sui.js/transactions'); -const { bcs } = require('@mysten/bcs'); -const { - utils: { arrayify, hexlify }, -} = require('ethers'); - -const objectCache = {}; - -function updateCache(objectChanges) { - for (const change of objectChanges) { - if (!change.objectId) continue; - objectCache[change.objectId] = change; - } -} - -function getObject(tx, object) { - if (Array.isArray(object)) { - object = hexlify(object); - } - - if (typeof object === 'string') { - const cached = objectCache[object]; - - if (cached) { - return tx.object(cached); - } - - return tx.object(object); - } - - return object; -} - -function getTypeName(type) { - function get(type) { - let name = `${type.address}::${type.module}::${type.name}`; - - if (type.typeArguments.length > 0) { - name += type.typeArguments.join(','); - } - - return name; - } - - if (type.Struct) { - return get(type.Struct); - } else if (type.Reference) { - return getTypeName(type.Reference); - } else if (type.MutableReference) { - return getTypeName(type.MutableReference); - } else if (type.Vector) { - return `vector<${getTypeName(type.Vector)}>`; - } - - return type.toLowerCase(); -} - -function getNestedStruct(tx, type, arg) { - let inside = type; - - while (inside.Vector) { - inside = inside.Vector; - } - - if (!inside.Struct && !inside.Reference && !inside.MutableReference) { - return null; - } - - if (isString(inside)) { - return null; - } - - if (type.Struct || type.Reference || type.MutableReference) { - return getObject(tx, arg); - } - - if (!type.Vector) return null; - const nested = arg.map((arg) => getNestedStruct(tx, type.Vector, arg)); - const typeName = getTypeName(type.Vector); - return tx.makeMoveVec({ - type: typeName, - objects: nested, - }); -} - -function serialize(tx, type, arg) { - const struct = getNestedStruct(tx, type, arg); - - if (struct) { - return struct; - } - - bcs.address = () => - bcs.fixedArray(32, bcs.u8()).transform({ - input: (id) => arrayify(id), - output: (id) => hexlify(id), - }); - - const vectorU8 = () => - bcs.vector(bcs.u8()).transform({ - input(input) { - if (typeof input === 'string') input = arrayify(input); - return input; - }, - }); - - const serializer = (type) => { - if (isString(type)) { - return bcs.string(); - } - - if (typeof type === 'string') { - return bcs[type.toLowerCase()](); - } else if (type.Vector) { - if (type.Vector === 'U8') { - return vectorU8(); - } - - return bcs.vector(serializer(type.Vector)); - } - - return null; - }; - - return tx.pure(serializer(type).serialize(arg).toBytes()); -} - -function isTxContext(parameter) { - parameter = parameter.MutableReference; - if (!parameter) return false; - parameter = parameter.Struct; - if (!parameter) return false; - return parameter.address === '0x2' && parameter.module === 'tx_context' && parameter.name === 'TxContext'; -} - -function isString(parameter) { - if (parameter.MutableReference) parameter = parameter.MutableReference; - if (parameter.Reference) parameter = parameter.Reference; - parameter = parameter.Struct; - if (!parameter) return false; - const isAsciiString = parameter.address === '0x1' && parameter.module === 'ascii' && parameter.name === 'String'; - const isStringString = parameter.address === '0x1' && parameter.module === 'string' && parameter.name === 'String'; - return isAsciiString || isStringString; -} - -class TxBuilder { - constructor(client) { - this.client = client; - this.tx = new TransactionBlock(); - } - - async moveCall(target, args, typeArguments = []) { - // If target is string, convert to object that `getNormalizedMoveFunction` accepts. - if (typeof target === 'string') { - const first = target.indexOf(':'); - const last = target.indexOf(':', first + 2); - const packageId = target.slice(0, first); - const module = target.slice(first + 2, last); - const functionName = target.slice(last + 2); - target = { - package: packageId, - module, - function: functionName, - }; - } - - const moveFn = await this.client.getNormalizedMoveFunction(target); - - let length = moveFn.parameters.length; - if (isTxContext(moveFn.parameters[length - 1])) length = length - 1; - if (length !== args.length) - throw new Error( - `Function ${target.package}::${target.module}::${target.function} takes ${moveFn.parameters.length} arguments but given ${args.length}`, - ); - - const convertedArgs = args.map((arg, index) => serialize(this.tx, moveFn.parameters[index], arg)); - - return this.tx.moveCall({ - target: `${target.package}::${target.module}::${target.function}`, - arguments: convertedArgs, - typeArguments, - }); - } - - async signAndExecute(keypair, options) { - const result = await this.client.signAndExecuteTransactionBlock({ - transactionBlock: this.tx, - signer: keypair, - options: { - showEffects: true, - showObjectChanges: true, - showContent: true, - ...options, - }, - }); - updateCache(result.objectChanges); - return result; - } - - async devInspect(sender, options) { - const result = await this.client.devInspectTransactionBlock({ - transactionBlock: this.tx, - sender, - - options: { - showEffects: true, - showObjectChanges: true, - showContent: true, - ...options, - }, - }); - return result; - } -} - -module.exports = { - TxBuilder, -}; From 4b1dd9c83a403b584a139db0b5584b4f673e10ec Mon Sep 17 00:00:00 2001 From: Foivos Date: Tue, 18 Jun 2024 16:32:33 +0300 Subject: [PATCH 24/47] add coverage.sh back --- scripts/coverage.sh | 59 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 scripts/coverage.sh diff --git a/scripts/coverage.sh b/scripts/coverage.sh new file mode 100644 index 00000000..1b437ab1 --- /dev/null +++ b/scripts/coverage.sh @@ -0,0 +1,59 @@ +#!/bin/sh + +export SUI=sui-debug + +# Check if sui-debug is available +if ! which "$SUI" >/dev/null 2>&1; then + echo "sui-debug not found. Setting SUI to ./sui/target/debug/sui." + + # Default to a local Sui build + export SUI="./sui/target/debug/sui" + + # Check if the file exists, install it otherwise + if [ ! -f "$SUI" ]; then + echo "Warning: $SUI not found. Installing sui-debug from scratch." + + git clone https://github.com/MystenLabs/sui.git + ( cd sui && cargo build ) + ./sui/target/debug/sui version + fi +fi + +for module in ./move/*/; do + "$SUI" move test --path "$module" --coverage & +done + +wait + +found=0 + +for module in ./move/*/; do + echo "Generating coverage info for package ${module}" + + if [ ! -f "${module}/.coverage_map.mvcov" ]; then + echo "\n NO tests found for module ${module}. Skipped.\n" >> .coverage.info + echo "\n NO tests found for module ${module}. Skipped.\n" >> .coverage.extended.info + continue + fi + + found=1 + + echo "Coverage report for module ${module}\n" >> .coverage.info + echo "Coverage report for module ${module}\n" >> .coverage.extended.info + + "$SUI" move coverage summary --path "${module}" >> .coverage.info + "$SUI" move coverage summary --summarize-functions --path "${module}" >> .coverage.extended.info + + echo "" >> .coverage.info + echo "" >> .coverage.extended.info + + # Display source code with coverage info + # find "$d/sources" -type f -name '*.move' | while IFS= read -r f; do + # "$SUI" move coverage source --path "$d" --module "$(basename "$f" .move)" + # done +done + +if [ $found -eq 0 ]; then + echo "No coverage info found. Coverage failed." + exit 1 +fi From ad10697885b8a02b26190ed1663c83514bfc526a Mon Sep 17 00:00:00 2001 From: Foivos Date: Tue, 18 Jun 2024 17:27:35 +0300 Subject: [PATCH 25/47] get eslint to work --- .eslintrc | 2 +- .prettierrc | 6 + package-lock.json | 408 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 7 +- src/index.ts | 2 +- src/tx-builder.ts | 104 +++++++----- src/utils.ts | 2 +- 7 files changed, 484 insertions(+), 47 deletions(-) diff --git a/.eslintrc b/.eslintrc index 0b44142f..5943b6a7 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,5 +1,5 @@ { - "extends": "richardpringle", + "extends": ["richardpringle", "plugin:@typescript-eslint/recommended"], "env": { "es2020": true, "mocha": true diff --git a/.prettierrc b/.prettierrc index ee79893b..70ea16e0 100644 --- a/.prettierrc +++ b/.prettierrc @@ -11,6 +11,12 @@ "trailingComma": "all" } }, + { + "files": "*.ts", + "options": { + "trailingComma": "all" + } + }, { "files": "*.json", "options": { diff --git a/package-lock.json b/package-lock.json index 263cd923..35e1c859 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,9 @@ }, "devDependencies": { "@ianvs/prettier-plugin-sort-imports": "^4.2.1", + "@types/tmp": "^0.2.6", + "@typescript-eslint/eslint-plugin": "^7.13.1", + "@typescript-eslint/parser": "^7.13.1", "dotenv": "^16.3.1", "eslint": "^8.57.0", "eslint-config-richardpringle": "^2.0.0", @@ -1701,6 +1704,233 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/tmp": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.2.6.tgz", + "integrity": "sha512-chhaNf2oKHlRkDGt+tiKE2Z5aJ6qalm7Z9rlLdBwmOiAAf09YQvvoLXjWK4HWPF1xU/fqvMgfNfpVoBscA/tKA==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.1.tgz", + "integrity": "sha512-kZqi+WZQaZfPKnsflLJQCz6Ze9FFSMfXrrIOcyargekQxG37ES7DJNpJUE9Q/X5n3yTIP/WPutVNzgknQ7biLg==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.13.1", + "@typescript-eslint/type-utils": "7.13.1", + "@typescript-eslint/utils": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.13.1.tgz", + "integrity": "sha512-1ELDPlnLvDQ5ybTSrMhRTFDfOQEOXNM+eP+3HT/Yq7ruWpciQw+Avi73pdEbA4SooCawEWo3dtYbF68gN7Ed1A==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "7.13.1", + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/typescript-estree": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.1.tgz", + "integrity": "sha512-adbXNVEs6GmbzaCpymHQ0MB6E4TqoiVbC0iqG3uijR8ZYfpAXMGttouQzF4Oat3P2GxDVIrg7bMI/P65LiQZdg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.13.1.tgz", + "integrity": "sha512-aWDbLu1s9bmgPGXSzNCxELu+0+HQOapV/y+60gPXafR8e2g1Bifxzevaa+4L2ytCWm+CHqpELq4CSoN9ELiwCg==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "7.13.1", + "@typescript-eslint/utils": "7.13.1", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.1.tgz", + "integrity": "sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.1.tgz", + "integrity": "sha512-uxNr51CMV7npU1BxZzYjoVz9iyjckBduFBP0S5sLlh1tXYzHzgZ3BR9SVsNed+LmwKrmnqN3Kdl5t7eZ5TS1Yw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.1.tgz", + "integrity": "sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.13.1", + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/typescript-estree": "7.13.1" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.1.tgz", + "integrity": "sha512-k/Bfne7lrP7hcb7m9zSsgcBmo+8eicqqfNAJ7uUY+jkTFpKeH2FSkWpFRtimBxgkyvqfu9jTPRbYOvud6isdXA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.13.1", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", @@ -1909,6 +2139,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/array.prototype.findlastindex": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", @@ -2074,6 +2313,18 @@ "concat-map": "0.0.1" } }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", @@ -2420,6 +2671,18 @@ "node": ">=6" } }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -3084,6 +3347,34 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -3117,6 +3408,18 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -3352,6 +3655,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -3691,6 +4014,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/is-number-object": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", @@ -3996,6 +4328,28 @@ "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", "peer": true }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -4294,6 +4648,15 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/periscopic": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", @@ -4320,6 +4683,18 @@ "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", "dev": true }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", @@ -4687,6 +5062,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/source-map-js": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", @@ -4890,6 +5274,30 @@ "node": ">=4" } }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", diff --git a/package.json b/package.json index 89000bff..1555acea 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,8 @@ "build": "./scripts/run.sh build", "test": "./scripts/run.sh test", "coverage": "./scripts/coverage.sh", - "lint": "eslint --fix './scripts/*.js'", - "prettier": "prettier --write './scripts/*.js'", + "lint": "eslint --fix './src/*.ts'", + "prettier": "prettier --write './src/*.ts'", "compile": "npx tsc", "postinstall": "npm run compile" }, @@ -36,6 +36,9 @@ }, "devDependencies": { "@ianvs/prettier-plugin-sort-imports": "^4.2.1", + "@types/tmp": "^0.2.6", + "@typescript-eslint/eslint-plugin": "^7.13.1", + "@typescript-eslint/parser": "^7.13.1", "dotenv": "^16.3.1", "eslint": "^8.57.0", "eslint-config-richardpringle": "^2.0.0", diff --git a/src/index.ts b/src/index.ts index 92d28245..32d7443f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,3 @@ export * from './bcs'; export * from './tx-builder'; -export * from './utils'; \ No newline at end of file +export * from './utils'; diff --git a/src/tx-builder.ts b/src/tx-builder.ts index 19dd1f51..27a8e278 100644 --- a/src/tx-builder.ts +++ b/src/tx-builder.ts @@ -1,20 +1,25 @@ -import { TransactionBlock, TransactionObjectInput } from '@mysten/sui.js/transactions'; -import { SuiObjectChange, SuiMoveNormalizedType, SuiClient, SuiTransactionBlockResponseOptions } from '@mysten/sui.js/client'; -import { bcs, BcsType } from '@mysten/bcs'; -import { utils as ethersUtils} from 'ethers'; -const { arrayify, hexlify } = ethersUtils; -const tmp = require('tmp'); -import path from 'path'; -import { updateMoveToml } from './utils'; import { execSync } from 'child_process'; +import path from 'path'; +import { bcs, BcsType } from '@mysten/bcs'; +import { SuiClient, SuiMoveNormalizedType, SuiObjectChange, SuiTransactionBlockResponseOptions } from '@mysten/sui.js/client'; import { Keypair } from '@mysten/sui.js/dist/cjs/cryptography'; +import { TransactionBlock, TransactionObjectInput } from '@mysten/sui.js/transactions'; +import { utils as ethersUtils } from 'ethers'; +import { updateMoveToml } from './utils'; +import tmp from 'tmp'; + +const { arrayify, hexlify } = ethersUtils; -const objectCache: {[id in string]: SuiObjectChange} = {}; +const objectCache = {} as { [id in string]: SuiObjectChange }; function updateCache(objectChanges: SuiObjectChange[]) { for (const change of objectChanges) { - if (!(change as any).objectId) continue; - objectCache[(change as any).objectId] = change; + if (!(change as { + objectId: string; + }).objectId) continue; + objectCache[(change as { + objectId: string; + }).objectId] = change; } } @@ -39,7 +44,9 @@ function getObject(tx: TransactionBlock, object: TransactionObjectInput) { } function getTypeName(type: SuiMoveNormalizedType): string { - function get(type: {address: string, module: string, name: string, typeArguments: string[]}) { + type Type = { address: string; module: string; name: string; typeArguments: string[] }; + + function get(type: Type) { let name = `${type.address}::${type.module}::${type.name}`; if (type.typeArguments.length > 0) { @@ -55,23 +62,24 @@ function getTypeName(type: SuiMoveNormalizedType): string { return name; } - if ((type as any).Struct) { - return get((type as any).Struct); - } else if ((type as any).Reference) { - return getTypeName((type as any).Reference); - } else if ((type as any).MutableReference) { - return getTypeName((type as any).MutableReference); - } else if ((type as any).Vector) { - return `vector<${getTypeName((type as any).Vector)}>`; + if ((type as {Struct: Type}).Struct) { + return get((type as {Struct: Type}).Struct); + } else if ((type as {Reference: SuiMoveNormalizedType}).Reference) { + return getTypeName((type as {Reference: SuiMoveNormalizedType}).Reference); + } else if ((type as {MutableReference: SuiMoveNormalizedType}).MutableReference) { + return getTypeName((type as {MutableReference: SuiMoveNormalizedType}).MutableReference); + } else if ((type as {Vector: SuiMoveNormalizedType}).Vector) { + return `vector<${getTypeName((type as {Vector: SuiMoveNormalizedType}).Vector)}>`; } return (type as string).toLowerCase(); } function getNestedStruct(tx: TransactionBlock, type: SuiMoveNormalizedType, arg: TransactionObjectInput) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any let inside = type as any; - while (inside.Vector) { + while ((inside as {Vector: SuiMoveNormalizedType}).Vector) { inside = inside.Vector; } @@ -83,20 +91,22 @@ function getNestedStruct(tx: TransactionBlock, type: SuiMoveNormalizedType, arg: return null; } + // eslint-disable-next-line @typescript-eslint/no-explicit-any if ((type as any).Struct || (type as any).Reference || (type as any).MutableReference) { return getObject(tx, arg); } - if (!(type as any).Vector) return null; + if (!(type as {Vector: SuiMoveNormalizedType}).Vector) return null; + // eslint-disable-next-line @typescript-eslint/no-explicit-any const nested = (arg as any).map((arg: any) => getNestedStruct(tx, (type as any).Vector, arg)); - const typeName = getTypeName((type as any).Vector); + const typeName = getTypeName((type as {Vector: SuiMoveNormalizedType}).Vector); return tx.makeMoveVec({ type: typeName, objects: nested, }); } -function serialize(tx: TransactionBlock, type: SuiMoveNormalizedType, arg: TransactionObjectInput ) { +function serialize(tx: TransactionBlock, type: SuiMoveNormalizedType, arg: TransactionObjectInput) { const struct = getNestedStruct(tx, type, arg); if (struct) { @@ -105,34 +115,36 @@ function serialize(tx: TransactionBlock, type: SuiMoveNormalizedType, arg: Trans const vectorU8 = () => bcs.vector(bcs.u8()).transform({ - input: (val: unknown) => { + input(val: unknown) { if (typeof val === 'string') val = arrayify(val); - return val as Iterable & { length: number; }; + return val as Iterable & { length: number }; }, - output: (value: number[]) => { + output(value: number[]) { return hexlify(value); - } + }, }); const serializer = (type: SuiMoveNormalizedType): BcsType => { if (isString(type)) { - return bcs.string() as any; + return bcs.string() as BcsType; } if (typeof type === 'string') { - if(type === 'Address') { + if (type === 'Address') { return bcs.fixedArray(32, bcs.u8()).transform({ - input: (id) => arrayify(id as any), + input: (id) => arrayify(id as number), output: (id) => hexlify(id), }); } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any return (bcs as any)[(type as string).toLowerCase()](); - } else if ((type as any).Vector) { - if ((type as any).Vector === 'U8') { - return vectorU8() as any; + } else if ((type as {Vector: SuiMoveNormalizedType}).Vector) { + if ((type as {Vector: SuiMoveNormalizedType}).Vector === 'U8') { + return vectorU8() as BcsType; } - return bcs.vector(serializer((type as any).Vector) as BcsType) as any; + return bcs.vector(serializer((type as {Vector: SuiMoveNormalizedType}).Vector)) as BcsType; } throw new Error(`Type ${JSON.stringify(type)} cannot be serialized`); @@ -142,8 +154,10 @@ function serialize(tx: TransactionBlock, type: SuiMoveNormalizedType, arg: Trans } function isTxContext(parameter: SuiMoveNormalizedType) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any let inside = parameter as any; - if(inside.MutableReference) { + + if (inside.MutableReference) { inside = inside.MutableReference.Struct; if (!inside) return false; } else if (inside.Reference) { @@ -152,10 +166,12 @@ function isTxContext(parameter: SuiMoveNormalizedType) { } else { return false; } + return inside.address === '0x2' && inside.module === 'tx_context' && inside.name === 'TxContext'; } function isString(parameter: SuiMoveNormalizedType) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any let asAny = parameter as any; if (asAny.MutableReference) parameter = asAny.MutableReference; if (asAny.Reference) asAny = asAny.Reference; @@ -177,9 +193,10 @@ class TxBuilder { async moveCall(moveCallInfo: { arguments?: TransactionObjectInput[]; typeArguments?: string[]; - target: `${string}::${string}::${string}` | {package: string, module: string, function: string}; + target: `${string}::${string}::${string}` | { package: string; module: string; function: string }; }) { let target = moveCallInfo.target; + // If target is string, convert to object that `getNormalizedMoveFunction` accepts. if (typeof target === 'string') { const first = target.indexOf(':'); @@ -198,7 +215,7 @@ class TxBuilder { let length = moveFn.parameters.length; if (isTxContext(moveFn.parameters[length - 1])) length = length - 1; - if(!moveCallInfo.arguments) moveCallInfo.arguments = []; + if (!moveCallInfo.arguments) moveCallInfo.arguments = []; if (length !== moveCallInfo.arguments.length) throw new Error( `Function ${target.package}::${target.module}::${target.function} takes ${moveFn.parameters.length} arguments but given ${moveCallInfo.arguments.length}`, @@ -208,6 +225,7 @@ class TxBuilder { return this.tx.moveCall({ target: `${target.package}::${target.module}::${target.function}`, + // eslint-disable-next-line @typescript-eslint/no-explicit-any arguments: convertedArgs as any, typeArguments: moveCallInfo.typeArguments, }); @@ -249,8 +267,9 @@ class TxBuilder { ...options, }, }); - if(!result.confirmedLocalExecution) { - while(true) { + + if (!result.confirmedLocalExecution) { + while (true) { try { result = await this.client.getTransactionBlock({ digest: result.digest, @@ -258,15 +277,16 @@ class TxBuilder { showEffects: true, showObjectChanges: true, ...options, - } + }, }); break; - } catch(e) { + } catch (e) { console.log(e); await new Promise((resolve) => setTimeout(resolve, 1000)); } } } + updateCache(result.objectChanges as SuiObjectChange[]); return result; } diff --git a/src/utils.ts b/src/utils.ts index 73c371dc..69bec017 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -82,7 +82,7 @@ export function parseEnv(arg: string) { case 'devnet': case 'testnet': case 'mainnet': - return { alias: arg, url: getFullnodeUrl(arg as "localnet" | "devnet" | "testnet" | "mainnet") }; + return { alias: arg, url: getFullnodeUrl(arg as 'localnet' | 'devnet' | 'testnet' | 'mainnet') }; default: return JSON.parse(arg); } From 4e62c8f07579cab80adbf313a3b6638528251dbd Mon Sep 17 00:00:00 2001 From: Foivos Date: Tue, 18 Jun 2024 18:21:03 +0300 Subject: [PATCH 26/47] prettier --- src/tx-builder.ts | 51 ++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/src/tx-builder.ts b/src/tx-builder.ts index 27a8e278..5ebc2ba9 100644 --- a/src/tx-builder.ts +++ b/src/tx-builder.ts @@ -5,8 +5,8 @@ import { SuiClient, SuiMoveNormalizedType, SuiObjectChange, SuiTransactionBlockR import { Keypair } from '@mysten/sui.js/dist/cjs/cryptography'; import { TransactionBlock, TransactionObjectInput } from '@mysten/sui.js/transactions'; import { utils as ethersUtils } from 'ethers'; -import { updateMoveToml } from './utils'; import tmp from 'tmp'; +import { updateMoveToml } from './utils'; const { arrayify, hexlify } = ethersUtils; @@ -14,12 +14,21 @@ const objectCache = {} as { [id in string]: SuiObjectChange }; function updateCache(objectChanges: SuiObjectChange[]) { for (const change of objectChanges) { - if (!(change as { - objectId: string; - }).objectId) continue; - objectCache[(change as { - objectId: string; - }).objectId] = change; + if ( + !( + change as { + objectId: string; + } + ).objectId + ) + continue; + objectCache[ + ( + change as { + objectId: string; + } + ).objectId + ] = change; } } @@ -62,14 +71,14 @@ function getTypeName(type: SuiMoveNormalizedType): string { return name; } - if ((type as {Struct: Type}).Struct) { - return get((type as {Struct: Type}).Struct); - } else if ((type as {Reference: SuiMoveNormalizedType}).Reference) { - return getTypeName((type as {Reference: SuiMoveNormalizedType}).Reference); - } else if ((type as {MutableReference: SuiMoveNormalizedType}).MutableReference) { - return getTypeName((type as {MutableReference: SuiMoveNormalizedType}).MutableReference); - } else if ((type as {Vector: SuiMoveNormalizedType}).Vector) { - return `vector<${getTypeName((type as {Vector: SuiMoveNormalizedType}).Vector)}>`; + if ((type as { Struct: Type }).Struct) { + return get((type as { Struct: Type }).Struct); + } else if ((type as { Reference: SuiMoveNormalizedType }).Reference) { + return getTypeName((type as { Reference: SuiMoveNormalizedType }).Reference); + } else if ((type as { MutableReference: SuiMoveNormalizedType }).MutableReference) { + return getTypeName((type as { MutableReference: SuiMoveNormalizedType }).MutableReference); + } else if ((type as { Vector: SuiMoveNormalizedType }).Vector) { + return `vector<${getTypeName((type as { Vector: SuiMoveNormalizedType }).Vector)}>`; } return (type as string).toLowerCase(); @@ -79,7 +88,7 @@ function getNestedStruct(tx: TransactionBlock, type: SuiMoveNormalizedType, arg: // eslint-disable-next-line @typescript-eslint/no-explicit-any let inside = type as any; - while ((inside as {Vector: SuiMoveNormalizedType}).Vector) { + while ((inside as { Vector: SuiMoveNormalizedType }).Vector) { inside = inside.Vector; } @@ -96,10 +105,10 @@ function getNestedStruct(tx: TransactionBlock, type: SuiMoveNormalizedType, arg: return getObject(tx, arg); } - if (!(type as {Vector: SuiMoveNormalizedType}).Vector) return null; + if (!(type as { Vector: SuiMoveNormalizedType }).Vector) return null; // eslint-disable-next-line @typescript-eslint/no-explicit-any const nested = (arg as any).map((arg: any) => getNestedStruct(tx, (type as any).Vector, arg)); - const typeName = getTypeName((type as {Vector: SuiMoveNormalizedType}).Vector); + const typeName = getTypeName((type as { Vector: SuiMoveNormalizedType }).Vector); return tx.makeMoveVec({ type: typeName, objects: nested, @@ -139,12 +148,12 @@ function serialize(tx: TransactionBlock, type: SuiMoveNormalizedType, arg: Trans // eslint-disable-next-line @typescript-eslint/no-explicit-any return (bcs as any)[(type as string).toLowerCase()](); - } else if ((type as {Vector: SuiMoveNormalizedType}).Vector) { - if ((type as {Vector: SuiMoveNormalizedType}).Vector === 'U8') { + } else if ((type as { Vector: SuiMoveNormalizedType }).Vector) { + if ((type as { Vector: SuiMoveNormalizedType }).Vector === 'U8') { return vectorU8() as BcsType; } - return bcs.vector(serializer((type as {Vector: SuiMoveNormalizedType}).Vector)) as BcsType; + return bcs.vector(serializer((type as { Vector: SuiMoveNormalizedType }).Vector)) as BcsType; } throw new Error(`Type ${JSON.stringify(type)} cannot be serialized`); From 80c6a6c96e648a0ca10a1416bee0c2790403806b Mon Sep 17 00:00:00 2001 From: Foivos Date: Wed, 19 Jun 2024 14:49:06 +0300 Subject: [PATCH 27/47] allow execution of scripts --- move/axelar_gateway/Move.lock | 2 +- move/test/Move.lock | 2 +- scripts/coverage.sh | 0 scripts/run.sh | 0 4 files changed, 2 insertions(+), 2 deletions(-) mode change 100644 => 100755 scripts/coverage.sh mode change 100644 => 100755 scripts/run.sh diff --git a/move/axelar_gateway/Move.lock b/move/axelar_gateway/Move.lock index 1242c5d3..a9960526 100644 --- a/move/axelar_gateway/Move.lock +++ b/move/axelar_gateway/Move.lock @@ -2,7 +2,7 @@ [move] version = 2 -manifest_digest = "10303CE6C59BAA2CE814E3D11BACC8CB24BE0F8D66753B02190E291CA40F0D39" +manifest_digest = "DFA4511B74DB0D387117726B3B29774671B68A69FABD22CD106286A3F83D0528" deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082" dependencies = [ { name = "Sui" }, diff --git a/move/test/Move.lock b/move/test/Move.lock index d5ba2f1e..0d5e0919 100644 --- a/move/test/Move.lock +++ b/move/test/Move.lock @@ -2,7 +2,7 @@ [move] version = 2 -manifest_digest = "6DF02196C888A850522C2336E4F8FF37DA00BCBB2240DEBF2500B46D2358E034" +manifest_digest = "AC0C11EC778EB65B6C370791BCD2EBF7AFB23F10DE58C30EB995EED85040CF5B" deps_digest = "3C4103934B1E040BB6B23F1D610B4EF9F2F1166A50A104EADCF77467C004C600" dependencies = [ { name = "AxelarGateway" }, diff --git a/scripts/coverage.sh b/scripts/coverage.sh old mode 100644 new mode 100755 diff --git a/scripts/run.sh b/scripts/run.sh old mode 100644 new mode 100755 From 8ab9ed0385e97b9202b082933c7c4bbeb1231441 Mon Sep 17 00:00:00 2001 From: Foivos Date: Wed, 19 Jun 2024 15:29:30 +0300 Subject: [PATCH 28/47] stash --- package.json | 3 ++- test/test.js | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 test/test.js diff --git a/package.json b/package.json index 1555acea..2b8e9d94 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,8 @@ "main": "dist/index.js", "scripts": { "build": "./scripts/run.sh build", - "test": "./scripts/run.sh test", + "test-move": "./scripts/run.sh test", + "test-js": "", "coverage": "./scripts/coverage.sh", "lint": "eslint --fix './src/*.ts'", "prettier": "prettier --write './src/*.ts'", diff --git a/test/test.js b/test/test.js new file mode 100644 index 00000000..f7ac20ad --- /dev/null +++ b/test/test.js @@ -0,0 +1,16 @@ + +const { TxBuilder } = require('../dist/tx-builder'); +const { SuiClient, getFullnodeUrl } = require('@mysten/sui.js/client'); + +describe('test', () => { + let client, keypair; + before(async() => { + client = new SuiClient(getFullnodeUrl('localnet')); + const builder = new TxBuilder(client); + + const response = await builder.signAndExecute(keypair); + }) + it('test', async () => { + + }); +}); \ No newline at end of file From 1cd9f11374752790f66dcb1838fc261c9cc75b9d Mon Sep 17 00:00:00 2001 From: Foivos Date: Wed, 19 Jun 2024 15:38:30 +0300 Subject: [PATCH 29/47] stash --- test/test.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/test.js b/test/test.js index f7ac20ad..52b0e3b9 100644 --- a/test/test.js +++ b/test/test.js @@ -1,4 +1,4 @@ - +require('dotenv').config(); const { TxBuilder } = require('../dist/tx-builder'); const { SuiClient, getFullnodeUrl } = require('@mysten/sui.js/client'); @@ -6,6 +6,7 @@ describe('test', () => { let client, keypair; before(async() => { client = new SuiClient(getFullnodeUrl('localnet')); + keypair = new SuiKeypair(); const builder = new TxBuilder(client); const response = await builder.signAndExecute(keypair); From fb549fa387d1a0c73ef28606f1ecb0b8b10a2ee5 Mon Sep 17 00:00:00 2001 From: Foivos Date: Wed, 19 Jun 2024 16:11:32 +0300 Subject: [PATCH 30/47] added deployment test --- .mocharc.yaml | 3 +++ move/abi/Move.lock | 2 +- move/abi/Move.toml | 4 ++-- move/axelar_gateway/Move.lock | 2 +- move/axelar_gateway/Move.toml | 4 ++-- move/gas_service/Move.lock | 2 +- move/gas_service/Move.toml | 3 ++- move/governance/Move.lock | 2 +- move/governance/Move.toml | 3 ++- move/its/Move.lock | 2 +- move/its/Move.toml | 3 ++- move/squid/Move.lock | 2 +- move/squid/Move.toml | 3 ++- test/test.js | 43 +++++++++++++++++++++++++++++++---- test/utils.js | 20 ++++++++++++++++ 15 files changed, 79 insertions(+), 19 deletions(-) create mode 100644 .mocharc.yaml create mode 100644 test/utils.js diff --git a/.mocharc.yaml b/.mocharc.yaml new file mode 100644 index 00000000..9e15fd2a --- /dev/null +++ b/.mocharc.yaml @@ -0,0 +1,3 @@ +exit: true +spec: test/**/*.js +timeout: 100000 diff --git a/move/abi/Move.lock b/move/abi/Move.lock index 75dc1a79..1db9b4db 100644 --- a/move/abi/Move.lock +++ b/move/abi/Move.lock @@ -2,7 +2,7 @@ [move] version = 2 -manifest_digest = "1250E6948210D730AADA7F51BB7CEA2D4A337A6A3D982567112494E70CC7F7BA" +manifest_digest = "89B38FFD4D0D8B2DCFE440924446CCF3A347EA904B2657C9CA229BD7BB881131" deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082" dependencies = [ { name = "Sui" }, diff --git a/move/abi/Move.toml b/move/abi/Move.toml index 0244441f..d8d50dd3 100644 --- a/move/abi/Move.toml +++ b/move/abi/Move.toml @@ -1,11 +1,11 @@ [package] name = "Abi" version = "0.1.0" -published-at = "0x09ede88971119f6a4fb5d5f5dd927fb48d1eeb92ba23a6ee696b1f51459354cb" +published-at = "0x1bc4c0259a0427f239bc6464548dc47d3beac0c2c55aec9b33323084d04dcddf" edition = "2024.beta" [dependencies] Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet-v1.25.3" } [addresses] -abi = "0x09ede88971119f6a4fb5d5f5dd927fb48d1eeb92ba23a6ee696b1f51459354cb" +abi = "0x1bc4c0259a0427f239bc6464548dc47d3beac0c2c55aec9b33323084d04dcddf" diff --git a/move/axelar_gateway/Move.lock b/move/axelar_gateway/Move.lock index a9960526..1242c5d3 100644 --- a/move/axelar_gateway/Move.lock +++ b/move/axelar_gateway/Move.lock @@ -2,7 +2,7 @@ [move] version = 2 -manifest_digest = "DFA4511B74DB0D387117726B3B29774671B68A69FABD22CD106286A3F83D0528" +manifest_digest = "10303CE6C59BAA2CE814E3D11BACC8CB24BE0F8D66753B02190E291CA40F0D39" deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082" dependencies = [ { name = "Sui" }, diff --git a/move/axelar_gateway/Move.toml b/move/axelar_gateway/Move.toml index 1e6bf58a..ecaaddac 100644 --- a/move/axelar_gateway/Move.toml +++ b/move/axelar_gateway/Move.toml @@ -1,12 +1,12 @@ [package] name = "AxelarGateway" version = "0.1.0" -published-at = "0xdd3b165835ec3d510016f8492519feb74a631f235f0126f44fec079c8aa81186" +published-at = "0x1611b7e3e958f74e4ef9f4727333a98d095a9f71baf4c814d310d986db1f5662" edition = "2024.beta" [dependencies] Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet-v1.25.3" } [addresses] -axelar_gateway = "0xdd3b165835ec3d510016f8492519feb74a631f235f0126f44fec079c8aa81186" +axelar_gateway = "0x1611b7e3e958f74e4ef9f4727333a98d095a9f71baf4c814d310d986db1f5662" clock = "0x6" diff --git a/move/gas_service/Move.lock b/move/gas_service/Move.lock index 04215722..5cc24c5f 100644 --- a/move/gas_service/Move.lock +++ b/move/gas_service/Move.lock @@ -2,7 +2,7 @@ [move] version = 2 -manifest_digest = "C1DEC087FF16954984395BB68E2E81D4A38E64A7F0BAB88AAF73A121C563E2D4" +manifest_digest = "A020C8D244BDE64D6F5F3107506F682AEA99E933953DE1FB01352999724E43EB" deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082" dependencies = [ { name = "Sui" }, diff --git a/move/gas_service/Move.toml b/move/gas_service/Move.toml index 49ee70fc..9c83307d 100644 --- a/move/gas_service/Move.toml +++ b/move/gas_service/Move.toml @@ -1,10 +1,11 @@ [package] name = "GasService" version = "0.1.0" +published-at = "0xe356c310916a4f0c76a2c50b1101f66a328eee2626f709b1138e5ca2a537d438" edition = "2024.beta" [dependencies] Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet-v1.25.3" } [addresses] -gas_service = "0x105" +gas_service = "0xe356c310916a4f0c76a2c50b1101f66a328eee2626f709b1138e5ca2a537d438" diff --git a/move/governance/Move.lock b/move/governance/Move.lock index 096fd921..a4cb0602 100644 --- a/move/governance/Move.lock +++ b/move/governance/Move.lock @@ -2,7 +2,7 @@ [move] version = 2 -manifest_digest = "4F26118CD341A5D382F6D63184C33AE0DEFBC380DA34B844908B98C7C2B228D9" +manifest_digest = "9DC4C192CAEBB80F2FBB1DC3CCEC7F9714E98AF18EBC9396F08BDB826A59E4F3" deps_digest = "060AD7E57DFB13104F21BE5F5C3759D03F0553FC3229247D9A7A6B45F50D03A3" dependencies = [ { name = "Abi" }, diff --git a/move/governance/Move.toml b/move/governance/Move.toml index f45f85da..59b7e05a 100644 --- a/move/governance/Move.toml +++ b/move/governance/Move.toml @@ -1,6 +1,7 @@ [package] name = "Governance" version = "0.1.0" +published-at = "0x5b07e6dd81eda8900a3f7e5cab693a0b9e32eaec30d27f26830611e536dead13" edition = "2024.beta" [dependencies] @@ -9,4 +10,4 @@ AxelarGateway = { local = "../axelar_gateway" } Abi = { local = "../abi" } [addresses] -governance = "0x101" +governance = "0x5b07e6dd81eda8900a3f7e5cab693a0b9e32eaec30d27f26830611e536dead13" diff --git a/move/its/Move.lock b/move/its/Move.lock index d45ae8ec..c52c3519 100644 --- a/move/its/Move.lock +++ b/move/its/Move.lock @@ -2,7 +2,7 @@ [move] version = 2 -manifest_digest = "8EB070D5A26ADEEBB191384EDCD8FE28EE8539D051B47C110ACB2E1BC0675B6A" +manifest_digest = "C47498B72EFC749BF4D0D66D86BC3702ADBFBD16CF406FA05127DAD55FBE28C4" deps_digest = "060AD7E57DFB13104F21BE5F5C3759D03F0553FC3229247D9A7A6B45F50D03A3" dependencies = [ { name = "AxelarGateway" }, diff --git a/move/its/Move.toml b/move/its/Move.toml index cc9d85d2..d11a4805 100644 --- a/move/its/Move.toml +++ b/move/its/Move.toml @@ -1,6 +1,7 @@ [package] name = "ITS" version = "0.1.0" +published-at = "0x542952f6e1278d7183d2fe788efe472a96f204c45328af28fa4e6fba36b432f2" edition = "2024.beta" [dependencies] @@ -9,4 +10,4 @@ AxelarGateway = { local = "../axelar_gateway" } Governance = { local = "../governance" } [addresses] -its = "0x102" +its = "0x542952f6e1278d7183d2fe788efe472a96f204c45328af28fa4e6fba36b432f2" diff --git a/move/squid/Move.lock b/move/squid/Move.lock index f7bcfa21..f6bf9855 100644 --- a/move/squid/Move.lock +++ b/move/squid/Move.lock @@ -2,7 +2,7 @@ [move] version = 2 -manifest_digest = "9568F12CBDAE1FD019A32A5F77C0B7CF8038887E8FAFE61D45CD75757251E932" +manifest_digest = "384A3D94552582FBDD012034F0BE9AC30A837A35416FCCFBA340F7C3597FB0D3" deps_digest = "F9B494B64F0615AED0E98FC12A85B85ECD2BC5185C22D30E7F67786BB52E507C" dependencies = [ { name = "AxelarGateway" }, diff --git a/move/squid/Move.toml b/move/squid/Move.toml index 5501ade5..1b8474ec 100644 --- a/move/squid/Move.toml +++ b/move/squid/Move.toml @@ -1,6 +1,7 @@ [package] name = "Squid" version = "0.1.0" +published-at = "0x0" edition = "2024.beta" [dependencies] @@ -10,4 +11,4 @@ AxelarGateway = { local = "../axelar_gateway" } ITS = { local = "../its" } [addresses] -squid = "0x104" +squid = "0x0" diff --git a/test/test.js b/test/test.js index 52b0e3b9..9e3c1e9d 100644 --- a/test/test.js +++ b/test/test.js @@ -1,16 +1,49 @@ require('dotenv').config(); const { TxBuilder } = require('../dist/tx-builder'); const { SuiClient, getFullnodeUrl } = require('@mysten/sui.js/client'); +const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); +const { requestSuiFromFaucetV0, getFaucetHost } = require('@mysten/sui.js/faucet'); +const { publishPackage } = require('./utils'); describe('test', () => { let client, keypair; before(async() => { - client = new SuiClient(getFullnodeUrl('localnet')); - keypair = new SuiKeypair(); - const builder = new TxBuilder(client); + client = new SuiClient({ url: getFullnodeUrl('localnet') }); + const privKey = Buffer.from(process.env.SUI_PRIVATE_KEY, 'hex'); - const response = await builder.signAndExecute(keypair); - }) + keypair = Ed25519Keypair.fromSecretKey(privKey); + await requestSuiFromFaucetV0({ + host: getFaucetHost('localnet'), + recipient: keypair.toSuiAddress(), + }); + let result = await publishPackage(client, keypair, 'abi'); + const abiPackageId = result.packageId; + const abiCap = result.publishTxn.objectChanges.find((change) => change.objectType === `0x2::package::UpgradeCap`).objectId; + + result = await publishPackage(client, keypair, 'axelar_gateway'); + const axelarPackageId = result.packageId; + const axelarCap = result.publishTxn.objectChanges.find((change) => change.objectType === `0x2::package::UpgradeCap`).objectId; + + result = await publishPackage(client, keypair, 'gas_service'); + const gasServicePackageId = result.packageId; + const gasServiceCap = result.publishTxn.objectChanges.find((change) => change.objectType === `0x2::package::UpgradeCap`).objectId; + + result = await publishPackage(client, keypair, 'governance'); + const governancePackageId = result.packageId; + const governanceCap = result.publishTxn.objectChanges.find((change) => change.objectType === `0x2::package::UpgradeCap`).objectId; + + result = await publishPackage(client, keypair, 'its'); + const itsPackageId = result.packageId; + const itsCap = result.publishTxn.objectChanges.find((change) => change.objectType === `0x2::package::UpgradeCap`).objectId; + + result = await publishPackage(client, keypair, 'squid'); + const squidPackageId = result.packageId; + const squidCap = result.publishTxn.objectChanges.find((change) => change.objectType === `0x2::package::UpgradeCap`).objectId; + + result = await publishPackage(client, keypair, 'test'); + const testPackageId = result.packageId; + const testCap = result.publishTxn.objectChanges.find((change) => change.objectType === `0x2::package::UpgradeCap`).objectId; + }); it('test', async () => { }); diff --git a/test/utils.js b/test/utils.js new file mode 100644 index 00000000..ed2bed3a --- /dev/null +++ b/test/utils.js @@ -0,0 +1,20 @@ + +require('dotenv').config(); +const { TxBuilder } = require('../dist/tx-builder'); +const { updateMoveToml } = require('../dist/utils'); + + +async function publishPackage(client, keypair, packageName) { + const builder = new TxBuilder(client); + await builder.publishPackageAndTransferCap(packageName, keypair.toSuiAddress()); + const publishTxn = await builder.signAndExecute(keypair); + + const packageId = (publishTxn.objectChanges?.find((a) => a.type === 'published') ?? []).packageId; + + updateMoveToml(packageName, packageId); + return { packageId, publishTxn }; +} + +module.exports = { + publishPackage, +} \ No newline at end of file From 4886636fbba4e666e2179a0d31653eda7cf52b5c Mon Sep 17 00:00:00 2001 From: Foivos Date: Wed, 19 Jun 2024 16:12:14 +0300 Subject: [PATCH 31/47] fix package scripts --- move/squid/Move.toml | 4 ++-- move/test/Move.lock | 2 +- move/test/Move.toml | 4 ++-- package.json | 3 ++- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/move/squid/Move.toml b/move/squid/Move.toml index 1b8474ec..cbe516a5 100644 --- a/move/squid/Move.toml +++ b/move/squid/Move.toml @@ -1,7 +1,7 @@ [package] name = "Squid" version = "0.1.0" -published-at = "0x0" +published-at = "0x69c9099c4b7da929dca09ac9991163b6e7d3c3fc0e3b9c692ed0c3f02dae16ff" edition = "2024.beta" [dependencies] @@ -11,4 +11,4 @@ AxelarGateway = { local = "../axelar_gateway" } ITS = { local = "../its" } [addresses] -squid = "0x0" +squid = "0x69c9099c4b7da929dca09ac9991163b6e7d3c3fc0e3b9c692ed0c3f02dae16ff" diff --git a/move/test/Move.lock b/move/test/Move.lock index 0d5e0919..d5ba2f1e 100644 --- a/move/test/Move.lock +++ b/move/test/Move.lock @@ -2,7 +2,7 @@ [move] version = 2 -manifest_digest = "AC0C11EC778EB65B6C370791BCD2EBF7AFB23F10DE58C30EB995EED85040CF5B" +manifest_digest = "6DF02196C888A850522C2336E4F8FF37DA00BCBB2240DEBF2500B46D2358E034" deps_digest = "3C4103934B1E040BB6B23F1D610B4EF9F2F1166A50A104EADCF77467C004C600" dependencies = [ { name = "AxelarGateway" }, diff --git a/move/test/Move.toml b/move/test/Move.toml index 2beb8b56..bf0cd676 100644 --- a/move/test/Move.toml +++ b/move/test/Move.toml @@ -1,7 +1,7 @@ [package] name = "Test" version = "0.1.0" -published-at = "0x3416821971d670acd3a1b8556d2df99bda3cd35c49d581c7ece89aca0137af4d" +published-at = "0x9110bc3d96f77d7ddd6ef058627fb9369c6bfbedfb169228e9d20959a5f893cd" edition = "2024.beta" [dependencies] @@ -9,4 +9,4 @@ Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-fram AxelarGateway = { local = "../axelar_gateway" } [addresses] -test = "0x3416821971d670acd3a1b8556d2df99bda3cd35c49d581c7ece89aca0137af4d" +test = "0x9110bc3d96f77d7ddd6ef058627fb9369c6bfbedfb169228e9d20959a5f893cd" diff --git a/package.json b/package.json index 2b8e9d94..401e0cd6 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "scripts": { "build": "./scripts/run.sh build", "test-move": "./scripts/run.sh test", - "test-js": "", + "test-js": "npx mocha", + "test": "npm run test-move && npm run test-js", "coverage": "./scripts/coverage.sh", "lint": "eslint --fix './src/*.ts'", "prettier": "prettier --write './src/*.ts'", From 5774306ed8765f71d3a2b3be9b0e047317d8d248 Mon Sep 17 00:00:00 2001 From: Foivos Date: Wed, 19 Jun 2024 16:17:51 +0300 Subject: [PATCH 32/47] prettier and include mocha --- move/abi/Move.toml | 4 ++-- package.json | 7 ++++--- test/test.js | 11 ++++------- test/utils.js | 21 +++++++++------------ 4 files changed, 19 insertions(+), 24 deletions(-) diff --git a/move/abi/Move.toml b/move/abi/Move.toml index d8d50dd3..459fdd59 100644 --- a/move/abi/Move.toml +++ b/move/abi/Move.toml @@ -1,11 +1,11 @@ [package] name = "Abi" version = "0.1.0" -published-at = "0x1bc4c0259a0427f239bc6464548dc47d3beac0c2c55aec9b33323084d04dcddf" +published-at = "0x0" edition = "2024.beta" [dependencies] Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet-v1.25.3" } [addresses] -abi = "0x1bc4c0259a0427f239bc6464548dc47d3beac0c2c55aec9b33323084d04dcddf" +abi = "0x0" diff --git a/package.json b/package.json index 401e0cd6..ff954392 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,8 @@ "test-js": "npx mocha", "test": "npm run test-move && npm run test-js", "coverage": "./scripts/coverage.sh", - "lint": "eslint --fix './src/*.ts'", - "prettier": "prettier --write './src/*.ts'", + "lint": "eslint --fix './src/*.ts' './test/*.js'", + "prettier": "prettier --write './src/*.ts' './test/*.js'", "compile": "npx tsc", "postinstall": "npm run compile" }, @@ -45,7 +45,8 @@ "eslint": "^8.57.0", "eslint-config-richardpringle": "^2.0.0", "prettier": "^2.8.7", - "prettier-plugin-sort-imports": "^1.8.5" + "prettier-plugin-sort-imports": "^1.8.5", + "mocha": "^10.4.0" }, "description": "Axelar Sui Move contracts" } diff --git a/test/test.js b/test/test.js index 9e3c1e9d..ee9daeb0 100644 --- a/test/test.js +++ b/test/test.js @@ -1,5 +1,4 @@ require('dotenv').config(); -const { TxBuilder } = require('../dist/tx-builder'); const { SuiClient, getFullnodeUrl } = require('@mysten/sui.js/client'); const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); const { requestSuiFromFaucetV0, getFaucetHost } = require('@mysten/sui.js/faucet'); @@ -7,7 +6,7 @@ const { publishPackage } = require('./utils'); describe('test', () => { let client, keypair; - before(async() => { + before(async () => { client = new SuiClient({ url: getFullnodeUrl('localnet') }); const privKey = Buffer.from(process.env.SUI_PRIVATE_KEY, 'hex'); @@ -39,12 +38,10 @@ describe('test', () => { result = await publishPackage(client, keypair, 'squid'); const squidPackageId = result.packageId; const squidCap = result.publishTxn.objectChanges.find((change) => change.objectType === `0x2::package::UpgradeCap`).objectId; - + result = await publishPackage(client, keypair, 'test'); const testPackageId = result.packageId; const testCap = result.publishTxn.objectChanges.find((change) => change.objectType === `0x2::package::UpgradeCap`).objectId; }); - it('test', async () => { - - }); -}); \ No newline at end of file + it('test', async () => {}); +}); diff --git a/test/utils.js b/test/utils.js index ed2bed3a..f491cae8 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,20 +1,17 @@ - -require('dotenv').config(); -const { TxBuilder } = require('../dist/tx-builder'); -const { updateMoveToml } = require('../dist/utils'); - +const { TxBuilder } = require('../dist/tx-builder'); +const { updateMoveToml } = require('../dist/utils'); async function publishPackage(client, keypair, packageName) { - const builder = new TxBuilder(client); - await builder.publishPackageAndTransferCap(packageName, keypair.toSuiAddress()); - const publishTxn = await builder.signAndExecute(keypair); + const builder = new TxBuilder(client); + await builder.publishPackageAndTransferCap(packageName, keypair.toSuiAddress()); + const publishTxn = await builder.signAndExecute(keypair); - const packageId = (publishTxn.objectChanges?.find((a) => a.type === 'published') ?? []).packageId; + const packageId = (publishTxn.objectChanges?.find((a) => a.type === 'published') ?? []).packageId; - updateMoveToml(packageName, packageId); - return { packageId, publishTxn }; + updateMoveToml(packageName, packageId); + return { packageId, publishTxn }; } module.exports = { publishPackage, -} \ No newline at end of file +}; From d0a487940710ae32f9ae0f8939a58abd41f31d2f Mon Sep 17 00:00:00 2001 From: Foivos Date: Wed, 19 Jun 2024 16:19:01 +0300 Subject: [PATCH 33/47] remove .env dependancy --- test/test.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/test.js b/test/test.js index ee9daeb0..62ee0cae 100644 --- a/test/test.js +++ b/test/test.js @@ -1,4 +1,3 @@ -require('dotenv').config(); const { SuiClient, getFullnodeUrl } = require('@mysten/sui.js/client'); const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); const { requestSuiFromFaucetV0, getFaucetHost } = require('@mysten/sui.js/faucet'); @@ -8,7 +7,7 @@ describe('test', () => { let client, keypair; before(async () => { client = new SuiClient({ url: getFullnodeUrl('localnet') }); - const privKey = Buffer.from(process.env.SUI_PRIVATE_KEY, 'hex'); + const privKey = Buffer.from('9027dcb35b21318572bda38641b394eb33896aa81878a4f0e7066b119a9ea000', 'hex'); keypair = Ed25519Keypair.fromSecretKey(privKey); await requestSuiFromFaucetV0({ From b143ef4aaf804081d30f9b9a124d05b2fd6aba23 Mon Sep 17 00:00:00 2001 From: Foivos Date: Thu, 20 Jun 2024 17:14:20 +0300 Subject: [PATCH 34/47] added a test to rotate signers --- move/abi/Move.toml | 4 +- move/axelar_gateway/Move.toml | 4 +- move/gas_service/Move.toml | 4 +- move/governance/Move.toml | 4 +- move/its/Move.toml | 4 +- move/squid/Move.toml | 4 +- move/test/Move.toml | 4 +- test/axelar-gateway.js | 150 ++++++++++++++++++++++++++++++++++ test/utils.js | 6 ++ 9 files changed, 170 insertions(+), 14 deletions(-) create mode 100644 test/axelar-gateway.js diff --git a/move/abi/Move.toml b/move/abi/Move.toml index 459fdd59..12c189a0 100644 --- a/move/abi/Move.toml +++ b/move/abi/Move.toml @@ -1,11 +1,11 @@ [package] name = "Abi" version = "0.1.0" -published-at = "0x0" +published-at = "0x845c6fa54ccb69bde81098dabac0e1fb11dd9ae217a034992203ce99801a3b67" edition = "2024.beta" [dependencies] Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet-v1.25.3" } [addresses] -abi = "0x0" +abi = "0x845c6fa54ccb69bde81098dabac0e1fb11dd9ae217a034992203ce99801a3b67" diff --git a/move/axelar_gateway/Move.toml b/move/axelar_gateway/Move.toml index ecaaddac..54cef027 100644 --- a/move/axelar_gateway/Move.toml +++ b/move/axelar_gateway/Move.toml @@ -1,12 +1,12 @@ [package] name = "AxelarGateway" version = "0.1.0" -published-at = "0x1611b7e3e958f74e4ef9f4727333a98d095a9f71baf4c814d310d986db1f5662" +published-at = "0x7bc9ff900d613dba5c53b5f84869a229ebb791be61b6f30cfec6d4f6130492c7" edition = "2024.beta" [dependencies] Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet-v1.25.3" } [addresses] -axelar_gateway = "0x1611b7e3e958f74e4ef9f4727333a98d095a9f71baf4c814d310d986db1f5662" +axelar_gateway = "0x7bc9ff900d613dba5c53b5f84869a229ebb791be61b6f30cfec6d4f6130492c7" clock = "0x6" diff --git a/move/gas_service/Move.toml b/move/gas_service/Move.toml index 9c83307d..2d976108 100644 --- a/move/gas_service/Move.toml +++ b/move/gas_service/Move.toml @@ -1,11 +1,11 @@ [package] name = "GasService" version = "0.1.0" -published-at = "0xe356c310916a4f0c76a2c50b1101f66a328eee2626f709b1138e5ca2a537d438" +published-at = "0x9249adc3fac09edb21a0848af2ccf4901ffb3689124bc91d67bc613903ca643c" edition = "2024.beta" [dependencies] Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet-v1.25.3" } [addresses] -gas_service = "0xe356c310916a4f0c76a2c50b1101f66a328eee2626f709b1138e5ca2a537d438" +gas_service = "0x9249adc3fac09edb21a0848af2ccf4901ffb3689124bc91d67bc613903ca643c" diff --git a/move/governance/Move.toml b/move/governance/Move.toml index 59b7e05a..ac50d7ee 100644 --- a/move/governance/Move.toml +++ b/move/governance/Move.toml @@ -1,7 +1,7 @@ [package] name = "Governance" version = "0.1.0" -published-at = "0x5b07e6dd81eda8900a3f7e5cab693a0b9e32eaec30d27f26830611e536dead13" +published-at = "0x0cba440261d721bde9c85eafe18aae673ee72702fa95da567675b34224f5ad77" edition = "2024.beta" [dependencies] @@ -10,4 +10,4 @@ AxelarGateway = { local = "../axelar_gateway" } Abi = { local = "../abi" } [addresses] -governance = "0x5b07e6dd81eda8900a3f7e5cab693a0b9e32eaec30d27f26830611e536dead13" +governance = "0x0cba440261d721bde9c85eafe18aae673ee72702fa95da567675b34224f5ad77" diff --git a/move/its/Move.toml b/move/its/Move.toml index d11a4805..ab5ee59d 100644 --- a/move/its/Move.toml +++ b/move/its/Move.toml @@ -1,7 +1,7 @@ [package] name = "ITS" version = "0.1.0" -published-at = "0x542952f6e1278d7183d2fe788efe472a96f204c45328af28fa4e6fba36b432f2" +published-at = "0x89967fea5cc3bdf2d44cabe901aca920aa2a0485ca9a479f9932814c55d5f9b3" edition = "2024.beta" [dependencies] @@ -10,4 +10,4 @@ AxelarGateway = { local = "../axelar_gateway" } Governance = { local = "../governance" } [addresses] -its = "0x542952f6e1278d7183d2fe788efe472a96f204c45328af28fa4e6fba36b432f2" +its = "0x89967fea5cc3bdf2d44cabe901aca920aa2a0485ca9a479f9932814c55d5f9b3" diff --git a/move/squid/Move.toml b/move/squid/Move.toml index cbe516a5..6f3d465d 100644 --- a/move/squid/Move.toml +++ b/move/squid/Move.toml @@ -1,7 +1,7 @@ [package] name = "Squid" version = "0.1.0" -published-at = "0x69c9099c4b7da929dca09ac9991163b6e7d3c3fc0e3b9c692ed0c3f02dae16ff" +published-at = "0x742acc52f94b86d3a2a4fdc39b1e0d75812f05253f88443754326c1e31cae873" edition = "2024.beta" [dependencies] @@ -11,4 +11,4 @@ AxelarGateway = { local = "../axelar_gateway" } ITS = { local = "../its" } [addresses] -squid = "0x69c9099c4b7da929dca09ac9991163b6e7d3c3fc0e3b9c692ed0c3f02dae16ff" +squid = "0x742acc52f94b86d3a2a4fdc39b1e0d75812f05253f88443754326c1e31cae873" diff --git a/move/test/Move.toml b/move/test/Move.toml index bf0cd676..24579009 100644 --- a/move/test/Move.toml +++ b/move/test/Move.toml @@ -1,7 +1,7 @@ [package] name = "Test" version = "0.1.0" -published-at = "0x9110bc3d96f77d7ddd6ef058627fb9369c6bfbedfb169228e9d20959a5f893cd" +published-at = "0x64cb77be32074cff87043543664dafb4eb766f980d08694cffca8c8136321872" edition = "2024.beta" [dependencies] @@ -9,4 +9,4 @@ Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-fram AxelarGateway = { local = "../axelar_gateway" } [addresses] -test = "0x9110bc3d96f77d7ddd6ef058627fb9369c6bfbedfb169228e9d20959a5f893cd" +test = "0x64cb77be32074cff87043543664dafb4eb766f980d08694cffca8c8136321872" diff --git a/test/axelar-gateway.js b/test/axelar-gateway.js new file mode 100644 index 00000000..f44492a7 --- /dev/null +++ b/test/axelar-gateway.js @@ -0,0 +1,150 @@ +const { SuiClient, getFullnodeUrl } = require('@mysten/sui.js/client'); +const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); +const { Secp256k1Keypair } = require('@mysten/sui.js/keypairs/secp256k1'); +const { requestSuiFromFaucetV0, getFaucetHost } = require('@mysten/sui.js/faucet'); +const { publishPackage, getRandomBytes32 } = require('./utils'); +const { TxBuilder } = require('../dist/tx-builder'); +const { bcsStructs: { axelarStructs } } = require('../dist/bcs'); +const { arrayify, hexlify, keccak256 } = require('ethers/lib/utils'); +const secp256k1 = require('secp256k1'); + +const COMMAND_TYPE_ROTATE_SIGNERS = 1; + +describe.only('test', () => { + let client; + const operator = Ed25519Keypair.fromSecretKey(arrayify(getRandomBytes32())); + const deployer = Ed25519Keypair.fromSecretKey(arrayify(getRandomBytes32())); + const keypair = Ed25519Keypair.fromSecretKey(arrayify(getRandomBytes32())); + const domainSeparator = getRandomBytes32(); + let operatorKeys; + let signers; + let nonce = 0; + let packageId; + + + function calculateNextSigners() { + operatorKeys = [getRandomBytes32(), getRandomBytes32(), getRandomBytes32()]; + pubkeys = operatorKeys.map(key => Secp256k1Keypair.fromSecretKey(arrayify(key)).getPublicKey().toRawBytes()); + const keys = operatorKeys.map((key,index) => { return { privkey: key, pubkey: pubkeys[index]} }); + keys.sort((key1, key2) => { + for(let i = 0; i < 33; i ++) { + if (key1.pubkey[i] < key2.pubkey[i]) return -1; + if (key1.pubkey[i] > key2.pubkey[i]) return 1; + } + return 0; + }); + operatorKeys = keys.map(key => key.privkey); + signers = { + signers: keys.map((key) => { + return { pubkey: key.pubkey, weight: 1 }; + }), + threshold: 2, + nonce: hexlify([++nonce]), + }; + } + + function hashMessage(data) { + const toHash = new Uint8Array(data.length + 1); + toHash[0] = COMMAND_TYPE_ROTATE_SIGNERS; + toHash.set(data, 1); + + return keccak256(toHash); + } + + function sign(privKeys, messageToSign) { + const signatures = []; + for(const privKey of privKeys) { + const { signature, recid } = secp256k1.ecdsaSign(arrayify(keccak256(messageToSign)), arrayify(privKey)); + signatures.push(new Uint8Array([...signature, recid])); + } + return signatures; + } + + async function sleep(ms = 1000) { + await new Promise((resolve) => setTimeout(resolve, ms)); + } + + const minimumRotationDelay = 1000; + before(async () => { + client = new SuiClient({ url: getFullnodeUrl('localnet') }); + + await Promise.all([operator, deployer, keypair].map( + (keypair) => requestSuiFromFaucetV0({ + host: getFaucetHost('localnet'), + recipient: keypair.toSuiAddress(), + }) + )) + + let result = await publishPackage(client, deployer, 'axelar_gateway'); + packageId = result.packageId; + const creatorCap = result.publishTxn.objectChanges.find((change) => change.objectType === `${packageId}::gateway::CreatorCap`).objectId; + + calculateNextSigners(); + + const encodedSigners = axelarStructs.WeightedSigners.serialize(signers).toBytes(); + const builder = new TxBuilder(client); + + const separator = await builder.moveCall({ + target: `${packageId}::bytes32::new`, + arguments: [domainSeparator], + }); + + await builder.moveCall({ + target: `${packageId}::gateway::setup`, + arguments: [ + creatorCap, + operator.toSuiAddress(), + separator, + minimumRotationDelay, + encodedSigners, + '0x6', + ] + }); + + result = await builder.signAndExecute(deployer); + + gateway = result.objectChanges.find((change) => change.objectType === `${packageId}::gateway::Gateway`).objectId; + }); + it('Should Rotate Signers', async () => { + await sleep(2000); + const proofSigners = signers; + const proofKeys = operatorKeys; + calculateNextSigners(); + + const encodedSigners = axelarStructs.WeightedSigners + .serialize(signers) + .toBytes(); + + const hashed = hashMessage(encodedSigners); + + const message = axelarStructs.MessageToSign + .serialize({ + domain_separator: domainSeparator, + signers_hash: keccak256(axelarStructs.WeightedSigners.serialize(proofSigners).toBytes()), + data_hash: hashed, + }) + .toBytes(); + + const signatures = sign(proofKeys, message); + const encodedProof = axelarStructs.Proof + .serialize({ + signers: proofSigners, + signatures, + }) + .toBytes(); + + const builder = new TxBuilder(client); + + await builder.moveCall({ + target: `${packageId}::gateway::rotate_signers`, + arguments: [ + gateway, + '0x6', + encodedSigners, + encodedProof, + ], + }); + + await builder.signAndExecute(keypair); + }); +}); diff --git a/test/utils.js b/test/utils.js index f491cae8..54762e5b 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,3 +1,4 @@ +const { keccak256, defaultAbiCoder } = require('ethers/lib/utils'); const { TxBuilder } = require('../dist/tx-builder'); const { updateMoveToml } = require('../dist/utils'); @@ -12,6 +13,11 @@ async function publishPackage(client, keypair, packageName) { return { packageId, publishTxn }; } +function getRandomBytes32() { + return keccak256(defaultAbiCoder.encode(['string'], [Math.random().toString()])); +} + module.exports = { publishPackage, + getRandomBytes32, }; From f71d272f2a970eba273b74fe1637dc8ca52f3705 Mon Sep 17 00:00:00 2001 From: Foivos Date: Fri, 21 Jun 2024 14:11:49 +0300 Subject: [PATCH 35/47] Add a revert util and test --- .mocharc.yaml | 2 +- move/axelar_gateway/Move.toml | 4 +-- test/axelar-gateway.js | 58 +++++++++++++++++++++++++++++++++-- test/utils.js | 37 ++++++++++++++++++++++ 4 files changed, 96 insertions(+), 5 deletions(-) diff --git a/.mocharc.yaml b/.mocharc.yaml index 9e15fd2a..0dacec69 100644 --- a/.mocharc.yaml +++ b/.mocharc.yaml @@ -1,3 +1,3 @@ exit: true spec: test/**/*.js -timeout: 100000 +timeout: 300000 diff --git a/move/axelar_gateway/Move.toml b/move/axelar_gateway/Move.toml index 54cef027..df8f1591 100644 --- a/move/axelar_gateway/Move.toml +++ b/move/axelar_gateway/Move.toml @@ -1,12 +1,12 @@ [package] name = "AxelarGateway" version = "0.1.0" -published-at = "0x7bc9ff900d613dba5c53b5f84869a229ebb791be61b6f30cfec6d4f6130492c7" +published-at = "0x8fd4826963d7fac11825df329a1460a49eb782d9719ad362c97e5e3c225fc748" edition = "2024.beta" [dependencies] Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet-v1.25.3" } [addresses] -axelar_gateway = "0x7bc9ff900d613dba5c53b5f84869a229ebb791be61b6f30cfec6d4f6130492c7" +axelar_gateway = "0x8fd4826963d7fac11825df329a1460a49eb782d9719ad362c97e5e3c225fc748" clock = "0x6" diff --git a/test/axelar-gateway.js b/test/axelar-gateway.js index f44492a7..e388273b 100644 --- a/test/axelar-gateway.js +++ b/test/axelar-gateway.js @@ -2,7 +2,7 @@ const { SuiClient, getFullnodeUrl } = require('@mysten/sui.js/client'); const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); const { Secp256k1Keypair } = require('@mysten/sui.js/keypairs/secp256k1'); const { requestSuiFromFaucetV0, getFaucetHost } = require('@mysten/sui.js/faucet'); -const { publishPackage, getRandomBytes32 } = require('./utils'); +const { publishPackage, getRandomBytes32, expectRevert } = require('./utils'); const { TxBuilder } = require('../dist/tx-builder'); const { bcsStructs: { axelarStructs } } = require('../dist/bcs'); const { arrayify, hexlify, keccak256 } = require('ethers/lib/utils'); @@ -65,6 +65,7 @@ describe.only('test', () => { } const minimumRotationDelay = 1000; + before(async () => { client = new SuiClient({ url: getFullnodeUrl('localnet') }); @@ -105,7 +106,8 @@ describe.only('test', () => { gateway = result.objectChanges.find((change) => change.objectType === `${packageId}::gateway::Gateway`).objectId; }); - it('Should Rotate Signers', async () => { + + it('Should rotate signers', async () => { await sleep(2000); const proofSigners = signers; const proofKeys = operatorKeys; @@ -147,4 +149,56 @@ describe.only('test', () => { await builder.signAndExecute(keypair); }); + + + it.only('Should not rotate to empty signers', async () => { + await sleep(2000); + const proofSigners = signers; + const proofKeys = operatorKeys; + + const encodedSigners = axelarStructs.WeightedSigners + .serialize({ + signers: [], + threshold: 2, + nonce: hexlify([nonce + 1]), + }) + .toBytes(); + + const hashed = hashMessage(encodedSigners); + + const message = axelarStructs.MessageToSign + .serialize({ + domain_separator: domainSeparator, + signers_hash: keccak256(axelarStructs.WeightedSigners.serialize(proofSigners).toBytes()), + data_hash: hashed, + }) + .toBytes(); + + const signatures = sign(proofKeys, message); + const encodedProof = axelarStructs.Proof + .serialize({ + signers: proofSigners, + signatures, + }) + .toBytes(); + + const builder = new TxBuilder(client); + + await builder.moveCall({ + target: `${packageId}::gateway::rotate_signers`, + arguments: [ + gateway, + '0x6', + encodedSigners, + encodedProof, + ], + }); + + await expectRevert(builder, keypair, { + packageId, + module: 'weighted_signers', + function: 'peel', + code: 0, + }); + }); }); diff --git a/test/utils.js b/test/utils.js index 54762e5b..06546ee5 100644 --- a/test/utils.js +++ b/test/utils.js @@ -17,7 +17,44 @@ function getRandomBytes32() { return keccak256(defaultAbiCoder.encode(['string'], [Math.random().toString()])); } +async function expectRevert(builder, keypair, error = {}) { + try{ + await builder.signAndExecute(keypair); + throw new Error(`Expected revert with ${error} but exeuted successfully instead`); + } catch (e) { + errorMessage = e.cause.effects.status.error; + let regexp = /address: (.*?),/; + const packageId = `0x${regexp.exec(errorMessage)[1]}`; + + regexp = /Identifier\(\"(.*?)\"\)/; + const module = regexp.exec(errorMessage)[1]; + + regexp = /Some\(\"(.*?)\"\)/; + const functionName = regexp.exec(errorMessage)[1]; + + regexp = /Some\(\".*?\"\) \}, (.*?)\)/; + const errorCode = parseInt(regexp.exec(errorMessage)[1]); + + if( error.packageId && error.packageId !== packageId ) { + throw new Error(`Expected ${errorMessage} to match ${error}} but it didn't, ${error.packageId} !== ${packageId}`); + } + + if( error.module && error.module !== module ) { + throw new Error(`Expected ${errorMessage} to match ${error}} but it didn't, ${error.module} !== ${module}`); + } + + if( error.function && error.function !== functionName ) { + throw new Error(`Expected ${errorMessage} to match ${error}} but it didn't, ${error.function} !== ${functionName}`); + } + + if( error.code && error.code !== errorCode ) { + throw new Error(`Expected ${errorMessage} to match ${error}} but it didn't, ${error.code} !== ${errorCode}`); + } + } +} + module.exports = { publishPackage, getRandomBytes32, + expectRevert, }; From df94e7ecc2b24bd0ab63a24e5f936d1c1798a4a0 Mon Sep 17 00:00:00 2001 From: Foivos Date: Fri, 21 Jun 2024 14:13:07 +0300 Subject: [PATCH 36/47] prettier --- test/axelar-gateway.js | 138 ++++++++++++++++++----------------------- test/test.js | 46 -------------- test/utils.js | 14 ++--- 3 files changed, 66 insertions(+), 132 deletions(-) delete mode 100644 test/test.js diff --git a/test/axelar-gateway.js b/test/axelar-gateway.js index e388273b..3c98fc2d 100644 --- a/test/axelar-gateway.js +++ b/test/axelar-gateway.js @@ -4,7 +4,9 @@ const { Secp256k1Keypair } = require('@mysten/sui.js/keypairs/secp256k1'); const { requestSuiFromFaucetV0, getFaucetHost } = require('@mysten/sui.js/faucet'); const { publishPackage, getRandomBytes32, expectRevert } = require('./utils'); const { TxBuilder } = require('../dist/tx-builder'); -const { bcsStructs: { axelarStructs } } = require('../dist/bcs'); +const { + bcsStructs: { axelarStructs }, +} = require('../dist/bcs'); const { arrayify, hexlify, keccak256 } = require('ethers/lib/utils'); const secp256k1 = require('secp256k1'); @@ -21,19 +23,21 @@ describe.only('test', () => { let nonce = 0; let packageId; - function calculateNextSigners() { operatorKeys = [getRandomBytes32(), getRandomBytes32(), getRandomBytes32()]; - pubkeys = operatorKeys.map(key => Secp256k1Keypair.fromSecretKey(arrayify(key)).getPublicKey().toRawBytes()); - const keys = operatorKeys.map((key,index) => { return { privkey: key, pubkey: pubkeys[index]} }); + pubkeys = operatorKeys.map((key) => Secp256k1Keypair.fromSecretKey(arrayify(key)).getPublicKey().toRawBytes()); + const keys = operatorKeys.map((key, index) => { + return { privkey: key, pubkey: pubkeys[index] }; + }); keys.sort((key1, key2) => { - for(let i = 0; i < 33; i ++) { + for (let i = 0; i < 33; i++) { if (key1.pubkey[i] < key2.pubkey[i]) return -1; if (key1.pubkey[i] > key2.pubkey[i]) return 1; } + return 0; }); - operatorKeys = keys.map(key => key.privkey); + operatorKeys = keys.map((key) => key.privkey); signers = { signers: keys.map((key) => { return { pubkey: key.pubkey, weight: 1 }; @@ -47,41 +51,47 @@ describe.only('test', () => { const toHash = new Uint8Array(data.length + 1); toHash[0] = COMMAND_TYPE_ROTATE_SIGNERS; toHash.set(data, 1); - + return keccak256(toHash); } function sign(privKeys, messageToSign) { const signatures = []; - for(const privKey of privKeys) { + + for (const privKey of privKeys) { const { signature, recid } = secp256k1.ecdsaSign(arrayify(keccak256(messageToSign)), arrayify(privKey)); signatures.push(new Uint8Array([...signature, recid])); } + return signatures; } async function sleep(ms = 1000) { await new Promise((resolve) => setTimeout(resolve, ms)); } - + const minimumRotationDelay = 1000; before(async () => { client = new SuiClient({ url: getFullnodeUrl('localnet') }); - await Promise.all([operator, deployer, keypair].map( - (keypair) => requestSuiFromFaucetV0({ - host: getFaucetHost('localnet'), - recipient: keypair.toSuiAddress(), - }) - )) + await Promise.all( + [operator, deployer, keypair].map((keypair) => + requestSuiFromFaucetV0({ + host: getFaucetHost('localnet'), + recipient: keypair.toSuiAddress(), + }), + ), + ); let result = await publishPackage(client, deployer, 'axelar_gateway'); packageId = result.packageId; - const creatorCap = result.publishTxn.objectChanges.find((change) => change.objectType === `${packageId}::gateway::CreatorCap`).objectId; + const creatorCap = result.publishTxn.objectChanges.find( + (change) => change.objectType === `${packageId}::gateway::CreatorCap`, + ).objectId; calculateNextSigners(); - + const encodedSigners = axelarStructs.WeightedSigners.serialize(signers).toBytes(); const builder = new TxBuilder(client); @@ -89,17 +99,10 @@ describe.only('test', () => { target: `${packageId}::bytes32::new`, arguments: [domainSeparator], }); - + await builder.moveCall({ target: `${packageId}::gateway::setup`, - arguments: [ - creatorCap, - operator.toSuiAddress(), - separator, - minimumRotationDelay, - encodedSigners, - '0x6', - ] + arguments: [creatorCap, operator.toSuiAddress(), separator, minimumRotationDelay, encodedSigners, '0x6'], }); result = await builder.signAndExecute(deployer); @@ -112,86 +115,63 @@ describe.only('test', () => { const proofSigners = signers; const proofKeys = operatorKeys; calculateNextSigners(); - - const encodedSigners = axelarStructs.WeightedSigners - .serialize(signers) - .toBytes(); + + const encodedSigners = axelarStructs.WeightedSigners.serialize(signers).toBytes(); const hashed = hashMessage(encodedSigners); - const message = axelarStructs.MessageToSign - .serialize({ - domain_separator: domainSeparator, - signers_hash: keccak256(axelarStructs.WeightedSigners.serialize(proofSigners).toBytes()), - data_hash: hashed, - }) - .toBytes(); + const message = axelarStructs.MessageToSign.serialize({ + domain_separator: domainSeparator, + signers_hash: keccak256(axelarStructs.WeightedSigners.serialize(proofSigners).toBytes()), + data_hash: hashed, + }).toBytes(); const signatures = sign(proofKeys, message); - const encodedProof = axelarStructs.Proof - .serialize({ - signers: proofSigners, - signatures, - }) - .toBytes(); + const encodedProof = axelarStructs.Proof.serialize({ + signers: proofSigners, + signatures, + }).toBytes(); - const builder = new TxBuilder(client); + const builder = new TxBuilder(client); await builder.moveCall({ target: `${packageId}::gateway::rotate_signers`, - arguments: [ - gateway, - '0x6', - encodedSigners, - encodedProof, - ], + arguments: [gateway, '0x6', encodedSigners, encodedProof], }); await builder.signAndExecute(keypair); }); - it.only('Should not rotate to empty signers', async () => { await sleep(2000); const proofSigners = signers; const proofKeys = operatorKeys; - - const encodedSigners = axelarStructs.WeightedSigners - .serialize({ - signers: [], - threshold: 2, - nonce: hexlify([nonce + 1]), - }) - .toBytes(); + + const encodedSigners = axelarStructs.WeightedSigners.serialize({ + signers: [], + threshold: 2, + nonce: hexlify([nonce + 1]), + }).toBytes(); const hashed = hashMessage(encodedSigners); - const message = axelarStructs.MessageToSign - .serialize({ - domain_separator: domainSeparator, - signers_hash: keccak256(axelarStructs.WeightedSigners.serialize(proofSigners).toBytes()), - data_hash: hashed, - }) - .toBytes(); + const message = axelarStructs.MessageToSign.serialize({ + domain_separator: domainSeparator, + signers_hash: keccak256(axelarStructs.WeightedSigners.serialize(proofSigners).toBytes()), + data_hash: hashed, + }).toBytes(); const signatures = sign(proofKeys, message); - const encodedProof = axelarStructs.Proof - .serialize({ - signers: proofSigners, - signatures, - }) - .toBytes(); + const encodedProof = axelarStructs.Proof.serialize({ + signers: proofSigners, + signatures, + }).toBytes(); - const builder = new TxBuilder(client); + const builder = new TxBuilder(client); await builder.moveCall({ target: `${packageId}::gateway::rotate_signers`, - arguments: [ - gateway, - '0x6', - encodedSigners, - encodedProof, - ], + arguments: [gateway, '0x6', encodedSigners, encodedProof], }); await expectRevert(builder, keypair, { diff --git a/test/test.js b/test/test.js deleted file mode 100644 index 62ee0cae..00000000 --- a/test/test.js +++ /dev/null @@ -1,46 +0,0 @@ -const { SuiClient, getFullnodeUrl } = require('@mysten/sui.js/client'); -const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); -const { requestSuiFromFaucetV0, getFaucetHost } = require('@mysten/sui.js/faucet'); -const { publishPackage } = require('./utils'); - -describe('test', () => { - let client, keypair; - before(async () => { - client = new SuiClient({ url: getFullnodeUrl('localnet') }); - const privKey = Buffer.from('9027dcb35b21318572bda38641b394eb33896aa81878a4f0e7066b119a9ea000', 'hex'); - - keypair = Ed25519Keypair.fromSecretKey(privKey); - await requestSuiFromFaucetV0({ - host: getFaucetHost('localnet'), - recipient: keypair.toSuiAddress(), - }); - let result = await publishPackage(client, keypair, 'abi'); - const abiPackageId = result.packageId; - const abiCap = result.publishTxn.objectChanges.find((change) => change.objectType === `0x2::package::UpgradeCap`).objectId; - - result = await publishPackage(client, keypair, 'axelar_gateway'); - const axelarPackageId = result.packageId; - const axelarCap = result.publishTxn.objectChanges.find((change) => change.objectType === `0x2::package::UpgradeCap`).objectId; - - result = await publishPackage(client, keypair, 'gas_service'); - const gasServicePackageId = result.packageId; - const gasServiceCap = result.publishTxn.objectChanges.find((change) => change.objectType === `0x2::package::UpgradeCap`).objectId; - - result = await publishPackage(client, keypair, 'governance'); - const governancePackageId = result.packageId; - const governanceCap = result.publishTxn.objectChanges.find((change) => change.objectType === `0x2::package::UpgradeCap`).objectId; - - result = await publishPackage(client, keypair, 'its'); - const itsPackageId = result.packageId; - const itsCap = result.publishTxn.objectChanges.find((change) => change.objectType === `0x2::package::UpgradeCap`).objectId; - - result = await publishPackage(client, keypair, 'squid'); - const squidPackageId = result.packageId; - const squidCap = result.publishTxn.objectChanges.find((change) => change.objectType === `0x2::package::UpgradeCap`).objectId; - - result = await publishPackage(client, keypair, 'test'); - const testPackageId = result.packageId; - const testCap = result.publishTxn.objectChanges.find((change) => change.objectType === `0x2::package::UpgradeCap`).objectId; - }); - it('test', async () => {}); -}); diff --git a/test/utils.js b/test/utils.js index 06546ee5..1df845cd 100644 --- a/test/utils.js +++ b/test/utils.js @@ -18,14 +18,14 @@ function getRandomBytes32() { } async function expectRevert(builder, keypair, error = {}) { - try{ + try { await builder.signAndExecute(keypair); throw new Error(`Expected revert with ${error} but exeuted successfully instead`); } catch (e) { errorMessage = e.cause.effects.status.error; let regexp = /address: (.*?),/; const packageId = `0x${regexp.exec(errorMessage)[1]}`; - + regexp = /Identifier\(\"(.*?)\"\)/; const module = regexp.exec(errorMessage)[1]; @@ -35,23 +35,23 @@ async function expectRevert(builder, keypair, error = {}) { regexp = /Some\(\".*?\"\) \}, (.*?)\)/; const errorCode = parseInt(regexp.exec(errorMessage)[1]); - if( error.packageId && error.packageId !== packageId ) { + if (error.packageId && error.packageId !== packageId) { throw new Error(`Expected ${errorMessage} to match ${error}} but it didn't, ${error.packageId} !== ${packageId}`); } - if( error.module && error.module !== module ) { + if (error.module && error.module !== module) { throw new Error(`Expected ${errorMessage} to match ${error}} but it didn't, ${error.module} !== ${module}`); } - if( error.function && error.function !== functionName ) { + if (error.function && error.function !== functionName) { throw new Error(`Expected ${errorMessage} to match ${error}} but it didn't, ${error.function} !== ${functionName}`); } - if( error.code && error.code !== errorCode ) { + if (error.code && error.code !== errorCode) { throw new Error(`Expected ${errorMessage} to match ${error}} but it didn't, ${error.code} !== ${errorCode}`); } } -} +} module.exports = { publishPackage, From afc4c9c66257046301f1c2df370676d097e8a81a Mon Sep 17 00:00:00 2001 From: Foivos Date: Fri, 21 Jun 2024 14:13:59 +0300 Subject: [PATCH 37/47] run imp i to fix tests --- package-lock.json | 473 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 473 insertions(+) diff --git a/package-lock.json b/package-lock.json index 35e1c859..3bcddb01 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,7 @@ "dotenv": "^16.3.1", "eslint": "^8.57.0", "eslint-config-richardpringle": "^2.0.0", + "mocha": "^10.4.0", "prettier": "^2.8.7", "prettier-plugin-sort-imports": "^1.8.5" }, @@ -2064,6 +2065,15 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -2088,6 +2098,19 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -2299,6 +2322,18 @@ "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/bn.js": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", @@ -2330,6 +2365,12 @@ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, "node_modules/browserslist": { "version": "4.23.0", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", @@ -2398,6 +2439,18 @@ "node": ">=6" } }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001625", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001625.tgz", @@ -2439,6 +2492,56 @@ "resolved": "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz", "integrity": "sha512-Wmza/JzL0SiWz7kl6MhIKT5ceIlnFPJX+lwUGj7Clhy5MMldsSoJR0+uvRzOS5Kv45Mq7t1PoE8TsOA9bzvb6g==" }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, "node_modules/code-red": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.4.tgz", @@ -2611,6 +2714,18 @@ } } }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/dedent-js": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dedent-js/-/dedent-js-1.0.1.tgz", @@ -2671,6 +2786,15 @@ "node": ">=6" } }, + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -2732,6 +2856,12 @@ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -3436,6 +3566,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, "node_modules/flat-cache": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", @@ -3507,6 +3646,20 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -3551,6 +3704,15 @@ "node": ">=6.9.0" } }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -3911,6 +4073,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", @@ -3990,6 +4164,15 @@ "node": ">=0.10.0" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -4047,6 +4230,15 @@ "node": ">=8" } }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-reference": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz", @@ -4132,6 +4324,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -4291,6 +4495,22 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/long": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", @@ -4399,6 +4619,103 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mocha": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz", + "integrity": "sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==", + "dev": true, + "dependencies": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "8.1.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -4446,6 +4763,15 @@ "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", @@ -4820,6 +5146,27 @@ "integrity": "sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA==", "dev": true }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/readonly-date": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/readonly-date/-/readonly-date-1.0.0.tgz", @@ -4855,6 +5202,15 @@ "url": "https://github.com/sponsors/mysticatea" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -4946,6 +5302,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/safe-regex-test": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", @@ -4991,6 +5367,15 @@ "semver": "bin/semver.js" } }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -5079,6 +5464,20 @@ "node": ">=0.10.0" } }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/string.prototype.trim": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", @@ -5556,6 +5955,29 @@ "node": ">=0.10.0" } }, + "node_modules/workerpool": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -5590,12 +6012,63 @@ "symbol-observable": "^2.0.3" } }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", From 8c5f516e19c389f5df07fefc25594b553b079d6a Mon Sep 17 00:00:00 2001 From: Foivos Date: Wed, 26 Jun 2024 12:48:24 +0300 Subject: [PATCH 38/47] added flow limits and scaling all incoming decimals down to 9 --- move/abi/Move.lock | 4 +- move/abi/Move.toml | 3 +- move/axelar_gateway/Move.lock | 4 +- move/axelar_gateway/Move.toml | 2 +- move/its/Move.lock | 2 +- move/its/sources/coin_info.move | 29 ++++++++++---- move/its/sources/coin_management.move | 18 ++++++++- move/its/sources/discovery.move | 4 +- move/its/sources/flow_limit.move | 52 +++++++++++++++++++++++++ move/its/sources/its.move | 13 +++++++ move/its/sources/service.move | 36 +++++++++++------ move/its/sources/utils.move | 26 ++++++++++--- move/squid/Move.lock | 2 +- move/squid/sources/squid/discovery.move | 1 + move/squid/sources/squid/squid.move | 5 ++- move/squid/sources/squid/transfers.move | 7 +++- scripts/publish-all.js | 2 +- 17 files changed, 169 insertions(+), 41 deletions(-) create mode 100644 move/its/sources/flow_limit.move diff --git a/move/abi/Move.lock b/move/abi/Move.lock index 285c6b4a..974dc3af 100644 --- a/move/abi/Move.lock +++ b/move/abi/Move.lock @@ -2,7 +2,7 @@ [move] version = 2 -manifest_digest = "7DED727D47EB51E5059409B19CC373C6D9AF249D837E9153E7368F3898025E41" +manifest_digest = "3532BD95263AA10C254F2DF0A5E5E545AFF9EED1DDB4AC7183A2E78E71E43E7B" deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082" dependencies = [ { name = "Sui" }, @@ -21,6 +21,6 @@ dependencies = [ ] [move.toolchain-version] -compiler-version = "1.25.1" +compiler-version = "1.26.1" edition = "2024.beta" flavor = "sui" diff --git a/move/abi/Move.toml b/move/abi/Move.toml index 7eb23213..06c165aa 100644 --- a/move/abi/Move.toml +++ b/move/abi/Move.toml @@ -1,10 +1,11 @@ [package] name = "Abi" version = "0.1.0" +published-at = "0x9b252019ef5d2939bcf3b78090c93438fe7bdec923e9dc978e00ee9fe8f2053b" edition = "2024.beta" [dependencies] Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet-v1.25.3" } [addresses] -abi = "0x103" +abi = "0x9b252019ef5d2939bcf3b78090c93438fe7bdec923e9dc978e00ee9fe8f2053b" diff --git a/move/axelar_gateway/Move.lock b/move/axelar_gateway/Move.lock index 4c88b1b8..665cc667 100644 --- a/move/axelar_gateway/Move.lock +++ b/move/axelar_gateway/Move.lock @@ -2,7 +2,7 @@ [move] version = 2 -manifest_digest = "11FAF5CFE0A4A2EBCD5E370FAD144FFF14243A85492B718A2B26A15CF7F0B571" +manifest_digest = "7C07F23DFA1760FD51607990389721D9B6179F46C68834C27D786FC43060166F" deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082" dependencies = [ { name = "Sui" }, @@ -21,6 +21,6 @@ dependencies = [ ] [move.toolchain-version] -compiler-version = "1.25.1" +compiler-version = "1.26.1" edition = "2024.beta" flavor = "sui" diff --git a/move/axelar_gateway/Move.toml b/move/axelar_gateway/Move.toml index 59b0a66f..092e51ff 100644 --- a/move/axelar_gateway/Move.toml +++ b/move/axelar_gateway/Move.toml @@ -7,5 +7,5 @@ edition = "2024.beta" Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet-v1.25.3" } [addresses] -axelar_gateway = "0x100" +axelar_gateway = "0x0" clock = "0x6" diff --git a/move/its/Move.lock b/move/its/Move.lock index 06cc4987..d45ae8ec 100644 --- a/move/its/Move.lock +++ b/move/its/Move.lock @@ -49,6 +49,6 @@ dependencies = [ ] [move.toolchain-version] -compiler-version = "1.25.1" +compiler-version = "1.26.1" edition = "2024.beta" flavor = "sui" diff --git a/move/its/sources/coin_info.move b/move/its/sources/coin_info.move index 8d84dc05..46d5d674 100644 --- a/move/its/sources/coin_info.move +++ b/move/its/sources/coin_info.move @@ -6,33 +6,38 @@ module its::coin_info { use std::ascii; use std::string::String; - use sui::coin::{Self, CoinMetadata}; + use sui::coin::CoinMetadata; + + use its::utils; public struct CoinInfo has store { name: String, symbol: ascii::String, decimals: u8, + remote_decimals: u8, metadata: Option>, } /// Create a new coin info from the given name, symbol and decimals. public fun from_info( - name: String, symbol: ascii::String, decimals: u8 + name: String, symbol: ascii::String, decimals: u8, remote_decimals: u8, ): CoinInfo { CoinInfo { name, symbol, decimals, + remote_decimals, metadata: option::none(), } } /// Create a new coin info from the given `CoinMetadata` object. - public fun from_metadata(metadata: CoinMetadata): CoinInfo { + public fun from_metadata(metadata: CoinMetadata, remote_decimals: u8): CoinInfo { CoinInfo { - name: coin::get_name(&metadata), - symbol: coin::get_symbol(&metadata), - decimals: coin::get_decimals(&metadata), + name: metadata.get_name(), + symbol: metadata.get_symbol(), + decimals: metadata.get_decimals(), + remote_decimals, metadata: option::some(metadata), } } @@ -51,6 +56,14 @@ module its::coin_info { self.decimals } + public fun remote_decimals(self: &CoinInfo): u8 { + self.remote_decimals + } + + public fun scaling(self: &CoinInfo): u256 { + utils::pow(10, self.remote_decimals - self.decimals) + } + public fun metadata(self: &CoinInfo): &Option> { &self.metadata } @@ -58,10 +71,10 @@ module its::coin_info { #[test_only] public fun drop(coin_info: CoinInfo) { let CoinInfo {name: _, symbol: _, decimals: _, metadata } = coin_info; - if (option::is_some(&metadata)) { + if (metadata.is_some()) { abort 0 } else { - option::destroy_none(metadata) + metadata.destroy_none() } } } diff --git a/move/its/sources/coin_management.move b/move/its/sources/coin_management.move index 707c9cdf..538c68ff 100644 --- a/move/its/sources/coin_management.move +++ b/move/its/sources/coin_management.move @@ -4,6 +4,9 @@ module its::coin_management { use sui::coin::{Self, TreasuryCap, Coin}; use sui::balance::{Self, Balance}; + use sui::clock::Clock; + + use its::flow_limit::{Self, FlowLimit}; /// Trying to add a distributor to a `CoinManagement` that does not /// have a `TreasuryCap`. @@ -14,6 +17,7 @@ module its::coin_management { treasury_cap: Option>, balance: Option>, distributor: Option
, + flow_limit: FlowLimit, } /// Create a new `CoinManagement` with a `TreasuryCap`. @@ -23,6 +27,7 @@ module its::coin_management { treasury_cap: option::some(treasury_cap), balance: option::none(), distributor: option::none(), + flow_limit: flow_limit::new(), } } @@ -33,6 +38,7 @@ module its::coin_management { treasury_cap: option::none(), balance: option::some(balance::zero()), distributor: option::none(), + flow_limit: flow_limit::new(), } } @@ -43,10 +49,17 @@ module its::coin_management { self.distributor.fill(distributor); } + /// Adds a rate limit to the `CoinManagement`. + /// Note that this rate limit will be calculated for the remote decimals of the token, not for the native decimals. + public fun set_flow_limit(self: &mut CoinManagement, flow_limit: u64) { + self.flow_limit.set_flow_limit(flow_limit); + } + // === Protected Methods === /// Takes the given amount of Coins from user. - public(package) fun take_coin(self: &mut CoinManagement, to_take: Coin) { + public(package) fun take_coin(self: &mut CoinManagement, to_take: Coin, clock: &Clock) { + self.flow_limit.add_flow_out(to_take.value(), clock); if (has_capability(self)) { self.treasury_cap .borrow_mut() @@ -60,8 +73,9 @@ module its::coin_management { /// Withdraws or mints the given amount of coins. public(package) fun give_coin( - self: &mut CoinManagement, amount: u64, ctx: &mut TxContext + self: &mut CoinManagement, amount: u64, clock: &Clock, ctx: &mut TxContext ): Coin { + self.flow_limit.add_flow_out(amount, clock); if (has_capability(self)) { self.treasury_cap .borrow_mut() diff --git a/move/its/sources/discovery.move b/move/its/sources/discovery.move index 47c0507d..8764e641 100644 --- a/move/its/sources/discovery.move +++ b/move/its/sources/discovery.move @@ -93,7 +93,8 @@ module its::discovery { let arguments = vector[ arg, - vector[2] + vector[2], + vector[0, 6], ]; @@ -127,6 +128,7 @@ module its::discovery { vector[ discovery_arg, channel_id_arg, + vector[0, 6], ], vector[], )], diff --git a/move/its/sources/flow_limit.move b/move/its/sources/flow_limit.move new file mode 100644 index 00000000..1485ffe0 --- /dev/null +++ b/move/its/sources/flow_limit.move @@ -0,0 +1,52 @@ +module its::flow_limit { + use sui::clock::Clock; + + const EPOCH_TIME: u64 = 6 * 60 * 60 * 1000; + + const EFlowLimitExceeded: u64 = 0; + + public struct FlowLimit has store, copy, drop { + flow_limit: u64, + flow_in: u64, + flow_out: u64, + current_epoch: u64, + } + + public(package) fun new(): FlowLimit { + FlowLimit { + flow_limit: 0, + flow_in: 0, + flow_out: 0, + current_epoch: 0, + } + } + + fun update_epoch(self: &mut FlowLimit, clock: &Clock) { + let epoch = clock.timestamp_ms() / EPOCH_TIME; + if(epoch > self.current_epoch) { + self.current_epoch = epoch; + self.flow_in = 0; + self.flow_out = 0; + } + } + + public(package) fun add_flow_in(self: &mut FlowLimit, amount: u64, clock: &Clock) { + if (self.flow_limit == 0) return; + + update_epoch(self, clock); + assert!(self.flow_in + amount < self.flow_limit + self.flow_out, EFlowLimitExceeded); + self.flow_in = self.flow_in + amount; + } + + public(package) fun add_flow_out(self: &mut FlowLimit, amount: u64, clock: &Clock) { + if (self.flow_limit == 0) return; + + update_epoch(self, clock); + assert!(self.flow_out + amount < self.flow_limit + self.flow_in, EFlowLimitExceeded); + self.flow_out = self.flow_out + amount; + } + + public(package) fun set_flow_limit(self: &mut FlowLimit, flow_limit: u64) { + self.flow_limit = flow_limit; + } +} \ No newline at end of file diff --git a/move/its/sources/its.move b/move/its/sources/its.move index 487ff4d7..29d17d98 100644 --- a/move/its/sources/its.move +++ b/move/its/sources/its.move @@ -96,6 +96,15 @@ module its::its { &self.registered_coins[token_id] } + public(package) fun get_coin_data_mut(self: &mut ITS, token_id: TokenId): &mut CoinData { + assert!(self.registered_coins.contains(token_id), EUnregisteredCoin); + &mut self.registered_coins[token_id] + } + + public(package) fun get_coin_scaling(self: &CoinData): u256 { + self.coin_info.scaling() + } + public fun get_coin_info(self: &ITS, token_id: TokenId): &CoinInfo { &get_coin_data(self, token_id).coin_info } @@ -112,6 +121,10 @@ module its::its { get_coin_info(self, token_id).decimals() } + public fun token_remote_decimals(self: &ITS, token_id: TokenId): u8 { + get_coin_info(self, token_id).remote_decimals() + } + public fun get_trusted_address(self: &ITS, chain_name: String): String { *self.address_tracker.get_trusted_address(chain_name) } diff --git a/move/its/sources/service.move b/move/its/sources/service.move index 49c8a88f..f3b5df14 100644 --- a/move/its/sources/service.move +++ b/move/its/sources/service.move @@ -7,6 +7,7 @@ module its::service { use sui::address; use sui::event; use sui::bcs; + use sui::clock::Clock; use abi::abi; @@ -30,6 +31,8 @@ module its::service { // address::to_u256(address::from_bytes(keccak256(b"sui-set-trusted-addresses"))); const MESSAGE_TYPE_SET_TRUSTED_ADDRESSES: u256 = 0x2af37a0d5d48850a855b1aaaf57f726c107eb99b40eabf4cc1ba30410cfa2f68; + const DECIMALS_CAP: u8 = 9; + const EUntrustedAddress: u64 = 0; const EInvalidMessageType: u64 = 1; const EWrongDestination: u64 = 2; @@ -84,9 +87,11 @@ module its::service { destination_chain: String, destination_address: vector, metadata: vector, + clock: &Clock, ctx: &mut TxContext, ) { - let amount = (coin::value(&coin) as u256); + let coin_info = self.get_coin_info(token_id); + let amount = (coin::value(&coin) as u256) * coin_info.scaling(); let (_version, data) = its_utils::decode_metadata(metadata); let mut writer = abi::new_writer(6); @@ -99,27 +104,28 @@ module its::service { .write_bytes(data); self.coin_management_mut(token_id) - .take_coin(coin); + .take_coin(coin, clock); send_payload(self, destination_chain, writer.into_bytes()); } - public fun receive_interchain_transfer(self: &mut ITS, approved_message: ApprovedMessage, ctx: &mut TxContext) { + public fun receive_interchain_transfer(self: &mut ITS, approved_message: ApprovedMessage, clock: &Clock, ctx: &mut TxContext) { let (_, payload) = decode_approved_message(self, approved_message); let mut reader = abi::new_reader(payload); assert!(reader.read_u256() == MESSAGE_TYPE_INTERCHAIN_TRANSFER, EInvalidMessageType); let token_id = token_id::from_u256(reader.read_u256()); + let coin_info = self.get_coin_info(token_id); reader.skip_slot(); // skip source_address let destination_address = address::from_bytes(reader.read_bytes()); - let amount = (reader.read_u256() as u64); + let amount = (reader.read_u256() / coin_info.scaling() as u64); let data = reader.read_bytes(); assert!(data.is_empty(), EInterchainTransferHasData); let coin = self .coin_management_mut(token_id) - .give_coin(amount, ctx); + .give_coin(amount, clock, ctx); transfer::public_transfer(coin, destination_address) } @@ -128,16 +134,19 @@ module its::service { self: &mut ITS, approved_message: ApprovedMessage, channel: &Channel, - ctx: &mut TxContext + clock: &Clock, + ctx: &mut TxContext, ): (String, vector, vector, Coin) { let (source_chain, payload) = decode_approved_message(self, approved_message); let mut reader = abi::new_reader(payload); assert!(reader.read_u256() == MESSAGE_TYPE_INTERCHAIN_TRANSFER, EInvalidMessageType); let token_id = token_id::from_u256(reader.read_u256()); + let coin_info = self.get_coin_info(token_id); + let source_address = reader.read_bytes(); let destination_address = reader.read_bytes(); - let amount = (reader.read_u256() as u64); + let amount = (reader.read_u256() / coin_info.scaling() as u64); let data = reader.read_bytes(); assert!(address::from_bytes(destination_address) == channel.to_address(), EWrongDestination); @@ -145,7 +154,7 @@ module its::service { let coin = self .coin_management_mut(token_id) - .give_coin(amount, ctx); + .give_coin(amount, clock, ctx); ( source_chain, @@ -163,8 +172,9 @@ module its::service { let token_id = token_id::from_u256(reader.read_u256()); let name = string::utf8(reader.read_bytes()); let symbol = ascii::string(reader.read_bytes()); - let decimals = (reader.read_u256() as u8); + let remote_decimals = (reader.read_u256() as u8); let distributor = address::from_bytes(reader.read_bytes()); + let decimals = if (remote_decimals > DECIMALS_CAP) DECIMALS_CAP else remote_decimals; let (treasury_cap, mut coin_metadata) = self.remove_unregistered_coin( token_id::unregistered_token_id(&symbol, decimals) @@ -174,7 +184,7 @@ module its::service { //coin::update_symbol(&treasury_cap, &mut coin_metadata, symbol); let mut coin_management = coin_management::new_with_cap(treasury_cap); - let coin_info = coin_info::from_metadata(coin_metadata); + let coin_info = coin_info::from_metadata(coin_metadata, remote_decimals); coin_management.add_distributor(distributor); @@ -207,6 +217,7 @@ module its::service { token_id: TokenId, to: address, amount: u64, + clock: &Clock, ctx: &mut TxContext ) { let coin_management = self.coin_management_mut(token_id); @@ -214,7 +225,7 @@ module its::service { assert!(coin_management.is_distributor(distributor), ENotDistributor); - let coin = coin_management.give_coin(amount, ctx); + let coin = coin_management.give_coin(amount, clock, ctx); transfer::public_transfer(coin, to) } @@ -222,6 +233,7 @@ module its::service { self: &mut ITS, channel: &Channel, token_id: TokenId, + clock: &Clock, coin: Coin ) { let coin_management = self.coin_management_mut(token_id); @@ -229,7 +241,7 @@ module its::service { assert!(coin_management.is_distributor(distributor), ENotDistributor); - coin_management.take_coin(coin); + coin_management.take_coin(coin, clock); } // === Special Call Receiving diff --git a/move/its/sources/utils.move b/move/its/sources/utils.move index 0c785f1e..2dd17a7d 100644 --- a/move/its/sources/utils.move +++ b/move/its/sources/utils.move @@ -13,19 +13,19 @@ module its::utils { const ALPHABET_LENGTH: u8 = 26; const NUMBERS_LENGTH: u8 = 10; - public fun is_lowercase(c: u8): bool { + entry fun is_lowercase(c: u8): bool { c >= LOWERCASE_START && c < LOWERCASE_START + ALPHABET_LENGTH } - public fun is_uppercase(c: u8): bool { + entry fun is_uppercase(c: u8): bool { c >= UPPERCASE_START && c < UPPERCASE_START + ALPHABET_LENGTH } - public fun is_number(c: u8): bool { + entry fun is_number(c: u8): bool { c >= NUMBERS_START && c < NUMBERS_START + NUMBERS_LENGTH } - public fun get_module_from_symbol(symbol: &ascii::String): ascii::String { + public(package) fun get_module_from_symbol(symbol: &ascii::String): ascii::String { let symbolBytes = ascii::as_bytes(symbol); let mut moduleName = vector[]; @@ -48,13 +48,13 @@ module its::utils { ascii::string(moduleName) } - public fun hash_coin_info(symbol: &ascii::String, decimals: &u8): address { + public(package) fun hash_coin_info(symbol: &ascii::String, decimals: &u8): address { let mut v = vector[*decimals]; v.append(*symbol.as_bytes()); address::from_bytes(keccak256(&v)) } - public fun decode_metadata(mut metadata: vector): (u32, vector) { + public(package) fun decode_metadata(mut metadata: vector): (u32, vector) { if (metadata.length() < 4) { (0, vector[]) } else { @@ -69,6 +69,20 @@ module its::utils { } } + public(package) fun pow(mut base: u256, mut exponent: u8): u256 { + let mut res: u256 = 1; + while (exponent > 0) { + if (exponent % 2 == 0) { + base = base * base; + exponent = exponent / 2; + } else { + res = res * base; + exponent = exponent - 1; + } + }; + res + } + #[test] fun test_get_module_from_symbol() { let symbol = ascii::string(b"1(TheCool1234Coin) _ []!rdt"); diff --git a/move/squid/Move.lock b/move/squid/Move.lock index d9e2d31f..f7bcfa21 100644 --- a/move/squid/Move.lock +++ b/move/squid/Move.lock @@ -69,6 +69,6 @@ dependencies = [ ] [move.toolchain-version] -compiler-version = "1.25.1" +compiler-version = "1.26.1" edition = "2024.beta" flavor = "sui" diff --git a/move/squid/sources/squid/discovery.move b/move/squid/sources/squid/discovery.move index 62dd1776..cb1b8f89 100644 --- a/move/squid/sources/squid/discovery.move +++ b/move/squid/sources/squid/discovery.move @@ -119,6 +119,7 @@ module squid::discovery { squid_arg, its_arg, vector[2], + vector[0, 6], ], vector[type_in], ) diff --git a/move/squid/sources/squid/squid.move b/move/squid/sources/squid/squid.move index ca8de3af..bceb606d 100644 --- a/move/squid/sources/squid/squid.move +++ b/move/squid/sources/squid/squid.move @@ -1,4 +1,6 @@ module squid::squid { + use sui::clock::Clock; + use axelar_gateway::channel::{Self, Channel, ApprovedMessage}; use its::service; @@ -25,11 +27,12 @@ module squid::squid { &self.channel } - public fun start_swap(self: &mut Squid, its: &mut ITS, approved_message: ApprovedMessage, ctx: &mut TxContext): SwapInfo { + public fun start_swap(self: &mut Squid, its: &mut ITS, approved_message: ApprovedMessage, clock: &Clock, ctx: &mut TxContext): SwapInfo { let (_, _, data, coin) = service::receive_interchain_transfer_with_data( its, approved_message, &self.channel, + clock, ctx, ); let mut swap_info = swap_info::new(data, ctx); diff --git a/move/squid/sources/squid/transfers.move b/move/squid/sources/squid/transfers.move index a362d38b..212ab802 100644 --- a/move/squid/sources/squid/transfers.move +++ b/move/squid/sources/squid/transfers.move @@ -4,6 +4,7 @@ module squid::transfers { use sui::bcs::{Self, BCS}; use sui::coin; + use sui::clock::Clock; use axelar_gateway::discovery::{Self, MoveCall}; @@ -70,7 +71,7 @@ module squid::transfers { transfer::public_transfer(coin::from_balance(option.destroy_some(), ctx), address); } - public fun its_transfer(swap_info: &mut SwapInfo, its: &mut ITS, ctx: &mut TxContext) { + public fun its_transfer(swap_info: &mut SwapInfo, its: &mut ITS, clock: &Clock, ctx: &mut TxContext) { let data = swap_info.get_data_swapping(); if (data.length() == 0) return; let mut bcs = bcs::new(data); @@ -98,6 +99,7 @@ module squid::transfers { destination_chain, destination_address, metadata, + clock, ctx, ); } @@ -157,7 +159,8 @@ module squid::transfers { ), vector[ swap_info_arg, - its_arg + its_arg, + vector[0, 6], ], vector[type_arg], ) diff --git a/scripts/publish-all.js b/scripts/publish-all.js index 1dcc047f..16acc7dc 100644 --- a/scripts/publish-all.js +++ b/scripts/publish-all.js @@ -11,7 +11,7 @@ async function publishAll(client, keypair, env) { const upgradeCaps = {}; const packageIds = {}; - for (const packagePath of ['abi', 'axelar', 'governance', 'gas_service', 'its', 'squid']) { + for (const packagePath of ['abi', 'axelar_gateway', 'governance', 'gas_service', 'its', 'squid']) { console.log(packagePath); while (true) From 5b1e6874f71548c9ca0aec775c545195bb1c33aa Mon Sep 17 00:00:00 2001 From: Foivos Date: Wed, 26 Jun 2024 13:15:27 +0300 Subject: [PATCH 39/47] added proper token handling and helper function for minting/burning as the distributor --- move/its/sources/coin_management.move | 51 ++++++++++++++++++++------- move/its/sources/its.move | 3 +- move/its/sources/service.move | 19 ++++------ 3 files changed, 46 insertions(+), 27 deletions(-) diff --git a/move/its/sources/coin_management.move b/move/its/sources/coin_management.move index 538c68ff..c7047ca5 100644 --- a/move/its/sources/coin_management.move +++ b/move/its/sources/coin_management.move @@ -18,6 +18,8 @@ module its::coin_management { balance: Option>, distributor: Option
, flow_limit: FlowLimit, + scaling: u256, + dust: u256, } /// Create a new `CoinManagement` with a `TreasuryCap`. @@ -28,6 +30,8 @@ module its::coin_management { balance: option::none(), distributor: option::none(), flow_limit: flow_limit::new(), + scaling: 0, // placeholder, this gets edited when a coin is registered. + dust: 0, } } @@ -39,6 +43,8 @@ module its::coin_management { balance: option::some(balance::zero()), distributor: option::none(), flow_limit: flow_limit::new(), + scaling: 0, // placeholder, this gets edited when a coin is registered. + dust: 0, } } @@ -57,34 +63,53 @@ module its::coin_management { // === Protected Methods === - /// Takes the given amount of Coins from user. - public(package) fun take_coin(self: &mut CoinManagement, to_take: Coin, clock: &Clock) { + /// Takes the given amount of Coins from user. Returns the amount that the ITS is supposed to give on other chains. + public(package) fun take_coin(self: &mut CoinManagement, to_take: Coin, clock: &Clock): u256 { self.flow_limit.add_flow_out(to_take.value(), clock); + let amount = (to_take.value() as u256) * self.scaling; if (has_capability(self)) { - self.treasury_cap - .borrow_mut() - .burn(to_take); + self.burn(to_take); } else { self.balance .borrow_mut() .join(to_take.into_balance()); - } + }; + amount } - /// Withdraws or mints the given amount of coins. + /// Withdraws or mints the given amount of coins. Any leftover amount from previous transfers is added to the coin here. public(package) fun give_coin( - self: &mut CoinManagement, amount: u64, clock: &Clock, ctx: &mut TxContext + self: &mut CoinManagement, mut amount: u256, clock: &Clock, ctx: &mut TxContext ): Coin { - self.flow_limit.add_flow_out(amount, clock); + amount = amount + self.dust; + self.dust = amount % self.scaling; + let sui_amount = ( amount / self.scaling as u64); + self.flow_limit.add_flow_out(sui_amount, clock); if (has_capability(self)) { - self.treasury_cap - .borrow_mut() - .mint(amount, ctx) + self.mint(sui_amount, ctx) } else { - coin::take(self.balance.borrow_mut(), amount, ctx) + coin::take(self.balance.borrow_mut(), sui_amount, ctx) } } + // helper function to mint as a distributor. + public(package) fun mint(self: &mut CoinManagement, amount: u64, ctx: &mut TxContext): Coin { + self.treasury_cap + .borrow_mut() + .mint(amount, ctx) + } + + // helper function to burn as a distributor. + public(package) fun burn(self: &mut CoinManagement, coin: Coin) { + self.treasury_cap + .borrow_mut() + .burn(coin); + } + + public(package) fun set_scaling(self: &mut CoinManagement, scaling: u256) { + self.scaling = scaling; + } + // === Views === /// Checks if the given address is a `distributor`. diff --git a/move/its/sources/its.move b/move/its/sources/its.move index 29d17d98..d07d3a12 100644 --- a/move/its/sources/its.move +++ b/move/its/sources/its.move @@ -182,9 +182,10 @@ module its::its { public(package) fun add_registered_coin( self: &mut ITS, token_id: TokenId, - coin_management: CoinManagement, + mut coin_management: CoinManagement, coin_info: CoinInfo, ) { + coin_management.set_scaling(coin_info.scaling()); self.registered_coins.add(token_id, CoinData { coin_management, coin_info, diff --git a/move/its/sources/service.move b/move/its/sources/service.move index f3b5df14..ea78081a 100644 --- a/move/its/sources/service.move +++ b/move/its/sources/service.move @@ -90,8 +90,8 @@ module its::service { clock: &Clock, ctx: &mut TxContext, ) { - let coin_info = self.get_coin_info(token_id); - let amount = (coin::value(&coin) as u256) * coin_info.scaling(); + let amount = self.coin_management_mut(token_id) + .take_coin(coin, clock); let (_version, data) = its_utils::decode_metadata(metadata); let mut writer = abi::new_writer(6); @@ -103,9 +103,6 @@ module its::service { .write_u256(amount) .write_bytes(data); - self.coin_management_mut(token_id) - .take_coin(coin, clock); - send_payload(self, destination_chain, writer.into_bytes()); } @@ -115,10 +112,9 @@ module its::service { assert!(reader.read_u256() == MESSAGE_TYPE_INTERCHAIN_TRANSFER, EInvalidMessageType); let token_id = token_id::from_u256(reader.read_u256()); - let coin_info = self.get_coin_info(token_id); reader.skip_slot(); // skip source_address let destination_address = address::from_bytes(reader.read_bytes()); - let amount = (reader.read_u256() / coin_info.scaling() as u64); + let amount = reader.read_u256(); let data = reader.read_bytes(); assert!(data.is_empty(), EInterchainTransferHasData); @@ -142,11 +138,10 @@ module its::service { assert!(reader.read_u256() == MESSAGE_TYPE_INTERCHAIN_TRANSFER, EInvalidMessageType); let token_id = token_id::from_u256(reader.read_u256()); - let coin_info = self.get_coin_info(token_id); let source_address = reader.read_bytes(); let destination_address = reader.read_bytes(); - let amount = (reader.read_u256() / coin_info.scaling() as u64); + let amount = reader.read_u256(); let data = reader.read_bytes(); assert!(address::from_bytes(destination_address) == channel.to_address(), EWrongDestination); @@ -217,7 +212,6 @@ module its::service { token_id: TokenId, to: address, amount: u64, - clock: &Clock, ctx: &mut TxContext ) { let coin_management = self.coin_management_mut(token_id); @@ -225,7 +219,7 @@ module its::service { assert!(coin_management.is_distributor(distributor), ENotDistributor); - let coin = coin_management.give_coin(amount, clock, ctx); + let coin = coin_management.mint(amount, ctx); transfer::public_transfer(coin, to) } @@ -233,7 +227,6 @@ module its::service { self: &mut ITS, channel: &Channel, token_id: TokenId, - clock: &Clock, coin: Coin ) { let coin_management = self.coin_management_mut(token_id); @@ -241,7 +234,7 @@ module its::service { assert!(coin_management.is_distributor(distributor), ENotDistributor); - coin_management.take_coin(coin, clock); + coin_management.burn(coin); } // === Special Call Receiving From c31fda9afeb4bbb995d005b0bf3a86d068d8cac5 Mon Sep 17 00:00:00 2001 From: Foivos Date: Mon, 1 Jul 2024 16:46:53 +0300 Subject: [PATCH 40/47] dinished adding all the features for flow limits and decimals conversions. --- move/abi/Move.lock | 2 +- move/abi/Move.toml | 4 +- move/axelar_gateway/Move.lock | 2 +- move/axelar_gateway/Move.toml | 4 +- move/governance/Move.toml | 4 +- move/its/Move.toml | 4 +- move/its/sources/coin_info.move | 2 +- move/its/sources/coin_management.move | 40 +++++- move/its/sources/discovery.move | 3 +- move/its/sources/token_id.move | 5 +- move/squid/sources/squid/transfers.move | 1 + test/axelar-gateway.js | 156 +++++++++++------------- test/its.js | 54 ++++++++ 13 files changed, 175 insertions(+), 106 deletions(-) create mode 100644 test/its.js diff --git a/move/abi/Move.lock b/move/abi/Move.lock index 974dc3af..1db9b4db 100644 --- a/move/abi/Move.lock +++ b/move/abi/Move.lock @@ -2,7 +2,7 @@ [move] version = 2 -manifest_digest = "3532BD95263AA10C254F2DF0A5E5E545AFF9EED1DDB4AC7183A2E78E71E43E7B" +manifest_digest = "89B38FFD4D0D8B2DCFE440924446CCF3A347EA904B2657C9CA229BD7BB881131" deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082" dependencies = [ { name = "Sui" }, diff --git a/move/abi/Move.toml b/move/abi/Move.toml index 06c165aa..b1f5f1c1 100644 --- a/move/abi/Move.toml +++ b/move/abi/Move.toml @@ -1,11 +1,11 @@ [package] name = "Abi" version = "0.1.0" -published-at = "0x9b252019ef5d2939bcf3b78090c93438fe7bdec923e9dc978e00ee9fe8f2053b" +published-at = "0x4ee08bf35bdb2afbcc4f968a38dc2303106f3dfeedfe8c7919d47da7c90b8c4e" edition = "2024.beta" [dependencies] Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet-v1.25.3" } [addresses] -abi = "0x9b252019ef5d2939bcf3b78090c93438fe7bdec923e9dc978e00ee9fe8f2053b" +abi = "0x4ee08bf35bdb2afbcc4f968a38dc2303106f3dfeedfe8c7919d47da7c90b8c4e" diff --git a/move/axelar_gateway/Move.lock b/move/axelar_gateway/Move.lock index 665cc667..1242c5d3 100644 --- a/move/axelar_gateway/Move.lock +++ b/move/axelar_gateway/Move.lock @@ -2,7 +2,7 @@ [move] version = 2 -manifest_digest = "7C07F23DFA1760FD51607990389721D9B6179F46C68834C27D786FC43060166F" +manifest_digest = "10303CE6C59BAA2CE814E3D11BACC8CB24BE0F8D66753B02190E291CA40F0D39" deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082" dependencies = [ { name = "Sui" }, diff --git a/move/axelar_gateway/Move.toml b/move/axelar_gateway/Move.toml index 436d7fda..210b721f 100644 --- a/move/axelar_gateway/Move.toml +++ b/move/axelar_gateway/Move.toml @@ -1,12 +1,12 @@ [package] name = "AxelarGateway" version = "0.1.0" -published-at = "0x8fd4826963d7fac11825df329a1460a49eb782d9719ad362c97e5e3c225fc748" +published-at = "0xe55593abd7b439764115a766b55b789048f473a52a2c0e7952447ab8ec05f1bc" edition = "2024.beta" [dependencies] Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet-v1.25.3" } [addresses] -axelar_gateway = "0x0" +axelar_gateway = "0xe55593abd7b439764115a766b55b789048f473a52a2c0e7952447ab8ec05f1bc" clock = "0x6" diff --git a/move/governance/Move.toml b/move/governance/Move.toml index ac50d7ee..cd97b2b7 100644 --- a/move/governance/Move.toml +++ b/move/governance/Move.toml @@ -1,7 +1,7 @@ [package] name = "Governance" version = "0.1.0" -published-at = "0x0cba440261d721bde9c85eafe18aae673ee72702fa95da567675b34224f5ad77" +published-at = "0xb9e48a2b95661318fed02f48b88f0d497fc768bebaed9467fdaf7317af9b5ef2" edition = "2024.beta" [dependencies] @@ -10,4 +10,4 @@ AxelarGateway = { local = "../axelar_gateway" } Abi = { local = "../abi" } [addresses] -governance = "0x0cba440261d721bde9c85eafe18aae673ee72702fa95da567675b34224f5ad77" +governance = "0xb9e48a2b95661318fed02f48b88f0d497fc768bebaed9467fdaf7317af9b5ef2" diff --git a/move/its/Move.toml b/move/its/Move.toml index ab5ee59d..29fa6f8c 100644 --- a/move/its/Move.toml +++ b/move/its/Move.toml @@ -1,7 +1,7 @@ [package] name = "ITS" version = "0.1.0" -published-at = "0x89967fea5cc3bdf2d44cabe901aca920aa2a0485ca9a479f9932814c55d5f9b3" +published-at = "0xdee89af6230d63b16d42c23851a2b7b464a6ee96292fe9720b5aefc527164dbc" edition = "2024.beta" [dependencies] @@ -10,4 +10,4 @@ AxelarGateway = { local = "../axelar_gateway" } Governance = { local = "../governance" } [addresses] -its = "0x89967fea5cc3bdf2d44cabe901aca920aa2a0485ca9a479f9932814c55d5f9b3" +its = "0xdee89af6230d63b16d42c23851a2b7b464a6ee96292fe9720b5aefc527164dbc" diff --git a/move/its/sources/coin_info.move b/move/its/sources/coin_info.move index 46d5d674..f7eebf00 100644 --- a/move/its/sources/coin_info.move +++ b/move/its/sources/coin_info.move @@ -70,7 +70,7 @@ module its::coin_info { #[test_only] public fun drop(coin_info: CoinInfo) { - let CoinInfo {name: _, symbol: _, decimals: _, metadata } = coin_info; + let CoinInfo {name: _, symbol: _, decimals: _, remote_decimals: _, metadata } = coin_info; if (metadata.is_some()) { abort 0 } else { diff --git a/move/its/sources/coin_management.move b/move/its/sources/coin_management.move index c7047ca5..1bb890ea 100644 --- a/move/its/sources/coin_management.move +++ b/move/its/sources/coin_management.move @@ -6,17 +6,21 @@ module its::coin_management { use sui::balance::{Self, Balance}; use sui::clock::Clock; + use axelar_gateway::channel::Channel; + use its::flow_limit::{Self, FlowLimit}; /// Trying to add a distributor to a `CoinManagement` that does not /// have a `TreasuryCap`. const EDistributorNeedsTreasuryCap: u64 = 0; + const ENotOperator: u64 = 1; /// Struct that stores information about the ITS Coin. public struct CoinManagement has store { treasury_cap: Option>, balance: Option>, distributor: Option
, + operator: Option
, flow_limit: FlowLimit, scaling: u256, dust: u256, @@ -29,6 +33,7 @@ module its::coin_management { treasury_cap: option::some(treasury_cap), balance: option::none(), distributor: option::none(), + operator: option::none(), flow_limit: flow_limit::new(), scaling: 0, // placeholder, this gets edited when a coin is registered. dust: 0, @@ -42,6 +47,7 @@ module its::coin_management { treasury_cap: option::none(), balance: option::some(balance::zero()), distributor: option::none(), + operator: option::none(), flow_limit: flow_limit::new(), scaling: 0, // placeholder, this gets edited when a coin is registered. dust: 0, @@ -55,9 +61,25 @@ module its::coin_management { self.distributor.fill(distributor); } + /// Adds the distributor address to the `CoinManagement`. + /// Only works for a `CoinManagement` with a `TreasuryCap`. + public fun add_operator(self: &mut CoinManagement, operator: address) { + self.operator.fill(operator); + } + + + /// Adds a rate limit to the `CoinManagement`. + /// Note that this rate limit will be calculated for the remote decimals of the token, not for the native decimals. + /// To be used by the designated operator of the contract. + public fun set_flow_limit(self: &mut CoinManagement, channel: &Channel, flow_limit: u64) { + assert!(self.operator.contains(&channel.to_address()), ENotOperator); + self.flow_limit.set_flow_limit(flow_limit); + } + /// Adds a rate limit to the `CoinManagement`. /// Note that this rate limit will be calculated for the remote decimals of the token, not for the native decimals. - public fun set_flow_limit(self: &mut CoinManagement, flow_limit: u64) { + /// To be used by the ITS operator. + public(package) fun set_flow_limit(self: &mut CoinManagement, flow_limit: u64) { self.flow_limit.set_flow_limit(flow_limit); } @@ -147,17 +169,19 @@ module its::coin_management { let mut coin = cap.mint(amount1, ctx); let mut management1 = new_locked(); - management1.take_coin(coin); + let clock = sui::clock::create_for_testing(ctx); + management1.take_coin(coin, &clock); assert!(management1.balance.borrow().value() == amount1, 0); coin = cap.mint(amount2, ctx); let mut management2 = new_with_cap(cap); - management2.take_coin(coin); + management2.take_coin(coin, &clock); sui::test_utils::destroy(metadata); sui::test_utils::destroy(management1); sui::test_utils::destroy(management2); + sui::test_utils::destroy(clock); } #[test] @@ -169,8 +193,10 @@ module its::coin_management { let mut coin = cap.mint(amount1, ctx); let mut management1 = new_locked(); - management1.take_coin(coin); - coin = management1.give_coin(amount1, ctx); + management1.scaling = 1; + let clock = sui::clock::create_for_testing(ctx); + management1.take_coin(coin, &clock); + coin = management1.give_coin((amount1 as u256), &clock, ctx); assert!(management1.balance.borrow().value() == 0, 0); assert!(coin.value() == amount1, 0); @@ -178,7 +204,8 @@ module its::coin_management { sui::test_utils::destroy(coin); let mut management2 = new_with_cap(cap); - coin = management2.give_coin(amount2, ctx); + management2.scaling = 1; + coin = management2.give_coin((amount2 as u256), &clock, ctx); assert!(coin.value() == amount2, 1); @@ -186,5 +213,6 @@ module its::coin_management { sui::test_utils::destroy(metadata); sui::test_utils::destroy(management1); sui::test_utils::destroy(management2); + sui::test_utils::destroy(clock); } } diff --git a/move/its/sources/discovery.move b/move/its/sources/discovery.move index 8764e641..4fe27264 100644 --- a/move/its/sources/discovery.move +++ b/move/its/sources/discovery.move @@ -255,7 +255,8 @@ module its::discovery { let arguments = vector[ arg, - vector[2] + vector[2], + vector[0, 6], ]; assert!(call_info.arguments() == arguments, 6); assert!(call_info.type_arguments() == vector[type_arg.into_string()], 7); diff --git a/move/its/sources/token_id.move b/move/its/sources/token_id.move index c39095c8..b8d21361 100644 --- a/move/its/sources/token_id.move +++ b/move/its/sources/token_id.move @@ -86,8 +86,9 @@ module its::token_id { let name = string::utf8(b"Name"); let symbol = ascii::string(b"Symbol"); - let decimals: u8 = 56; - let coin_info = coin_info::from_info(name, symbol, decimals); + let decimals: u8 = 9; + let remote_decimals: u8 = 18; + let coin_info = coin_info::from_info(name, symbol, decimals, remote_decimals); let mut vec = address::from_u256(PREFIX_SUI_TOKEN_ID).to_bytes(); vec.append(bcs::to_bytes>(&coin_info)); diff --git a/move/squid/sources/squid/transfers.move b/move/squid/sources/squid/transfers.move index 0e819c78..bf6810b2 100644 --- a/move/squid/sources/squid/transfers.move +++ b/move/squid/sources/squid/transfers.move @@ -132,6 +132,7 @@ module squid::transfers { swap_data.destination_chain, swap_data.destination_address, swap_data.metadata, + clock, ctx, ); } diff --git a/test/axelar-gateway.js b/test/axelar-gateway.js index 3c98fc2d..046b0e02 100644 --- a/test/axelar-gateway.js +++ b/test/axelar-gateway.js @@ -12,40 +12,74 @@ const secp256k1 = require('secp256k1'); const COMMAND_TYPE_ROTATE_SIGNERS = 1; -describe.only('test', () => { +const minimumRotationDelay = 1000; +const domainSeparator = getRandomBytes32(); +let operatorKeys; +let signers; +let nonce = 0; + +function calculateNextSigners() { + operatorKeys = [getRandomBytes32(), getRandomBytes32(), getRandomBytes32()]; + pubkeys = operatorKeys.map((key) => Secp256k1Keypair.fromSecretKey(arrayify(key)).getPublicKey().toRawBytes()); + const keys = operatorKeys.map((key, index) => { + return { privkey: key, pubkey: pubkeys[index] }; + }); + keys.sort((key1, key2) => { + for (let i = 0; i < 33; i++) { + if (key1.pubkey[i] < key2.pubkey[i]) return -1; + if (key1.pubkey[i] > key2.pubkey[i]) return 1; + } + + return 0; + }); + operatorKeys = keys.map((key) => key.privkey); + signers = { + signers: keys.map((key) => { + return { pubkey: key.pubkey, weight: 1 }; + }), + threshold: 2, + nonce: hexlify([++nonce]), + }; +} + +async function deployGateway(client, keypair, deployer = keypair, operator = keypair) { + let result = await publishPackage(client, deployer, 'axelar_gateway'); + packageId = result.packageId; + const creatorCap = result.publishTxn.objectChanges.find( + (change) => change.objectType === `${packageId}::gateway::CreatorCap`, + ).objectId; + + calculateNextSigners(); + + const encodedSigners = axelarStructs.WeightedSigners.serialize(signers).toBytes(); + const builder = new TxBuilder(client); + + const separator = await builder.moveCall({ + target: `${packageId}::bytes32::new`, + arguments: [domainSeparator], + }); + + await builder.moveCall({ + target: `${packageId}::gateway::setup`, + arguments: [creatorCap, operator.toSuiAddress(), separator, minimumRotationDelay, encodedSigners, '0x6'], + }); + + result = await builder.signAndExecute(deployer); + + gateway = result.objectChanges.find((change) => change.objectType === `${packageId}::gateway::Gateway`).objectId; + return { + gateway, packageId, + } +} + +describe('test', () => { let client; const operator = Ed25519Keypair.fromSecretKey(arrayify(getRandomBytes32())); const deployer = Ed25519Keypair.fromSecretKey(arrayify(getRandomBytes32())); const keypair = Ed25519Keypair.fromSecretKey(arrayify(getRandomBytes32())); - const domainSeparator = getRandomBytes32(); - let operatorKeys; - let signers; - let nonce = 0; let packageId; + let gateway; - function calculateNextSigners() { - operatorKeys = [getRandomBytes32(), getRandomBytes32(), getRandomBytes32()]; - pubkeys = operatorKeys.map((key) => Secp256k1Keypair.fromSecretKey(arrayify(key)).getPublicKey().toRawBytes()); - const keys = operatorKeys.map((key, index) => { - return { privkey: key, pubkey: pubkeys[index] }; - }); - keys.sort((key1, key2) => { - for (let i = 0; i < 33; i++) { - if (key1.pubkey[i] < key2.pubkey[i]) return -1; - if (key1.pubkey[i] > key2.pubkey[i]) return 1; - } - - return 0; - }); - operatorKeys = keys.map((key) => key.privkey); - signers = { - signers: keys.map((key) => { - return { pubkey: key.pubkey, weight: 1 }; - }), - threshold: 2, - nonce: hexlify([++nonce]), - }; - } function hashMessage(data) { const toHash = new Uint8Array(data.length + 1); @@ -70,7 +104,6 @@ describe.only('test', () => { await new Promise((resolve) => setTimeout(resolve, ms)); } - const minimumRotationDelay = 1000; before(async () => { client = new SuiClient({ url: getFullnodeUrl('localnet') }); @@ -84,65 +117,12 @@ describe.only('test', () => { ), ); - let result = await publishPackage(client, deployer, 'axelar_gateway'); - packageId = result.packageId; - const creatorCap = result.publishTxn.objectChanges.find( - (change) => change.objectType === `${packageId}::gateway::CreatorCap`, - ).objectId; - - calculateNextSigners(); - - const encodedSigners = axelarStructs.WeightedSigners.serialize(signers).toBytes(); - const builder = new TxBuilder(client); - - const separator = await builder.moveCall({ - target: `${packageId}::bytes32::new`, - arguments: [domainSeparator], - }); - - await builder.moveCall({ - target: `${packageId}::gateway::setup`, - arguments: [creatorCap, operator.toSuiAddress(), separator, minimumRotationDelay, encodedSigners, '0x6'], - }); - - result = await builder.signAndExecute(deployer); - - gateway = result.objectChanges.find((change) => change.objectType === `${packageId}::gateway::Gateway`).objectId; + const deployment = await deployGateway(client, keypair, deployer, operator); + packageId = deployment.packageId; + gateway = deployment.gateway; }); - it('Should rotate signers', async () => { - await sleep(2000); - const proofSigners = signers; - const proofKeys = operatorKeys; - calculateNextSigners(); - - const encodedSigners = axelarStructs.WeightedSigners.serialize(signers).toBytes(); - - const hashed = hashMessage(encodedSigners); - - const message = axelarStructs.MessageToSign.serialize({ - domain_separator: domainSeparator, - signers_hash: keccak256(axelarStructs.WeightedSigners.serialize(proofSigners).toBytes()), - data_hash: hashed, - }).toBytes(); - - const signatures = sign(proofKeys, message); - const encodedProof = axelarStructs.Proof.serialize({ - signers: proofSigners, - signatures, - }).toBytes(); - - const builder = new TxBuilder(client); - - await builder.moveCall({ - target: `${packageId}::gateway::rotate_signers`, - arguments: [gateway, '0x6', encodedSigners, encodedProof], - }); - - await builder.signAndExecute(keypair); - }); - - it.only('Should not rotate to empty signers', async () => { + it('Should not rotate to empty signers', async () => { await sleep(2000); const proofSigners = signers; const proofKeys = operatorKeys; @@ -182,3 +162,7 @@ describe.only('test', () => { }); }); }); + +module.exports = { + deployGateway +} diff --git a/test/its.js b/test/its.js new file mode 100644 index 00000000..da286910 --- /dev/null +++ b/test/its.js @@ -0,0 +1,54 @@ +const { SuiClient, getFullnodeUrl } = require('@mysten/sui.js/client'); +const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); +const { Secp256k1Keypair } = require('@mysten/sui.js/keypairs/secp256k1'); +const { requestSuiFromFaucetV0, getFaucetHost } = require('@mysten/sui.js/faucet'); +const { publishPackage, getRandomBytes32, expectRevert } = require('./utils'); +const { TxBuilder } = require('../dist/tx-builder'); +const { + bcsStructs: { axelarStructs }, +} = require('../dist/bcs'); +const { arrayify, hexlify, keccak256 } = require('ethers/lib/utils'); +const secp256k1 = require('secp256k1'); +const { deployGateway } = require('./axelar-gateway'); + +async function deployIts(client, keypair) { + const {packageId, gateway} = await deployGateway(client, keypair); + await publishPackage(client, keypair, 'abi'); + await publishPackage(client, keypair, 'governance'); + const result = await publishPackage(client, keypair, 'its'); + + return result; +} + +describe.only('test', () => { + let client; + const operator = Ed25519Keypair.fromSecretKey(arrayify(getRandomBytes32())); + const deployer = Ed25519Keypair.fromSecretKey(arrayify(getRandomBytes32())); + const keypair = Ed25519Keypair.fromSecretKey(arrayify(getRandomBytes32())); + const domainSeparator = getRandomBytes32(); + let packageId; + let its; + + + before(async () => { + client = new SuiClient({ url: getFullnodeUrl('localnet') }); + + await Promise.all( + [operator, deployer, keypair].map((keypair) => + requestSuiFromFaucetV0({ + host: getFaucetHost('localnet'), + recipient: keypair.toSuiAddress(), + }), + ), + ); + + let result = await deployIts(client, deployer); + + packageId = result.packageId; + its = result.publishTxn.objectChanges.find((change) => change.objectType === `${packageId}::its::ITS`).objectId; + }); + + it('Should not rotate to empty signers', async () => { + + }); +}); From b237b8f24b04bfff5aa02abb5e8124f77b65345d Mon Sep 17 00:00:00 2001 From: Foivos Date: Tue, 2 Jul 2024 16:58:49 +0300 Subject: [PATCH 41/47] add a test file --- test/axelar-gateway.js | 47 ++++++++++++++++++++---------------------- test/its.js | 11 ++++------ 2 files changed, 26 insertions(+), 32 deletions(-) diff --git a/test/axelar-gateway.js b/test/axelar-gateway.js index 046b0e02..a45b0dab 100644 --- a/test/axelar-gateway.js +++ b/test/axelar-gateway.js @@ -43,33 +43,32 @@ function calculateNextSigners() { } async function deployGateway(client, keypair, deployer = keypair, operator = keypair) { - let result = await publishPackage(client, deployer, 'axelar_gateway'); - packageId = result.packageId; - const creatorCap = result.publishTxn.objectChanges.find( - (change) => change.objectType === `${packageId}::gateway::CreatorCap`, - ).objectId; + let result = await publishPackage(client, deployer, 'axelar_gateway'); + packageId = result.packageId; + const creatorCap = result.publishTxn.objectChanges.find((change) => change.objectType === `${packageId}::gateway::CreatorCap`).objectId; - calculateNextSigners(); + calculateNextSigners(); - const encodedSigners = axelarStructs.WeightedSigners.serialize(signers).toBytes(); - const builder = new TxBuilder(client); + const encodedSigners = axelarStructs.WeightedSigners.serialize(signers).toBytes(); + const builder = new TxBuilder(client); - const separator = await builder.moveCall({ - target: `${packageId}::bytes32::new`, - arguments: [domainSeparator], - }); + const separator = await builder.moveCall({ + target: `${packageId}::bytes32::new`, + arguments: [domainSeparator], + }); - await builder.moveCall({ - target: `${packageId}::gateway::setup`, - arguments: [creatorCap, operator.toSuiAddress(), separator, minimumRotationDelay, encodedSigners, '0x6'], - }); + await builder.moveCall({ + target: `${packageId}::gateway::setup`, + arguments: [creatorCap, operator.toSuiAddress(), separator, minimumRotationDelay, encodedSigners, '0x6'], + }); - result = await builder.signAndExecute(deployer); + result = await builder.signAndExecute(deployer); - gateway = result.objectChanges.find((change) => change.objectType === `${packageId}::gateway::Gateway`).objectId; - return { - gateway, packageId, - } + gateway = result.objectChanges.find((change) => change.objectType === `${packageId}::gateway::Gateway`).objectId; + return { + gateway, + packageId, + }; } describe('test', () => { @@ -80,7 +79,6 @@ describe('test', () => { let packageId; let gateway; - function hashMessage(data) { const toHash = new Uint8Array(data.length + 1); toHash[0] = COMMAND_TYPE_ROTATE_SIGNERS; @@ -104,7 +102,6 @@ describe('test', () => { await new Promise((resolve) => setTimeout(resolve, ms)); } - before(async () => { client = new SuiClient({ url: getFullnodeUrl('localnet') }); @@ -164,5 +161,5 @@ describe('test', () => { }); module.exports = { - deployGateway -} + deployGateway, +}; diff --git a/test/its.js b/test/its.js index da286910..ed3478d5 100644 --- a/test/its.js +++ b/test/its.js @@ -12,7 +12,7 @@ const secp256k1 = require('secp256k1'); const { deployGateway } = require('./axelar-gateway'); async function deployIts(client, keypair) { - const {packageId, gateway} = await deployGateway(client, keypair); + const { packageId, gateway } = await deployGateway(client, keypair); await publishPackage(client, keypair, 'abi'); await publishPackage(client, keypair, 'governance'); const result = await publishPackage(client, keypair, 'its'); @@ -29,7 +29,6 @@ describe.only('test', () => { let packageId; let its; - before(async () => { client = new SuiClient({ url: getFullnodeUrl('localnet') }); @@ -42,13 +41,11 @@ describe.only('test', () => { ), ); - let result = await deployIts(client, deployer); - + const result = await deployIts(client, deployer); + packageId = result.packageId; its = result.publishTxn.objectChanges.find((change) => change.objectType === `${packageId}::its::ITS`).objectId; }); - it('Should not rotate to empty signers', async () => { - - }); + it('Should not rotate to empty signers', async () => {}); }); From f7c04a09d8db85a24b825b69bc1dc61bc019dfb2 Mon Sep 17 00:00:00 2001 From: Foivos Date: Tue, 30 Jul 2024 16:09:22 +0300 Subject: [PATCH 42/47] fixed move tests --- move/its/sources/coin_management.move | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/move/its/sources/coin_management.move b/move/its/sources/coin_management.move index 1bb890ea..30d3cc6e 100644 --- a/move/its/sources/coin_management.move +++ b/move/its/sources/coin_management.move @@ -6,14 +6,11 @@ module its::coin_management { use sui::balance::{Self, Balance}; use sui::clock::Clock; - use axelar_gateway::channel::Channel; - use its::flow_limit::{Self, FlowLimit}; /// Trying to add a distributor to a `CoinManagement` that does not /// have a `TreasuryCap`. const EDistributorNeedsTreasuryCap: u64 = 0; - const ENotOperator: u64 = 1; /// Struct that stores information about the ITS Coin. public struct CoinManagement has store { @@ -67,22 +64,6 @@ module its::coin_management { self.operator.fill(operator); } - - /// Adds a rate limit to the `CoinManagement`. - /// Note that this rate limit will be calculated for the remote decimals of the token, not for the native decimals. - /// To be used by the designated operator of the contract. - public fun set_flow_limit(self: &mut CoinManagement, channel: &Channel, flow_limit: u64) { - assert!(self.operator.contains(&channel.to_address()), ENotOperator); - self.flow_limit.set_flow_limit(flow_limit); - } - - /// Adds a rate limit to the `CoinManagement`. - /// Note that this rate limit will be calculated for the remote decimals of the token, not for the native decimals. - /// To be used by the ITS operator. - public(package) fun set_flow_limit(self: &mut CoinManagement, flow_limit: u64) { - self.flow_limit.set_flow_limit(flow_limit); - } - // === Protected Methods === /// Takes the given amount of Coins from user. Returns the amount that the ITS is supposed to give on other chains. From 3256b02b69046d694da6de924876796e6ab15588 Mon Sep 17 00:00:00 2001 From: Foivos Date: Tue, 30 Jul 2024 16:11:39 +0300 Subject: [PATCH 43/47] fix lint --- test/its.js | 51 --------------------------------------------------- test/utils.js | 8 ++++---- 2 files changed, 4 insertions(+), 55 deletions(-) delete mode 100644 test/its.js diff --git a/test/its.js b/test/its.js deleted file mode 100644 index ed3478d5..00000000 --- a/test/its.js +++ /dev/null @@ -1,51 +0,0 @@ -const { SuiClient, getFullnodeUrl } = require('@mysten/sui.js/client'); -const { Ed25519Keypair } = require('@mysten/sui.js/keypairs/ed25519'); -const { Secp256k1Keypair } = require('@mysten/sui.js/keypairs/secp256k1'); -const { requestSuiFromFaucetV0, getFaucetHost } = require('@mysten/sui.js/faucet'); -const { publishPackage, getRandomBytes32, expectRevert } = require('./utils'); -const { TxBuilder } = require('../dist/tx-builder'); -const { - bcsStructs: { axelarStructs }, -} = require('../dist/bcs'); -const { arrayify, hexlify, keccak256 } = require('ethers/lib/utils'); -const secp256k1 = require('secp256k1'); -const { deployGateway } = require('./axelar-gateway'); - -async function deployIts(client, keypair) { - const { packageId, gateway } = await deployGateway(client, keypair); - await publishPackage(client, keypair, 'abi'); - await publishPackage(client, keypair, 'governance'); - const result = await publishPackage(client, keypair, 'its'); - - return result; -} - -describe.only('test', () => { - let client; - const operator = Ed25519Keypair.fromSecretKey(arrayify(getRandomBytes32())); - const deployer = Ed25519Keypair.fromSecretKey(arrayify(getRandomBytes32())); - const keypair = Ed25519Keypair.fromSecretKey(arrayify(getRandomBytes32())); - const domainSeparator = getRandomBytes32(); - let packageId; - let its; - - before(async () => { - client = new SuiClient({ url: getFullnodeUrl('localnet') }); - - await Promise.all( - [operator, deployer, keypair].map((keypair) => - requestSuiFromFaucetV0({ - host: getFaucetHost('localnet'), - recipient: keypair.toSuiAddress(), - }), - ), - ); - - const result = await deployIts(client, deployer); - - packageId = result.packageId; - its = result.publishTxn.objectChanges.find((change) => change.objectType === `${packageId}::its::ITS`).objectId; - }); - - it('Should not rotate to empty signers', async () => {}); -}); diff --git a/test/utils.js b/test/utils.js index 1df845cd..88d68b0c 100644 --- a/test/utils.js +++ b/test/utils.js @@ -22,17 +22,17 @@ async function expectRevert(builder, keypair, error = {}) { await builder.signAndExecute(keypair); throw new Error(`Expected revert with ${error} but exeuted successfully instead`); } catch (e) { - errorMessage = e.cause.effects.status.error; + const errorMessage = e.cause.effects.status.error; let regexp = /address: (.*?),/; const packageId = `0x${regexp.exec(errorMessage)[1]}`; - regexp = /Identifier\(\"(.*?)\"\)/; + regexp = /Identifier\("(.*?)"\)/; const module = regexp.exec(errorMessage)[1]; - regexp = /Some\(\"(.*?)\"\)/; + regexp = /Some\("(.*?)"\)/; const functionName = regexp.exec(errorMessage)[1]; - regexp = /Some\(\".*?\"\) \}, (.*?)\)/; + regexp = /Some\(".*?"\) \}, (.*?)\)/; const errorCode = parseInt(regexp.exec(errorMessage)[1]); if (error.packageId && error.packageId !== packageId) { From 88b32a94863079f23277be92c69ef115a36feee8 Mon Sep 17 00:00:00 2001 From: Foivos Date: Tue, 30 Jul 2024 16:16:21 +0300 Subject: [PATCH 44/47] fix js tests --- test/utils.js | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/test/utils.js b/test/utils.js index 88d68b0c..cda066e0 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,15 +1,19 @@ const { keccak256, defaultAbiCoder } = require('ethers/lib/utils'); const { TxBuilder } = require('../dist/tx-builder'); -const { updateMoveToml } = require('../dist/utils'); +const { updateMoveToml, copyMovePackage } = require('../dist/utils'); +const chai = require('chai'); +const { expect } = chai; async function publishPackage(client, keypair, packageName) { + const compileDir = `${__dirname}/../move_compile`; + copyMovePackage(packageName, null, compileDir); const builder = new TxBuilder(client); - await builder.publishPackageAndTransferCap(packageName, keypair.toSuiAddress()); + await builder.publishPackageAndTransferCap(packageName, keypair.toSuiAddress(), compileDir); const publishTxn = await builder.signAndExecute(keypair); const packageId = (publishTxn.objectChanges?.find((a) => a.type === 'published') ?? []).packageId; - updateMoveToml(packageName, packageId); + updateMoveToml(packageName, packageId, compileDir); return { packageId, publishTxn }; } @@ -53,8 +57,33 @@ async function expectRevert(builder, keypair, error = {}) { } } +async function expectEvent(builder, keypair, eventData = {}) { + const response = await builder.signAndExecute(keypair, { showEvents: true }); + + const event = response.events.find((event) => event.type === eventData.type); + + function compare(a, b) { + if (Array.isArray(a)) { + expect(a.length).to.equal(b.length); + + for (let i = 0; i < a.length; i++) { + compare(a[i], b[i]); + } + + return; + } + + expect(a).to.equal(b); + } + + for (const key of Object.keys(eventData.arguments)) { + compare(event.parsedJson[key], eventData.arguments[key]); + } +} + module.exports = { publishPackage, getRandomBytes32, expectRevert, -}; + expectEvent, +}; \ No newline at end of file From 483a0cf50762f1977d52313e7e011ea2d1b49a08 Mon Sep 17 00:00:00 2001 From: Foivos Date: Tue, 30 Jul 2024 16:58:48 +0300 Subject: [PATCH 45/47] fix install --- package-lock.json | 1182 +++++++++++++++++++-------------------------- 1 file changed, 499 insertions(+), 683 deletions(-) diff --git a/package-lock.json b/package-lock.json index 405b31d8..accdf97f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -50,9 +50,9 @@ } }, "node_modules/@0no-co/graphqlsp": { - "version": "1.12.11", - "resolved": "https://registry.npmjs.org/@0no-co/graphqlsp/-/graphqlsp-1.12.11.tgz", - "integrity": "sha512-vLja9r7L6BBXwxW86Wyi5z5hjTHscH7qoQooy+MXHkM9srBB6ZuesYZq5DQ/+SErQrFyaxeY+hwv2qBAksxriw==", + "version": "1.12.12", + "resolved": "https://registry.npmjs.org/@0no-co/graphqlsp/-/graphqlsp-1.12.12.tgz", + "integrity": "sha512-BmCAc/q3tQcIwXxKoxubYaB23s2fWMMmNGSlY9mgQvWiReBS8ZutPZSf11OADfwTv1J1JIazU6q6OFX+cEp8PQ==", "dependencies": { "@gql.tada/internal": "^1.0.0", "graphql": "^15.5.0 || ^16.0.0 || ^17.0.0" @@ -88,30 +88,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.7.tgz", - "integrity": "sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.2.tgz", + "integrity": "sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz", - "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", + "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.7", - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helpers": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/template": "^7.24.7", - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-module-transforms": "^7.25.2", + "@babel/helpers": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.2", + "@babel/types": "^7.25.2", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -136,12 +136,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", - "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz", + "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==", "dev": true, "dependencies": { - "@babel/types": "^7.24.7", + "@babel/types": "^7.25.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" @@ -151,14 +151,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz", - "integrity": "sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", + "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.24.7", - "@babel/helper-validator-option": "^7.24.7", - "browserslist": "^4.22.2", + "@babel/compat-data": "^7.25.2", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -175,43 +175,6 @@ "semver": "bin/semver.js" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", - "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", - "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", - "dev": true, - "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", - "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-module-imports": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", @@ -226,16 +189,15 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz", - "integrity": "sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", + "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", "@babel/helper-module-imports": "^7.24.7", "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7" + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.2" }, "engines": { "node": ">=6.9.0" @@ -257,22 +219,10 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", - "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz", - "integrity": "sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -288,22 +238,22 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz", - "integrity": "sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.7.tgz", - "integrity": "sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.0.tgz", + "integrity": "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==", "dev": true, "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.0" }, "engines": { "node": ">=6.9.0" @@ -325,20 +275,20 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", - "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.0.tgz", + "integrity": "sha512-CzdIU9jdP0dg7HdyB+bHvDJGagUv+qtzZt5rYCWwW6tITNqV9odjp6Qu41gkG0ca5UfdDUWrKkiAnHHdGRnOrA==", "bin": { - "semver": "bin/semver.js" + "parser": "bin/babel-parser.js" }, "engines": { - "node": ">=10" + "node": ">=6.0.0" } }, "node_modules/@babel/runtime": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz", - "integrity": "sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz", + "integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==", "dev": true, "dependencies": { "regenerator-runtime": "^0.14.0" @@ -348,52 +298,49 @@ } }, "node_modules/@babel/template": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", - "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", + "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", "dev": true, "dependencies": { "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/parser": "^7.25.0", + "@babel/types": "^7.25.0" }, "engines": { - "node": ">=4" + "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz", - "integrity": "sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.2.tgz", + "integrity": "sha512-s4/r+a7xTnny2O6FcZzqgT6nE4/GHEdcqj4qAeglbUOh0TeglEfmNJFAd/OLoVtGd6ZhAO8GCVvCNUO5t/VJVQ==", "dev": true, "dependencies": { "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.7", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-hoist-variables": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.2", "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { - "node": ">=4" + "node": ">=6.9.0" } }, "node_modules/@babel/types": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", - "integrity": "sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", + "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.24.7", + "@babel/helper-string-parser": "^7.24.8", "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" }, "engines": { - "node": ">=0.8.0" + "node": ">=6.9.0" } }, "node_modules/@changesets/apply-release-plan": { @@ -418,15 +365,6 @@ "semver": "^7.5.3" } }, - "node_modules/@changesets/apply-release-plan/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/@changesets/assemble-release-plan": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/@changesets/assemble-release-plan/-/assemble-release-plan-6.0.3.tgz", @@ -494,30 +432,6 @@ "changeset": "bin.js" } }, - "node_modules/@changesets/cli/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@changesets/cli/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/@changesets/config": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@changesets/config/-/config-3.0.2.tgz", @@ -610,28 +524,6 @@ "js-yaml": "^3.13.1" } }, - "node_modules/@changesets/parse/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@changesets/parse/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/@changesets/pre": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@changesets/pre/-/pre-2.0.0.tgz", @@ -661,77 +553,6 @@ "p-filter": "^2.1.0" } }, - "node_modules/@changesets/read/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@changesets/read/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@changesets/read/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@changesets/read/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@changesets/read/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@changesets/read/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@changesets/read/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@changesets/should-skip-package": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/@changesets/should-skip-package/-/should-skip-package-0.1.0.tgz", @@ -958,6 +779,12 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -983,6 +810,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -1715,12 +1554,12 @@ } }, "node_modules/@gql.tada/cli-utils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@gql.tada/cli-utils/-/cli-utils-1.5.1.tgz", - "integrity": "sha512-JVLpoXLa4msrE7MHnmW/7fYnIl8dncLom8T/Ghsxu+Kz5iMGnzK2joJN5cZt4ewCAqfCV3HZZ0VH189OalGd9g==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@gql.tada/cli-utils/-/cli-utils-1.5.2.tgz", + "integrity": "sha512-sJRGVOGAFg4M7jDU4ErSq+5tTTVwHRmlTURNoAeukJvIvgDoPA4JDlH2AGmUnqDGi+eMyIJwYDJV5RvZxKT6dg==", "dependencies": { "@0no-co/graphqlsp": "^1.12.9", - "@gql.tada/internal": "1.0.4", + "@gql.tada/internal": "1.0.5", "@vue/compiler-dom": "^3.4.23", "@vue/language-core": "^2.0.17", "graphql": "^15.5.0 || ^16.0.0 || ^17.0.0", @@ -1733,9 +1572,9 @@ } }, "node_modules/@gql.tada/internal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@gql.tada/internal/-/internal-1.0.4.tgz", - "integrity": "sha512-tq0rgoqjhdVqKWEsbrkiX7Qpp5gA4/Br9r9TVBeh3WpJIcuGh5U48UjB4IOxtXBePZdX8E0oc07GjOid/P60Wg==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@gql.tada/internal/-/internal-1.0.5.tgz", + "integrity": "sha512-3rTRBAwfXem4OV0Lm5aM5cShfrUnPFaXc03F78165Q95Zw1dlI7cmsNZK9pmLm5IevjwMHqqT8C1aN1Kb+AJvw==", "dependencies": { "@0no-co/graphql.web": "^1.0.5" }, @@ -1810,9 +1649,9 @@ "dev": true }, "node_modules/@ianvs/prettier-plugin-sort-imports": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@ianvs/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.3.0.tgz", - "integrity": "sha512-OOMtUcO4J3LoL63dOKAe7bn+lSRRPeit2DqNHpx+wvBp3Grejo2PMaK4Mp1mwy8pnat64ccSgk/lBZbsAdLErw==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@ianvs/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.3.1.tgz", + "integrity": "sha512-ZHwbyjkANZOjaBm3ZosADD2OUYGFzQGxfy67HmGZU94mHqe7g1LCMA7YYKB1Cq+UTPCBqlAYapY0KXAjKEw8Sg==", "dev": true, "dependencies": { "@babel/core": "^7.24.0", @@ -1862,9 +1701,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", @@ -1893,19 +1732,6 @@ "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", "dev": true }, - "node_modules/@manypkg/find-root/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@manypkg/find-root/node_modules/fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -1920,45 +1746,6 @@ "node": ">=6 <7 || >=8" } }, - "node_modules/@manypkg/find-root/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@manypkg/find-root/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@manypkg/find-root/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@manypkg/get-packages": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@manypkg/get-packages/-/get-packages-1.1.3.tgz", @@ -2002,9 +1789,9 @@ } }, "node_modules/@mysten/sui": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@mysten/sui/-/sui-1.3.0.tgz", - "integrity": "sha512-KBEM+nzY30i+S1meWage5jU+upNBGSrZxY5v+oz68gj1VluldWwiaf/LtcZ3RnMcnNtkyMkeYpDL9eiMxTBTbQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@mysten/sui/-/sui-1.3.1.tgz", + "integrity": "sha512-TxTYFO9ou/LOk3LQYZIJrZQJ/8UHEqYpT67MbCHYLCxGiPqAnvpIgnVBzJkpYFA/7vR0pQ1e3KELvQrYHnz2Ag==", "dependencies": { "@graphql-typed-document-node/core": "^3.2.0", "@mysten/bcs": "1.0.3", @@ -2195,9 +1982,9 @@ "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" }, "node_modules/@types/node": { - "version": "20.14.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz", - "integrity": "sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==", + "version": "20.14.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.13.tgz", + "integrity": "sha512-+bHoGiZb8UiQ0+WEtmph2IWQCjIqg8MDZMAV+ppRRhUZnquF5mQkP/9vpSwJClEiSM/C7fZZExPzfU0vJTyp8w==", "dependencies": { "undici-types": "~5.26.4" } @@ -2215,16 +2002,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz", - "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", + "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/type-utils": "7.16.0", - "@typescript-eslint/utils": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/type-utils": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -2248,15 +2035,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.0.tgz", - "integrity": "sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", + "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", "debug": "^4.3.4" }, "engines": { @@ -2276,13 +2063,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz", - "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", + "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0" + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2293,13 +2080,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz", - "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", + "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.16.0", - "@typescript-eslint/utils": "7.16.0", + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/utils": "7.18.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -2320,9 +2107,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", - "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", + "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2333,13 +2120,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", - "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", + "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2361,15 +2148,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", - "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", + "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0" + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2383,12 +2170,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz", - "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", + "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/types": "7.18.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2406,52 +2193,61 @@ "dev": true }, "node_modules/@volar/language-core": { - "version": "2.4.0-alpha.16", - "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.0-alpha.16.tgz", - "integrity": "sha512-oOTnIZlx0P/idFwVw+W0NbzKDtZAQMzXSdIFfTePCKcXlb4Ys12GaGkx8NF9dsvPYV3nbv3ZsSxnkZWBmNKd7A==", + "version": "2.4.0-alpha.18", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.0-alpha.18.tgz", + "integrity": "sha512-JAYeJvYQQROmVRtSBIczaPjP3DX4QW1fOqW1Ebs0d3Y3EwSNRglz03dSv0Dm61dzd0Yx3WgTW3hndDnTQqgmyg==", "dependencies": { - "@volar/source-map": "2.4.0-alpha.16" + "@volar/source-map": "2.4.0-alpha.18" } }, "node_modules/@volar/source-map": { - "version": "2.4.0-alpha.16", - "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.0-alpha.16.tgz", - "integrity": "sha512-sL9vNG7iR2hiKZor7UkD5Sufu3QCia4cbp2gX/nGRNSdaPbhOpdAoavwlBm0PrVkpiA19NZuavZoobD8krviFg==" + "version": "2.4.0-alpha.18", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.0-alpha.18.tgz", + "integrity": "sha512-MTeCV9MUwwsH0sNFiZwKtFrrVZUK6p8ioZs3xFzHc2cvDXHWlYN3bChdQtwKX+FY2HG6H3CfAu1pKijolzIQ8g==" }, "node_modules/@vue/compiler-core": { - "version": "3.4.33", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.33.tgz", - "integrity": "sha512-MoIREbkdPQlnGfSKDMgzTqzqx5nmEjIc0ydLVYlTACGBsfvOJ4tHSbZXKVF536n6fB+0eZaGEOqsGThPpdvF5A==", + "version": "3.4.34", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.34.tgz", + "integrity": "sha512-Z0izUf32+wAnQewjHu+pQf1yw00EGOmevl1kE+ljjjMe7oEfpQ+BI3/JNK7yMB4IrUsqLDmPecUrpj3mCP+yJQ==", "dependencies": { "@babel/parser": "^7.24.7", - "@vue/shared": "3.4.33", + "@vue/shared": "3.4.34", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "node_modules/@vue/compiler-dom": { - "version": "3.4.33", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.33.tgz", - "integrity": "sha512-GzB8fxEHKw0gGet5BKlpfXEqoBnzSVWwMnT+dc25wE7pFEfrU/QsvjZMP9rD4iVXHBBoemTct8mN0GJEI6ZX5A==", + "version": "3.4.34", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.34.tgz", + "integrity": "sha512-3PUOTS1h5cskdOJMExCu2TInXuM0j60DRPpSCJDqOCupCfUZCJoyQmKtRmA8EgDNZ5kcEE7vketamRZfrEuVDw==", "dependencies": { - "@vue/compiler-core": "3.4.33", - "@vue/shared": "3.4.33" + "@vue/compiler-core": "3.4.34", + "@vue/shared": "3.4.34" } }, - "node_modules/@vue/language-core": { - "version": "2.0.26", - "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.0.26.tgz", - "integrity": "sha512-/lt6SfQ3O1yDAhPsnLv9iSUgXd1dMHqUm/t3RctfqjuwQf1LnftZ414X3UBn6aXT4MiwXWtbNJ4Z0NZWwDWgJQ==", + "node_modules/@vue/compiler-vue2": { + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz", + "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==", "dependencies": { - "@volar/language-core": "~2.4.0-alpha.15", - "@vue/compiler-dom": "^3.4.0", - "@vue/shared": "^3.4.0", - "computeds": "^0.0.1", + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, + "node_modules/@vue/language-core": { + "version": "2.0.29", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.0.29.tgz", + "integrity": "sha512-o2qz9JPjhdoVj8D2+9bDXbaI4q2uZTHQA/dbyZT4Bj1FR9viZxDJnLcKVHfxdn6wsOzRgpqIzJEEmSSvgMvDTQ==", + "dependencies": { + "@volar/language-core": "~2.4.0-alpha.18", + "@vue/compiler-dom": "^3.4.0", + "@vue/compiler-vue2": "^2.7.16", + "@vue/shared": "^3.4.0", + "computeds": "^0.0.1", "minimatch": "^9.0.3", "muggle-string": "^0.4.1", - "path-browserify": "^1.0.1", - "vue-template-compiler": "^2.7.14" + "path-browserify": "^1.0.1" }, "peerDependencies": { "typescript": "*" @@ -2463,9 +2259,9 @@ } }, "node_modules/@vue/shared": { - "version": "3.4.33", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.33.tgz", - "integrity": "sha512-aoRY0jQk3A/cuvdkodTrM4NMfxco8n55eG4H7ML/CRy7OryHfiqvug4xrCBBMbbN+dvXAetDDwZW9DXWWjBntA==" + "version": "3.4.34", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.34.tgz", + "integrity": "sha512-x5LmiRLpRsd9KTjAB8MPKf0CDPMcuItjP0gbNqFCIgL1I8iYp4zglhj9w9FPCdIbHG2M91RVeIbArFfFTz9I3A==" }, "node_modules/acorn": { "version": "8.12.1", @@ -2551,25 +2347,15 @@ "node": ">= 8" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" + "sprintf-js": "~1.0.2" } }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, "node_modules/aria-query": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", @@ -2833,18 +2619,6 @@ "node": ">=8" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", @@ -2857,9 +2631,9 @@ "dev": true }, "node_modules/browserslist": { - "version": "4.23.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz", - "integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", + "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", "dev": true, "funding": [ { @@ -2876,10 +2650,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001629", - "electron-to-chromium": "^1.4.796", + "caniuse-lite": "^1.0.30001640", + "electron-to-chromium": "^1.4.820", "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.16" + "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" @@ -2937,9 +2711,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001640", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001640.tgz", - "integrity": "sha512-lA4VMpW0PSUrFnkmVuEKBUovSWKhj7puyCg8StBChgu298N1AtuF1sKWEvfDuimSEDbhlb/KqPKC3fs1HbuQUA==", + "version": "1.0.30001644", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001644.tgz", + "integrity": "sha512-YGvlOZB4QhZuiis+ETS0VXR+MExbFf4fZYYeMTEE0aTQd/RdIjkTyZjLrbYVKnHzppDvnOhritRVv+i7Go6mHw==", "dev": true, "funding": [ { @@ -2957,9 +2731,9 @@ ] }, "node_modules/chai": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", - "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", "dev": true, "dependencies": { "assertion-error": "^1.1.0", @@ -2968,7 +2742,7 @@ "get-func-name": "^2.0.2", "loupe": "^2.3.6", "pathval": "^1.1.1", - "type-detect": "^4.0.8" + "type-detect": "^4.1.0" }, "engines": { "node": ">=4" @@ -3068,56 +2842,6 @@ "wrap-ansi": "^7.0.0" } }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, "node_modules/code-red": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.4.tgz", @@ -3272,9 +2996,9 @@ "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==" }, "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -3427,15 +3151,15 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.820", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.820.tgz", - "integrity": "sha512-kK/4O/YunacfboFEk/BDf7VO1HoPmDudLTJAU9NmXIOSjsV7qVIX3OrI4REZo0VmdqhcpUcncQc6N8Q3aEXlHg==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.3.tgz", + "integrity": "sha512-QNdYSS5i8D9axWp/6XIezRObRHqaav/ur9z1VzCDUCH1XIFOr9WQk5xmgunhsTpjjgDy3oLxO/WMOVZlpUQrlA==", "dev": true }, "node_modules/elliptic": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.5.tgz", - "integrity": "sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw==", + "version": "6.5.6", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.6.tgz", + "integrity": "sha512-mpzdtpeCLuS3BmE3pO3Cpp5bbjlOPY2Q0PgoF+Od1XZrHLYI28Xe3ossCmYCQt11FQKEYd9+PF8jymTvtWJSHQ==", "dependencies": { "bn.js": "^4.11.9", "brorand": "^1.1.0", @@ -4042,6 +3766,12 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/eslint/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, "node_modules/eslint/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -4098,6 +3828,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eslint/node_modules/globals": { "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", @@ -4122,6 +3868,33 @@ "node": ">=8" } }, + "node_modules/eslint/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eslint/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -4134,6 +3907,36 @@ "node": "*" } }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eslint/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -4382,19 +4185,16 @@ } }, "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "dependencies": { - "locate-path": "^6.0.0", + "locate-path": "^5.0.0", "path-exists": "^4.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/find-yarn-workspace-root2": { @@ -4511,20 +4311,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -4731,14 +4517,14 @@ } }, "node_modules/gql.tada": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/gql.tada/-/gql.tada-1.8.2.tgz", - "integrity": "sha512-LLt+2RcLY6i+Rq+LQQwx3uiEAPfA+pmEaAo/bJjUdaV1CVJBy3Wowds6GHeerW5kvekRM/XdbPTJw5OvnLq/DQ==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/gql.tada/-/gql.tada-1.8.3.tgz", + "integrity": "sha512-0H81I3M54jKTDHbnNWhXDf57Ie2d2raxnFCc93zdYjXHnrXe522jrio9AAFwqBlGx/xtaP3ILSSUw7J9H31LAA==", "dependencies": { "@0no-co/graphql.web": "^1.0.5", "@0no-co/graphqlsp": "^1.12.9", - "@gql.tada/cli-utils": "1.5.1", - "@gql.tada/internal": "1.0.4" + "@gql.tada/cli-utils": "1.5.2", + "@gql.tada/internal": "1.0.5" }, "bin": { "gql-tada": "bin/cli.js", @@ -4915,6 +4701,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -5023,9 +4818,9 @@ } }, "node_modules/is-core-module": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", - "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", + "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", "dev": true, "dependencies": { "hasown": "^2.0.2" @@ -5313,12 +5108,13 @@ "dev": true }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "dependencies": { - "argparse": "^2.0.1" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" @@ -5403,11 +5199,11 @@ "integrity": "sha512-2nDge6qlAjcwyslAhWfVumlkeSNK5+WCfKa2/VEq9prvlT5vP2FR0m0o5hmKaYqfsZ4TQVj5czQsimZvXDB1CQ==" }, "node_modules/libsodium-wrappers-sumo": { - "version": "0.7.13", - "resolved": "https://registry.npmjs.org/libsodium-wrappers-sumo/-/libsodium-wrappers-sumo-0.7.13.tgz", - "integrity": "sha512-lz4YdplzDRh6AhnLGF2Dj2IUj94xRN6Bh8T0HLNwzYGwPehQJX6c7iYVrFUPZ3QqxE0bqC+K0IIqqZJYWumwSQ==", + "version": "0.7.14", + "resolved": "https://registry.npmjs.org/libsodium-wrappers-sumo/-/libsodium-wrappers-sumo-0.7.14.tgz", + "integrity": "sha512-0lm7ZwN5a95J2yUi8R1rgQeeaVDIWnvNzgVmXmZswis4mC+bQtbDrB+QpJlL4qklaKx3hVpJjoc6ubzJFiv64Q==", "dependencies": { - "libsodium-sumo": "^0.7.13" + "libsodium-sumo": "^0.7.14" } }, "node_modules/load-yaml-file": { @@ -5425,28 +5221,6 @@ "node": ">=6" } }, - "node_modules/load-yaml-file/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/load-yaml-file/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/locate-character": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", @@ -5454,18 +5228,15 @@ "peer": true }, "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "dependencies": { - "p-locate": "^5.0.0" + "p-locate": "^4.1.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/lodash.merge": { @@ -5598,12 +5369,12 @@ } }, "node_modules/magic-string": { - "version": "0.30.10", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", - "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", + "version": "0.30.11", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", + "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", "peer": true, "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" + "@jridgewell/sourcemap-codec": "^1.5.0" } }, "node_modules/mdn-data": { @@ -5687,9 +5458,9 @@ } }, "node_modules/mocha": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.6.0.tgz", - "integrity": "sha512-hxjt4+EEB0SA0ZDygSS015t65lJw/I2yRCS3Ae+SJ5FrbzrXgfYwJr96f0OvIXdj7h4lv/vLCrH3rkiuizFSvw==", + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.0.tgz", + "integrity": "sha512-v8/rBWr2VO5YkspYINnvu81inSz2y3ODJrhO175/Exzor1RcEZZkizgE2A+w/CAXXoESS8Kys5E62dOHGHzULA==", "dev": true, "dependencies": { "ansi-colors": "^4.1.3", @@ -5721,6 +5492,12 @@ "node": ">= 14.0.0" } }, + "node_modules/mocha/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, "node_modules/mocha/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -5733,6 +5510,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/mocha/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mocha/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -5742,6 +5535,33 @@ "node": ">=8" } }, + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/mocha/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mocha/node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", @@ -5760,6 +5580,36 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, + "node_modules/mocha/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -5826,9 +5676,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", "dev": true }, "node_modules/normalize-path": { @@ -5981,33 +5831,30 @@ } }, "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { - "yocto-queue": "^0.1.0" + "p-try": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { - "p-limit": "^3.0.2" + "p-limit": "^2.2.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/p-map": { @@ -6169,80 +6016,89 @@ "node": ">=8" } }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/preferred-pm": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/preferred-pm/-/preferred-pm-3.1.4.tgz", + "integrity": "sha512-lEHd+yEm22jXdCphDrkvIJQU66EuLojPPtvZkpKIkiD+l0DMThF/niqZKJSoU8Vl7iuvtmzyMhir9LdVy5WMnA==", "dev": true, "dependencies": { - "p-locate": "^4.1.0" + "find-up": "^5.0.0", + "find-yarn-workspace-root2": "1.2.16", + "path-exists": "^4.0.0", + "which-pm": "^2.2.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/preferred-pm/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "dependencies": { - "p-try": "^2.0.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/preferred-pm/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "dependencies": { - "p-limit": "^2.2.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "node_modules/preferred-pm/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/preferred-pm": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/preferred-pm/-/preferred-pm-3.1.3.tgz", - "integrity": "sha512-MkXsENfftWSRpzCzImcp4FRsCc3y1opwB73CfCNWyzMqArju2CrlMHlqB7VexKiPEOjGMbttv1r9fSCn5S610w==", + "node_modules/preferred-pm/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { - "find-up": "^5.0.0", - "find-yarn-workspace-root2": "1.2.16", - "path-exists": "^4.0.0", - "which-pm": "2.0.0" + "p-limit": "^3.0.2" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/prelude-ls": { @@ -6270,9 +6126,9 @@ } }, "node_modules/prettier-plugin-sort-imports": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-1.8.5.tgz", - "integrity": "sha512-PkizzuO2S8h3kJeWHytnMZXqvv/fD6g+en/dhv4y5QjoiMm1wq3FWzFiFT7c/BilX95l0ZIqJTlMsXYs8z/WQQ==", + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-1.8.6.tgz", + "integrity": "sha512-jOEzFCyvdDL8geCmr4DP/VBKULZ6OaDQHBEmHTuFHf4EzWyedmwnHg2KawNy5rnrQ6gnCqwrfgymMQZctzCE1Q==", "dev": true, "dependencies": { "prettier": "^3.1.1" @@ -6282,9 +6138,9 @@ } }, "node_modules/prettier-plugin-sort-imports/node_modules/prettier": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", - "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -6391,28 +6247,6 @@ "node": ">=6" } }, - "node_modules/read-yaml-file/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/read-yaml-file/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -6493,12 +6327,12 @@ } }, "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/reusify": { @@ -6674,9 +6508,9 @@ } }, "node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -6694,15 +6528,6 @@ "randombytes": "^2.1.0" } }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -7154,9 +6979,9 @@ } }, "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", "dev": true, "engines": { "node": ">=4" @@ -7248,9 +7073,9 @@ } }, "node_modules/typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -7332,15 +7157,6 @@ "resolved": "https://registry.npmjs.org/valibot/-/valibot-0.36.0.tgz", "integrity": "sha512-CjF1XN4sUce8sBK9TixrDqFM7RwNkuXdJu174/AwmQUB62QbCQADg5lLe8ldBalFgtj1uKj+pKwDJiNo4Mn+eQ==" }, - "node_modules/vue-template-compiler": { - "version": "2.7.16", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz", - "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==", - "dependencies": { - "de-indent": "^1.0.2", - "he": "^1.2.0" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -7373,9 +7189,9 @@ } }, "node_modules/which-pm": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-pm/-/which-pm-2.0.0.tgz", - "integrity": "sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/which-pm/-/which-pm-2.2.0.tgz", + "integrity": "sha512-MOiaDbA5ZZgUjkeMWM5EkJp4loW5ZRoa5bc3/aeMox/PJelMhE6t7S/mLuiY43DBupyxH+S0U1bTui9kWUlmsw==", "dev": true, "dependencies": { "load-yaml-file": "^0.2.0", From 609792688ba22555993da01de89eb9815f4531a0 Mon Sep 17 00:00:00 2001 From: Foivos Date: Tue, 30 Jul 2024 17:05:56 +0300 Subject: [PATCH 46/47] prettier --- test/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/utils.js b/test/utils.js index cda066e0..f479b78e 100644 --- a/test/utils.js +++ b/test/utils.js @@ -86,4 +86,4 @@ module.exports = { getRandomBytes32, expectRevert, expectEvent, -}; \ No newline at end of file +}; From b5fa66a0a24cca7cda40adff7a4b2d5cb571ff4b Mon Sep 17 00:00:00 2001 From: Foivos Date: Tue, 30 Jul 2024 17:23:35 +0300 Subject: [PATCH 47/47] fix move.toml --- move/abi/Move.toml | 1 - move/axelar_gateway/Move.toml | 1 - move/gas_service/Move.toml | 1 - move/governance/Move.toml | 1 - move/its/Move.toml | 1 - move/squid/Move.toml | 1 - move/test/Move.toml | 1 - 7 files changed, 7 deletions(-) diff --git a/move/abi/Move.toml b/move/abi/Move.toml index 06f87e85..55300848 100644 --- a/move/abi/Move.toml +++ b/move/abi/Move.toml @@ -1,7 +1,6 @@ [package] name = "Abi" version = "0.1.0" -published-at = "0x4ee08bf35bdb2afbcc4f968a38dc2303106f3dfeedfe8c7919d47da7c90b8c4e" edition = "2024.beta" [dependencies] diff --git a/move/axelar_gateway/Move.toml b/move/axelar_gateway/Move.toml index 3c3e9d47..fab31178 100644 --- a/move/axelar_gateway/Move.toml +++ b/move/axelar_gateway/Move.toml @@ -1,7 +1,6 @@ [package] name = "AxelarGateway" version = "0.1.0" -published-at = "0xe55593abd7b439764115a766b55b789048f473a52a2c0e7952447ab8ec05f1bc" edition = "2024.beta" [dependencies] diff --git a/move/gas_service/Move.toml b/move/gas_service/Move.toml index 9b0d6b95..a9c0f632 100644 --- a/move/gas_service/Move.toml +++ b/move/gas_service/Move.toml @@ -1,7 +1,6 @@ [package] name = "GasService" version = "0.1.0" -published-at = "0x9249adc3fac09edb21a0848af2ccf4901ffb3689124bc91d67bc613903ca643c" edition = "2024.beta" [dependencies] diff --git a/move/governance/Move.toml b/move/governance/Move.toml index 460efb4b..04f1fdf8 100644 --- a/move/governance/Move.toml +++ b/move/governance/Move.toml @@ -1,7 +1,6 @@ [package] name = "Governance" version = "0.1.0" -published-at = "0xb9e48a2b95661318fed02f48b88f0d497fc768bebaed9467fdaf7317af9b5ef2" edition = "2024.beta" [dependencies] diff --git a/move/its/Move.toml b/move/its/Move.toml index 4fac3d01..b34bdb53 100644 --- a/move/its/Move.toml +++ b/move/its/Move.toml @@ -1,7 +1,6 @@ [package] name = "ITS" version = "0.1.0" -published-at = "0xdee89af6230d63b16d42c23851a2b7b464a6ee96292fe9720b5aefc527164dbc" edition = "2024.beta" [dependencies] diff --git a/move/squid/Move.toml b/move/squid/Move.toml index ba562c6d..ddebc93f 100644 --- a/move/squid/Move.toml +++ b/move/squid/Move.toml @@ -1,7 +1,6 @@ [package] name = "Squid" version = "0.1.0" -published-at = "0x742acc52f94b86d3a2a4fdc39b1e0d75812f05253f88443754326c1e31cae873" edition = "2024.beta" [dependencies] diff --git a/move/test/Move.toml b/move/test/Move.toml index 4d33e6bd..69335454 100644 --- a/move/test/Move.toml +++ b/move/test/Move.toml @@ -1,7 +1,6 @@ [package] name = "Test" version = "0.1.0" -published-at = "0x64cb77be32074cff87043543664dafb4eb766f980d08694cffca8c8136321872" edition = "2024.beta" [dependencies]