From a9b9683b15bd19390b900dc0515dc2fd30801761 Mon Sep 17 00:00:00 2001 From: Milap Sheth Date: Thu, 30 May 2024 05:08:27 -0400 Subject: [PATCH] feat: sui deployment script --- .npmignore | 3 +++ package.json | 4 ++-- scripts/gateway.js | 7 +++++-- scripts/governance.js | 5 +++-- scripts/publish-all.js | 3 +++ scripts/publish-package.js | 7 ++++++- scripts/test-receive-call.js | 12 +++++++++--- scripts/utils.js | 16 ++++++++++++++-- 8 files changed, 45 insertions(+), 12 deletions(-) diff --git a/.npmignore b/.npmignore index e7c4a4ba..6ca6eaa7 100644 --- a/.npmignore +++ b/.npmignore @@ -21,3 +21,6 @@ logs # workflows .github + +# Sui dep +/sui diff --git a/package.json b/package.json index cd502b5f..7dac40f8 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,8 @@ "build": "for d in ./move/*/; do cd $d; sui move build --lint --warnings-are-errors & cd ../../; done; wait", "test": "for d in ./move/*/; do sui move test --path $d ; done", "coverage": "./scripts/coverage.sh", - "lint": "eslint --fix '**/*.js'", - "prettier": "prettier --write '**/*.js'" + "lint": "eslint --fix './scripts/*.js'", + "prettier": "prettier --write './scripts/*.js'" }, "keywords": [ "axelar", diff --git a/scripts/gateway.js b/scripts/gateway.js index 113b81dc..6b518213 100644 --- a/scripts/gateway.js +++ b/scripts/gateway.js @@ -10,7 +10,7 @@ const secp256k1 = require('secp256k1'); function hashMessage(data) { // sorry for putting it here... const messagePrefix = new Uint8Array(Buffer.from('\x19Sui Signed Message:\n', 'ascii')); - let hashed = new Uint8Array(messagePrefix.length + data.length); + const hashed = new Uint8Array(messagePrefix.length + data.length); hashed.set(messagePrefix); hashed.set(data, messagePrefix.length); @@ -66,11 +66,13 @@ function getOperators(axelarInfo) { 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)); } @@ -85,6 +87,7 @@ function getRandomOperators(n = 5) { const bByte = pubKeys[b][i]; if (aByte != bByte) return aByte - bByte; } + return 0; }); pubKeys = indices.map((i) => pubKeys[i]); @@ -124,7 +127,7 @@ function getInputForMessage(info, message) { const input = bcs .ser('Input', { data: message, - proof: proof, + proof, }) .toBytes(); return input; diff --git a/scripts/governance.js b/scripts/governance.js index 8debef5e..05843a61 100644 --- a/scripts/governance.js +++ b/scripts/governance.js @@ -5,7 +5,7 @@ async function initializeGovernance(upgradeCap, client, keypair, env) { const governanceConfig = getConfig('governance', env.alias); const packageId = governanceConfig.packageId; - let tx = new TransactionBlock(); + const tx = new TransactionBlock(); tx.moveCall({ target: `${packageId}::governance::new`, arguments: [ @@ -27,7 +27,7 @@ async function initializeGovernance(upgradeCap, client, keypair, env) { requestType: 'WaitForLocalExecution', }); - const governance = publishTxn.objectChanges.find((obj) => obj.objectType == `${packageId}::governance::Governance`); + const governance = publishTxn.objectChanges.find((obj) => obj.objectType === `${packageId}::governance::Governance`); governanceConfig['governance::Governance'] = await getFullObject(governance, client); setConfig('governance', env.alias, governanceConfig); @@ -39,6 +39,7 @@ async function takeUpgradeCaps(upgradeCaps, client, keypair, env) { const governanceConfig = getConfig('governance', env.alias); const packageId = governanceConfig.packageId; tx = new TransactionBlock(); + for (const upgradeCap of upgradeCaps) { tx.moveCall({ target: `${packageId}::governance::take_upgrade_cap`, diff --git a/scripts/publish-all.js b/scripts/publish-all.js index d9e53956..436ad74f 100644 --- a/scripts/publish-all.js +++ b/scripts/publish-all.js @@ -10,8 +10,10 @@ 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); @@ -65,6 +67,7 @@ if (require.main === module) { if (faucet) { requestSuiFromFaucet(env, address); } + await publishAll(client, keypair, env); })(); } diff --git a/scripts/publish-package.js b/scripts/publish-package.js index 55762558..76278869 100644 --- a/scripts/publish-package.js +++ b/scripts/publish-package.js @@ -9,7 +9,7 @@ const tmp = require('tmp'); const fs = require('fs'); async function publishPackage(packageName, client, keypair) { - let toml = fs.readFileSync(`${__dirname}/../move/${packageName}/Move.toml`, 'utf8'); + const toml = fs.readFileSync(`${__dirname}/../move/${packageName}/Move.toml`, 'utf8'); fs.writeFileSync(`${__dirname}/../move/${packageName}/Move.toml`, fillAddresses(toml, '0x0', packageName)); // remove all controlled temporary objects on process exit @@ -62,9 +62,11 @@ function updateMoveToml(packageName, packageId) { 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'); } @@ -72,6 +74,7 @@ function insertPublishedAt(toml, packageId) { 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('='); @@ -82,6 +85,7 @@ function fillAddresses(toml, address, packageName) { lines[i] = line.slice(0, eqIndex + 1) + ` "${address}"`; } + return lines.join('\n'); } @@ -90,6 +94,7 @@ async function publishPackageFull(packageName, client, keypair, env) { 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); diff --git a/scripts/test-receive-call.js b/scripts/test-receive-call.js index a6b58339..a25c3e07 100644 --- a/scripts/test-receive-call.js +++ b/scripts/test-receive-call.js @@ -40,6 +40,7 @@ async function receiveCall(client, keypair, axelarInfo, sourceChain, sourceAddre }, ]; let is_final = false; + while (!is_final) { const tx = new TransactionBlock(); makeCalls(tx, moveCalls, payload); @@ -53,6 +54,7 @@ async function receiveCall(client, keypair, axelarInfo, sourceChain, sourceAddre is_final = nextTx.is_final; moveCalls = nextTx.move_calls; } + const tx = new TransactionBlock(); const ApprovedMessage = tx.moveCall({ target: `${axelarPackageId}::gateway::take_approved_message`, @@ -80,6 +82,7 @@ async function receiveCall(client, keypair, axelarInfo, sourceChain, sourceAddre 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]; @@ -107,6 +110,7 @@ function getTransactionBcs() { }); return bcs; } + function buildMoveCall(tx, moveCallInfo, payload, callContractObj, previousReturns) { const decodeArgs = (args, tx) => args.map((arg) => { @@ -120,9 +124,10 @@ function buildMoveCall(tx, moveCallInfo, payload, callContractObj, previousRetur return tx.pure(bcsEncoder.vector(bcsEncoder.u8()).serialize(arrayify(payload))); } else if (arg[0] === 4) { return previousReturns[arg[1]][arg[2]]; - } else { - throw new Error(`Invalid argument prefix: ${arg[0]}`); } + + throw new Error(`Invalid argument prefix: ${arg[0]}`); + }); const decodeDescription = (description) => `${description.package_id}::${description.module_name}::${description.name}`; return { @@ -136,6 +141,7 @@ module.exports = { receiveCall, getTransactionBcs, }; + if (require.main === module) { (async () => { const env = process.argv[2] || 'localnet'; @@ -155,7 +161,7 @@ if (require.main === module) { const payload = '0x1234'; - let tx = new TransactionBlock(); + const tx = new TransactionBlock(); tx.moveCall({ target: `${testPackageId}::test::register_transaction`, arguments: [tx.object(discovery.objectId), tx.object(test.objectId)], diff --git a/scripts/utils.js b/scripts/utils.js index 4837cdea..6e4882d1 100644 --- a/scripts/utils.js +++ b/scripts/utils.js @@ -13,22 +13,26 @@ 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; - let length = symbol.length; + const length = symbol.length; let moduleName = ''; while (isNumber(symbol[i])) { i++; } + while (i < length) { - let char = symbol[i]; + const char = symbol[i]; + if (isLowercase(char) || isNumber(char)) { moduleName += char; } else if (isUppercase(char)) { @@ -36,8 +40,10 @@ function getModuleNameFromSymbol(symbol) { } else if (char == '_' || char == ' ') { moduleName += '_'; } + i++; } + return moduleName; } @@ -66,11 +72,13 @@ function setConfig(packagePath, envAlias, config) { } } } + 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)); } @@ -93,6 +101,7 @@ async function getFullObject(object, client) { delete object[field]; } } + const objectResponce = await client.getObject({ id: object.objectId, options: { @@ -104,6 +113,7 @@ async function getFullObject(object, client) { function decodeFields(fields, object) { for (const key in fields) { if (key === 'id') continue; + if (fields[key].fields) { if (!fields[key].fields.id) { object[key] = {}; @@ -117,8 +127,10 @@ async function getFullObject(object, client) { object[key] = fields[key]; } } + return object; } + decodeFields(fields, object); return object; }