diff --git a/README.md b/README.md index 396e8f5..02e7dcf 100644 --- a/README.md +++ b/README.md @@ -28,15 +28,11 @@ The blueprint provides several management jobs that can be triggered through the - Configure privileged executors - Manage executor permissions -3. **Batch Poster Configuration** - - Set batch poster addresses - - Enable/disable batch posters - -4. **Fee Management** +3. **Fee Management** - Configure fee recipients - Set fee distribution weights -5. **Fast Withdrawals** +4. **Fast Withdrawals** - Configure withdrawal confirmers - Enable/disable fast withdrawal functionality diff --git a/blueprints/arbitrum-orbit/dist/add-executors.d.ts b/blueprints/arbitrum-orbit/dist/add-executors.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/blueprints/arbitrum-orbit/dist/add-executors.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/blueprints/arbitrum-orbit/dist/add-executors.js b/blueprints/arbitrum-orbit/dist/add-executors.js new file mode 100644 index 0000000..80d0820 --- /dev/null +++ b/blueprints/arbitrum-orbit/dist/add-executors.js @@ -0,0 +1,54 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const arbitrum_orbit_toolkit_1 = require("arbitrum-orbit-toolkit"); +const viem_1 = require("viem"); +const accounts_1 = require("viem/accounts"); +function validateParams(params) { + if (!params || typeof params !== "object") { + throw new Error("Invalid params: must be an object"); + } + const requiredFields = [ + "parentChainRpc", + "orbitChainRpc", + "chainId", + "chainName", + "chainNetworkName", + "nativeCurrency", + "ownerPrivateKey", + "rollupAddress", + "upgradeExecutor", + "newExecutors", + ]; + for (const field of requiredFields) { + if (!(field in params)) { + throw new Error(`Missing required field: ${field}`); + } + } +} +async function main() { + const params = JSON.parse(process.argv[2]); + validateParams(params); + const parentChainClient = (0, viem_1.createPublicClient)({ + transport: (0, viem_1.http)(params.parentChainRpc), + }); + const orbitChainClient = (0, arbitrum_orbit_toolkit_1.createOrbitChainClient)(params.chainId, params.chainName, params.chainNetworkName, { + name: params.currencyName, + symbol: params.currencySymbol, + decimals: params.currencyDecimals, + }, params.orbitChainRpc, params.rollupAddress); + let account = (0, accounts_1.privateKeyToAccount)(params.ownerPrivateKey); + try { + const result = await (0, arbitrum_orbit_toolkit_1.addPrivilegedExecutors)({ + rollupAddress: params.rollupAddress, + newExecutors: params.newExecutors, + upgradeExecutor: params.upgradeExecutor, + owner: account, + }, parentChainClient, orbitChainClient); + console.log(JSON.stringify({ transactionHash: result })); + } + catch (error) { + console.error(error); + process.exit(1); + } +} +main().catch(console.error); diff --git a/blueprints/arbitrum-orbit/dist/configure-fast-withdrawals.d.ts b/blueprints/arbitrum-orbit/dist/configure-fast-withdrawals.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/blueprints/arbitrum-orbit/dist/configure-fast-withdrawals.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/blueprints/arbitrum-orbit/dist/configure-fast-withdrawals.js b/blueprints/arbitrum-orbit/dist/configure-fast-withdrawals.js new file mode 100644 index 0000000..95d9348 --- /dev/null +++ b/blueprints/arbitrum-orbit/dist/configure-fast-withdrawals.js @@ -0,0 +1,47 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const arbitrum_orbit_toolkit_1 = require("arbitrum-orbit-toolkit"); +const viem_1 = require("viem"); +const accounts_1 = require("viem/accounts"); +function validateParams(params) { + if (!params || typeof params !== "object") { + throw new Error("Invalid params: must be an object"); + } + const requiredFields = [ + "parentChainRpc", + "ownerPrivateKey", + "ownerAddress", + "rollupAddress", + "upgradeExecutor", + "minimumAssertionPeriod", + "fastConfirmer", + ]; + for (const field of requiredFields) { + if (!(field in params)) { + throw new Error(`Missing required field: ${field}`); + } + } +} +async function main() { + const params = JSON.parse(process.argv[2]); + validateParams(params); + const parentChainClient = (0, viem_1.createPublicClient)({ + transport: (0, viem_1.http)(params.parentChainRpc), + }); + const account = (0, accounts_1.privateKeyToAccount)(params.ownerPrivateKey); + try { + const result = await (0, arbitrum_orbit_toolkit_1.setupFastWithdrawal)({ + rollupAddress: params.rollupAddress, + owner: account, + upgradeExecutor: params.upgradeExecutor, + minimumAssertionPeriod: params.minimumAssertionPeriod, + fastConfirmer: params.fastConfirmer, + }, parentChainClient); + console.log(JSON.stringify(result)); + } + catch (error) { + console.error(error); + process.exit(1); + } +} +main().catch(console.error); diff --git a/blueprints/arbitrum-orbit/dist/configure-fee-recipients.d.ts b/blueprints/arbitrum-orbit/dist/configure-fee-recipients.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/blueprints/arbitrum-orbit/dist/configure-fee-recipients.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/blueprints/arbitrum-orbit/scripts/configure-fee-recipients.ts b/blueprints/arbitrum-orbit/dist/configure-fee-recipients.js similarity index 57% rename from blueprints/arbitrum-orbit/scripts/configure-fee-recipients.ts rename to blueprints/arbitrum-orbit/dist/configure-fee-recipients.js index 49af644..ab7798d 100644 --- a/blueprints/arbitrum-orbit/scripts/configure-fee-recipients.ts +++ b/blueprints/arbitrum-orbit/dist/configure-fee-recipients.js @@ -1,14 +1,14 @@ -import { setFeeRecipients } from 'arbitrum-orbit-toolkit'; -import { createPublicClient, http } from 'viem'; - +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const arbitrum_orbit_toolkit_1 = require("arbitrum-orbit-toolkit"); +const viem_1 = require("viem"); async function main() { const params = JSON.parse(process.argv[2]); - const parentChainClient = createPublicClient({ - transport: http(process.env.PARENT_CHAIN_RPC) + const parentChainClient = (0, viem_1.createPublicClient)({ + transport: (0, viem_1.http)(process.env.PARENT_CHAIN_RPC) }); - try { - const result = await setFeeRecipients({ + const result = await (0, arbitrum_orbit_toolkit_1.setFeeRecipients)({ rollupAddress: params.rollup_address, recipients: params.recipients, weights: params.weights, @@ -18,12 +18,11 @@ async function main() { account: process.env.OWNER_PRIVATE_KEY } }, parentChainClient); - console.log(JSON.stringify({ transactionHash: result })); - } catch (error) { + } + catch (error) { console.error(error); process.exit(1); } } - -main().catch(console.error); \ No newline at end of file +main().catch(console.error); diff --git a/blueprints/arbitrum-orbit/dist/configure-token-bridge.d.ts b/blueprints/arbitrum-orbit/dist/configure-token-bridge.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/blueprints/arbitrum-orbit/dist/configure-token-bridge.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/blueprints/arbitrum-orbit/dist/configure-token-bridge.js b/blueprints/arbitrum-orbit/dist/configure-token-bridge.js new file mode 100644 index 0000000..43e0963 --- /dev/null +++ b/blueprints/arbitrum-orbit/dist/configure-token-bridge.js @@ -0,0 +1,53 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const arbitrum_orbit_toolkit_1 = require("arbitrum-orbit-toolkit"); +const viem_1 = require("viem"); +const accounts_1 = require("viem/accounts"); +function validateParams(params) { + if (!params || typeof params !== "object") { + throw new Error("Invalid params: must be an object"); + } + const requiredFields = [ + "parentChainRpc", + "orbitChainRpc", + "chainName", + "chainNetworkName", + "currencyName", + "currencySymbol", + "currencyDecimals", + "ownerPrivateKey", + "rollupAddress", + "nativeToken", + ]; + for (const field of requiredFields) { + if (!(field in params)) { + throw new Error(`Missing required field: ${field}`); + } + } +} +async function main() { + const params = JSON.parse(process.argv[2]); + validateParams(params); + const parentChainClient = (0, viem_1.createPublicClient)({ + transport: (0, viem_1.http)(params.parentChainRpc), + }); + const orbitChainClient = (0, arbitrum_orbit_toolkit_1.createOrbitChainClient)(params.orbitChainId, params.chainName, params.chainNetworkName, { + name: params.currencyName, + symbol: params.currencySymbol, + decimals: params.currencyDecimals, + }, params.orbitChainRpc, params.rollupAddress); + const account = (0, accounts_1.privateKeyToAccount)(params.ownerPrivateKey); + try { + const result = await (0, arbitrum_orbit_toolkit_1.createTokenBridge)({ + rollupAddress: params.rollupAddress, + nativeToken: params.nativeToken, + owner: account, + }, parentChainClient, orbitChainClient); + console.log(JSON.stringify(result)); + } + catch (error) { + console.error(error); + process.exit(1); + } +} +main().catch(console.error); diff --git a/blueprints/arbitrum-orbit/dist/deploy-rollup.d.ts b/blueprints/arbitrum-orbit/dist/deploy-rollup.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/blueprints/arbitrum-orbit/dist/deploy-rollup.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/blueprints/arbitrum-orbit/dist/deploy-rollup.js b/blueprints/arbitrum-orbit/dist/deploy-rollup.js new file mode 100644 index 0000000..8c6560d --- /dev/null +++ b/blueprints/arbitrum-orbit/dist/deploy-rollup.js @@ -0,0 +1,55 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const arbitrum_orbit_toolkit_1 = require("arbitrum-orbit-toolkit"); +const viem_1 = require("viem"); +const accounts_1 = require("viem/accounts"); +function validateParams(params) { + if (!params || typeof params !== "object") { + throw new Error("Invalid params: must be an object"); + } + const requiredFields = [ + "ownerPrivateKey", + "chainId", + "validators", + "batchPosters", + "nativeToken", + "dataAvailabilityCommittee", + ]; + for (const field of requiredFields) { + if (!(field in params)) { + throw new Error(`Missing required field: ${field}`); + } + } +} +async function main() { + const params = JSON.parse(process.argv[2]); + validateParams(params); + const parentChainClient = (0, viem_1.createPublicClient)({ + transport: (0, viem_1.http)(process.env.PARENT_CHAIN_RPC), + }); + const account = (0, accounts_1.privateKeyToAccount)(params.ownerPrivateKey); + // Prepare complete rollup parameters + const rollupParams = { + chainId: params.chainId, + owner: account, + validators: params.validators, + batchPosters: params.batchPosters, + nativeToken: params.nativeToken, + dataAvailabilityCommittee: params.dataAvailabilityCommittee, + }; + try { + const result = await (0, arbitrum_orbit_toolkit_1.createRollup)(rollupParams, parentChainClient); + console.log(JSON.stringify({ + rollupAddress: result.rollupAddress, + inboxAddress: result.inboxAddress, + adminAddress: result.adminAddress, + sequencerInboxAddress: result.sequencerInboxAddress, + transactionHash: result.transactionHash, + })); + } + catch (error) { + console.error(error); + process.exit(1); + } +} +main().catch(console.error); diff --git a/blueprints/arbitrum-orbit/dist/manage-batch-posters.d.ts b/blueprints/arbitrum-orbit/dist/manage-batch-posters.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/blueprints/arbitrum-orbit/dist/manage-batch-posters.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/blueprints/arbitrum-orbit/scripts/manage-batch-posters.ts b/blueprints/arbitrum-orbit/dist/manage-batch-posters.js similarity index 57% rename from blueprints/arbitrum-orbit/scripts/manage-batch-posters.ts rename to blueprints/arbitrum-orbit/dist/manage-batch-posters.js index fa9e94a..94a20df 100644 --- a/blueprints/arbitrum-orbit/scripts/manage-batch-posters.ts +++ b/blueprints/arbitrum-orbit/dist/manage-batch-posters.js @@ -1,14 +1,14 @@ -import { setBatchPosters } from 'arbitrum-orbit-toolkit'; -import { createPublicClient, http } from 'viem'; - +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const arbitrum_orbit_toolkit_1 = require("arbitrum-orbit-toolkit"); +const viem_1 = require("viem"); async function main() { const params = JSON.parse(process.argv[2]); - const parentChainClient = createPublicClient({ - transport: http(process.env.PARENT_CHAIN_RPC) + const parentChainClient = (0, viem_1.createPublicClient)({ + transport: (0, viem_1.http)(process.env.PARENT_CHAIN_RPC) }); - try { - const result = await setBatchPosters({ + const result = await (0, arbitrum_orbit_toolkit_1.setBatchPosters)({ rollupAddress: params.rollup_address, batchPosters: params.batch_posters, isActive: params.is_active, @@ -18,12 +18,11 @@ async function main() { account: process.env.OWNER_PRIVATE_KEY } }, parentChainClient); - console.log(JSON.stringify({ transactionHash: result })); - } catch (error) { + } + catch (error) { console.error(error); process.exit(1); } } - -main().catch(console.error); \ No newline at end of file +main().catch(console.error); diff --git a/blueprints/arbitrum-orbit/dist/set-validators.d.ts b/blueprints/arbitrum-orbit/dist/set-validators.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/blueprints/arbitrum-orbit/dist/set-validators.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/blueprints/arbitrum-orbit/dist/set-validators.js b/blueprints/arbitrum-orbit/dist/set-validators.js new file mode 100644 index 0000000..d540d06 --- /dev/null +++ b/blueprints/arbitrum-orbit/dist/set-validators.js @@ -0,0 +1,46 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const arbitrum_orbit_toolkit_1 = require("arbitrum-orbit-toolkit"); +const viem_1 = require("viem"); +const accounts_1 = require("viem/accounts"); +function validateParams(params) { + if (!params || typeof params !== "object") { + throw new Error("Invalid params: must be an object"); + } + const requiredFields = [ + "parentChainRpc", + "ownerPrivateKey", + "upgradeExecutor", + "rollupAddress", + "validators", + "isActive", + ]; + for (const field of requiredFields) { + if (!(field in params)) { + throw new Error(`Missing required field: ${field}`); + } + } +} +async function main() { + const params = JSON.parse(process.argv[2]); + validateParams(params); + const parentChainClient = (0, viem_1.createPublicClient)({ + transport: (0, viem_1.http)(params.parentChainRpc), + }); + const account = (0, accounts_1.privateKeyToAccount)(params.ownerPrivateKey); + try { + const result = await (0, arbitrum_orbit_toolkit_1.setValidators)({ + rollupAddress: params.rollupAddress, + validators: params.validators, + isActive: params.isActive, + upgradeExecutor: process.env.UPGRADE_EXECUTOR_ADDRESS, + owner: account, + }, parentChainClient); + console.log(JSON.stringify({ transactionHash: result })); + } + catch (error) { + console.error(error); + process.exit(1); + } +} +main().catch(console.error); diff --git a/blueprints/arbitrum-orbit/scripts/add-executors.ts b/blueprints/arbitrum-orbit/scripts/add-executors.ts index 4782333..b8c5126 100644 --- a/blueprints/arbitrum-orbit/scripts/add-executors.ts +++ b/blueprints/arbitrum-orbit/scripts/add-executors.ts @@ -1,28 +1,88 @@ -import { addPrivilegedExecutors } from 'arbitrum-orbit-toolkit'; -import { createPublicClient, http } from 'viem'; +import { + ExecutorConfig, + addPrivilegedExecutors, + createOrbitChainClient, +} from "arbitrum-orbit-toolkit"; +import { createPublicClient, http } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; -async function main() { - const params = JSON.parse(process.argv[2]); - const parentChainClient = createPublicClient({ - transport: http(process.env.PARENT_CHAIN_RPC) - }); - - try { - const result = await addPrivilegedExecutors({ - rollupAddress: params.rollup_address, - newExecutors: params.new_executors, - upgradeExecutor: process.env.UPGRADE_EXECUTOR_ADDRESS, - owner: { - address: process.env.OWNER_ADDRESS, - account: process.env.OWNER_PRIVATE_KEY - } - }, parentChainClient); - - console.log(JSON.stringify({ transactionHash: result })); - } catch (error) { - console.error(error); - process.exit(1); +interface ScriptParams extends Omit { + parentChainRpc: string; + orbitChainRpc: string; + chainId: number; + chainName: string; + chainNetworkName: string; + currencyName: string; + currencySymbol: string; + currencyDecimals: number; + ownerPrivateKey: `0x${string}`; +} + +function validateParams(params: unknown): asserts params is ScriptParams { + if (!params || typeof params !== "object") { + throw new Error("Invalid params: must be an object"); + } + + const requiredFields = [ + "parentChainRpc", + "orbitChainRpc", + "chainId", + "chainName", + "chainNetworkName", + "nativeCurrency", + "ownerPrivateKey", + "rollupAddress", + "upgradeExecutor", + "newExecutors", + ]; + + for (const field of requiredFields) { + if (!(field in params)) { + throw new Error(`Missing required field: ${field}`); } + } +} + +async function main() { + const params: ScriptParams = JSON.parse(process.argv[2]); + validateParams(params); + + const parentChainClient = createPublicClient({ + transport: http(params.parentChainRpc), + }); + + const orbitChainClient = createOrbitChainClient( + params.chainId, + params.chainName, + params.chainNetworkName, + { + name: params.currencyName, + symbol: params.currencySymbol, + decimals: params.currencyDecimals, + }, + params.orbitChainRpc, + params.rollupAddress, + ); + + let account = privateKeyToAccount(params.ownerPrivateKey); + + try { + const result = await addPrivilegedExecutors( + { + rollupAddress: params.rollupAddress, + newExecutors: params.newExecutors, + upgradeExecutor: params.upgradeExecutor, + owner: account, + }, + parentChainClient, + orbitChainClient, + ); + + console.log(JSON.stringify({ transactionHash: result })); + } catch (error) { + console.error(error); + process.exit(1); + } } -main().catch(console.error); \ No newline at end of file +main().catch(console.error); diff --git a/blueprints/arbitrum-orbit/scripts/configure-fast-withdrawals.ts b/blueprints/arbitrum-orbit/scripts/configure-fast-withdrawals.ts index 7683cc5..cbf0477 100644 --- a/blueprints/arbitrum-orbit/scripts/configure-fast-withdrawals.ts +++ b/blueprints/arbitrum-orbit/scripts/configure-fast-withdrawals.ts @@ -1,29 +1,64 @@ -import { setupFastWithdrawal } from 'arbitrum-orbit-toolkit'; -import { createPublicClient, http } from 'viem'; +import { + FastWithdrawalConfig, + setupFastWithdrawal, +} from "arbitrum-orbit-toolkit"; +import { createPublicClient, http } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; -async function main() { - const params = JSON.parse(process.argv[2]); - const parentChainClient = createPublicClient({ - transport: http(process.env.PARENT_CHAIN_RPC) - }); - - try { - const result = await setupFastWithdrawal({ - rollupAddress: params.rollup_address, - confirmers: params.confirmers, - isActive: params.is_active, - upgradeExecutor: process.env.UPGRADE_EXECUTOR_ADDRESS, - owner: { - address: process.env.OWNER_ADDRESS, - account: process.env.OWNER_PRIVATE_KEY - } - }, parentChainClient); - - console.log(JSON.stringify({ transactionHash: result })); - } catch (error) { - console.error(error); - process.exit(1); +interface ScriptParams extends Omit { + parentChainRpc: string; + ownerPrivateKey: `0x${string}`; +} + +function validateParams(params: unknown): asserts params is ScriptParams { + if (!params || typeof params !== "object") { + throw new Error("Invalid params: must be an object"); + } + + const requiredFields = [ + "parentChainRpc", + "ownerPrivateKey", + "ownerAddress", + "rollupAddress", + "upgradeExecutor", + "minimumAssertionPeriod", + "fastConfirmer", + ]; + + for (const field of requiredFields) { + if (!(field in params)) { + throw new Error(`Missing required field: ${field}`); } + } +} + +async function main() { + const params: ScriptParams = JSON.parse(process.argv[2]); + validateParams(params); + + const parentChainClient = createPublicClient({ + transport: http(params.parentChainRpc), + }); + + const account = privateKeyToAccount(params.ownerPrivateKey); + + try { + const result = await setupFastWithdrawal( + { + rollupAddress: params.rollupAddress, + owner: account, + upgradeExecutor: params.upgradeExecutor, + minimumAssertionPeriod: params.minimumAssertionPeriod, + fastConfirmer: params.fastConfirmer, + }, + parentChainClient, + ); + + console.log(JSON.stringify(result)); + } catch (error) { + console.error(error); + process.exit(1); + } } -main().catch(console.error); \ No newline at end of file +main().catch(console.error); diff --git a/blueprints/arbitrum-orbit/scripts/configure-token-bridge.ts b/blueprints/arbitrum-orbit/scripts/configure-token-bridge.ts index 812d3eb..ad36131 100644 --- a/blueprints/arbitrum-orbit/scripts/configure-token-bridge.ts +++ b/blueprints/arbitrum-orbit/scripts/configure-token-bridge.ts @@ -1,25 +1,87 @@ -import { createTokenBridge } from 'arbitrum-orbit-toolkit'; -import { createPublicClient, http } from 'viem'; +import { + CreateTokenBridgeParams, + createOrbitChainClient, + createTokenBridge, +} from "arbitrum-orbit-toolkit"; +import { createPublicClient, http } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; -async function main() { - const params = JSON.parse(process.argv[2]); - const parentChainClient = createPublicClient({ - transport: http(process.env.PARENT_CHAIN_RPC) - }); - - try { - const result = await createTokenBridge({ - rollupAddress: params.rollup_address, - nativeToken: params.native_token, - owner: params.owner, - upgradeExecutor: process.env.UPGRADE_EXECUTOR_ADDRESS - }, parentChainClient); - - console.log(JSON.stringify({ transactionHash: result })); - } catch (error) { - console.error(error); - process.exit(1); +interface ScriptParams extends Omit { + orbitChainId: number; + parentChainRpc: string; + orbitChainRpc: string; + chainName: string; + chainNetworkName: string; + currencyName: string; + currencySymbol: string; + currencyDecimals: number; + ownerPrivateKey: `0x${string}`; +} + +function validateParams(params: unknown): asserts params is ScriptParams { + if (!params || typeof params !== "object") { + throw new Error("Invalid params: must be an object"); + } + + const requiredFields = [ + "parentChainRpc", + "orbitChainRpc", + "chainName", + "chainNetworkName", + "currencyName", + "currencySymbol", + "currencyDecimals", + "ownerPrivateKey", + "rollupAddress", + "nativeToken", + ]; + + for (const field of requiredFields) { + if (!(field in params)) { + throw new Error(`Missing required field: ${field}`); } + } +} + +async function main() { + const params: ScriptParams = JSON.parse(process.argv[2]); + validateParams(params); + + const parentChainClient = createPublicClient({ + transport: http(params.parentChainRpc), + }); + + const orbitChainClient = createOrbitChainClient( + params.orbitChainId, + params.chainName, + params.chainNetworkName, + { + name: params.currencyName, + symbol: params.currencySymbol, + decimals: params.currencyDecimals, + }, + params.orbitChainRpc, + params.rollupAddress, + ); + + const account = privateKeyToAccount(params.ownerPrivateKey); + + try { + const result = await createTokenBridge( + { + rollupAddress: params.rollupAddress, + nativeToken: params.nativeToken, + owner: account, + }, + parentChainClient, + orbitChainClient, + ); + + console.log(JSON.stringify(result)); + } catch (error) { + console.error(error); + process.exit(1); + } } -main().catch(console.error); \ No newline at end of file +main().catch(console.error); diff --git a/blueprints/arbitrum-orbit/scripts/deploy-rollup.ts b/blueprints/arbitrum-orbit/scripts/deploy-rollup.ts index cfca36c..23418a3 100644 --- a/blueprints/arbitrum-orbit/scripts/deploy-rollup.ts +++ b/blueprints/arbitrum-orbit/scripts/deploy-rollup.ts @@ -1,25 +1,68 @@ -import { createRollup, CreateRollupParams } from 'arbitrum-orbit-toolkit'; -import { createPublicClient, http } from 'viem'; +import { createRollup } from "arbitrum-orbit-toolkit"; +import { CreateRollupParams } from "arbitrum-orbit-toolkit/src/rollup/create"; +import { Chain, createPublicClient, http, PublicClient } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; -async function main() { - const config: CreateRollupParams = JSON.parse(process.argv[2]); - const parentChainClient = createPublicClient({ - transport: http(process.env.PARENT_CHAIN_RPC) - }); - - try { - const result = await createRollup(config, parentChainClient); - console.log(JSON.stringify({ - rollupAddress: result.rollupAddress, - inboxAddress: result.inboxAddress, - adminAddress: result.adminAddress, - sequencerInboxAddress: result.sequencerInboxAddress, - transactionHash: result.transactionHash - })); - } catch (error) { - console.error(error); - process.exit(1); +interface ScriptParams extends Omit { + ownerPrivateKey: `0x${string}`; +} + +function validateParams(params: unknown): asserts params is ScriptParams { + if (!params || typeof params !== "object") { + throw new Error("Invalid params: must be an object"); + } + + const requiredFields = [ + "ownerPrivateKey", + "chainId", + "validators", + "batchPosters", + "nativeToken", + "dataAvailabilityCommittee", + ]; + + for (const field of requiredFields) { + if (!(field in params)) { + throw new Error(`Missing required field: ${field}`); } + } +} + +async function main() { + const params: ScriptParams = JSON.parse(process.argv[2]); + validateParams(params); + + const parentChainClient: PublicClient = createPublicClient({ + transport: http(process.env.PARENT_CHAIN_RPC), + }); + + const account = privateKeyToAccount(params.ownerPrivateKey); + + // Prepare complete rollup parameters + const rollupParams: CreateRollupParams = { + chainId: params.chainId, + owner: account, + validators: params.validators, + batchPosters: params.batchPosters, + nativeToken: params.nativeToken, + dataAvailabilityCommittee: params.dataAvailabilityCommittee, + }; + + try { + const result = await createRollup(rollupParams, parentChainClient); + console.log( + JSON.stringify({ + rollupAddress: result.rollupAddress, + inboxAddress: result.inboxAddress, + adminAddress: result.adminAddress, + sequencerInboxAddress: result.sequencerInboxAddress, + transactionHash: result.transactionHash, + }), + ); + } catch (error) { + console.error(error); + process.exit(1); + } } -main().catch(console.error); \ No newline at end of file +main().catch(console.error); diff --git a/blueprints/arbitrum-orbit/scripts/set-validators.ts b/blueprints/arbitrum-orbit/scripts/set-validators.ts index 9c51d6e..d37e653 100644 --- a/blueprints/arbitrum-orbit/scripts/set-validators.ts +++ b/blueprints/arbitrum-orbit/scripts/set-validators.ts @@ -1,29 +1,60 @@ -import { setValidators } from 'arbitrum-orbit-toolkit'; -import { createPublicClient, http } from 'viem'; +import { setValidators, SetValidatorsParams } from "arbitrum-orbit-toolkit"; +import { Chain, createPublicClient, http, PublicClient } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; -async function main() { - const params = JSON.parse(process.argv[2]); - const parentChainClient = createPublicClient({ - transport: http(process.env.PARENT_CHAIN_RPC) - }); - - try { - const result = await setValidators({ - rollupAddress: params.rollup_address, - validators: params.validators, - isActive: params.is_active, - upgradeExecutor: process.env.UPGRADE_EXECUTOR_ADDRESS, - owner: { - address: process.env.OWNER_ADDRESS, - account: process.env.OWNER_PRIVATE_KEY - } - }, parentChainClient); - - console.log(JSON.stringify({ transactionHash: result })); - } catch (error) { - console.error(error); - process.exit(1); +interface ScriptParams extends Omit { + parentChainRpc: string; + ownerPrivateKey: `0x${string}`; +} + +function validateParams(params: unknown): asserts params is ScriptParams { + if (!params || typeof params !== "object") { + throw new Error("Invalid params: must be an object"); + } + + const requiredFields = [ + "parentChainRpc", + "ownerPrivateKey", + "upgradeExecutor", + "rollupAddress", + "validators", + "isActive", + ]; + + for (const field of requiredFields) { + if (!(field in params)) { + throw new Error(`Missing required field: ${field}`); } + } +} + +async function main() { + const params: ScriptParams = JSON.parse(process.argv[2]); + validateParams(params); + + const parentChainClient: PublicClient = createPublicClient({ + transport: http(params.parentChainRpc), + }); + + const account = privateKeyToAccount(params.ownerPrivateKey); + + try { + const result = await setValidators( + { + rollupAddress: params.rollupAddress, + validators: params.validators, + isActive: params.isActive, + upgradeExecutor: process.env.UPGRADE_EXECUTOR_ADDRESS as `0x${string}`, + owner: account, + }, + parentChainClient, + ); + + console.log(JSON.stringify({ transactionHash: result })); + } catch (error) { + console.error(error); + process.exit(1); + } } -main().catch(console.error); \ No newline at end of file +main().catch(console.error); diff --git a/blueprints/arbitrum-orbit/src/jobs/mod.rs b/blueprints/arbitrum-orbit/src/jobs/mod.rs index fb6c1cb..a18b559 100644 --- a/blueprints/arbitrum-orbit/src/jobs/mod.rs +++ b/blueprints/arbitrum-orbit/src/jobs/mod.rs @@ -43,14 +43,6 @@ pub struct FastWithdrawalParams { pub is_active: bool, } -// Parameters for batch poster management -#[derive(Serialize, Deserialize)] -pub struct BatchPosterParams { - pub rollup_address: Address, - pub batch_posters: Vec
, - pub is_active: bool, -} - // Parameters for fee recipient configuration #[derive(Serialize, Deserialize)] pub struct FeeRecipientParams { @@ -62,13 +54,13 @@ pub struct FeeRecipientParams { macro_rules! create_job { ($id:expr, $name:ident, $params_type:ty) => { #[sdk::job( - id = $id, - params(params_bytes), - event_listener( - listener = TangleEventListener::, - pre_processor = services_pre_processor, - ), - )] + id = $id, + params(params_bytes), + event_listener( + listener = TangleEventListener::, + pre_processor = services_pre_processor, + ), + )] pub fn $name(params_bytes: Vec, context: ServiceContext) -> Result { let params: $params_type = serde_json::from_slice(¶ms_bytes).expect(&format!( "Failed to deserialize {} params", @@ -98,8 +90,5 @@ create_job!(2, add_executors, ExecutorParams); // Job to configure fast withdrawals create_job!(3, configure_fast_withdrawals, FastWithdrawalParams); -// Job to manage batch posters -create_job!(4, manage_batch_posters, BatchPosterParams); - // Job to configure fee recipients -create_job!(5, configure_fee_recipients, FeeRecipientParams); +create_job!(4, configure_fee_recipients, FeeRecipientParams); diff --git a/blueprints/arbitrum-orbit/src/lib.rs b/blueprints/arbitrum-orbit/src/lib.rs index a38990c..d0670fd 100644 --- a/blueprints/arbitrum-orbit/src/lib.rs +++ b/blueprints/arbitrum-orbit/src/lib.rs @@ -4,11 +4,9 @@ use alloy_primitives::Address; use alloy_sol_types::sol; use color_eyre::eyre::Result; use gadget_sdk::load_abi; -use jobs::{ - manage_batch_posters, set_validators, BatchPosterParams, ServiceContext, TokenBridgeParams, - ValidatorParams, -}; +use jobs::{set_validators, ServiceContext, TokenBridgeParams, ValidatorParams}; use serde::{Deserialize, Serialize}; +use serde_json::json; pub mod jobs; @@ -26,7 +24,7 @@ load_abi!( ); #[derive(Serialize, Deserialize)] -pub struct DeploymentResult { +pub struct OrbitDeploymentResult { pub rollup_address: Address, pub inbox_address: Address, pub admin_address: Address, @@ -35,7 +33,8 @@ pub struct DeploymentResult { } #[derive(Clone, Debug, Serialize, Deserialize)] -pub struct RollupConfig { +pub struct OrbitRollupConfig { + pub parent_chain_id: u64, pub chain_id: u64, pub owner: Address, pub validators: Vec
, @@ -48,11 +47,25 @@ pub struct RollupConfig { pub native_token_is_erc20: bool, } -pub async fn deploy_rollup(config: RollupConfig) -> Result { - let config_json = serde_json::to_string(&config)?; +pub async fn deploy_rollup(config: OrbitRollupConfig) -> Result { + let params = json!({ + "chainId": config.chain_id, + "owner": { + "address": config.owner, + "account": std::env::var("OWNER_PRIVATE_KEY")? + }, + "validators": config.validators, + "batchPosters": config.batch_posters, + "nativeToken": config.native_token, + "dataAvailabilityCommittee": config.data_availability_committee, + "isCustomFeeToken": config.is_custom_fee_token, + "customFeeToken": config.custom_fee_token, + "nativeTokenIsERC20": config.native_token_is_erc20 + }); + let output = Command::new("node") .arg("scripts/deploy-rollup.ts") - .arg(config_json) + .arg(params.to_string()) .output()?; if !output.status.success() { @@ -62,13 +75,13 @@ pub async fn deploy_rollup(config: RollupConfig) -> Result { )); } - let result: DeploymentResult = serde_json::from_str(&String::from_utf8(output.stdout)?)?; + let result: OrbitDeploymentResult = serde_json::from_str(&String::from_utf8(output.stdout)?)?; Ok(result) } pub async fn setup_initial_configuration( - deployment: &DeploymentResult, - config: &RollupConfig, + deployment: &OrbitDeploymentResult, + config: &OrbitRollupConfig, context: &ServiceContext, ) -> Result<()> { // Configure token bridge if requested (one-time setup) @@ -93,15 +106,6 @@ pub async fn setup_initial_configuration( } } - // Set initial batch posters - let batch_poster_params = BatchPosterParams { - rollup_address: deployment.rollup_address, - batch_posters: config.batch_posters.clone(), - is_active: true, - }; - let batch_poster_bytes = serde_json::to_vec(&batch_poster_params)?; - manage_batch_posters(batch_poster_bytes, context.clone())?; - // Set initial validators let validator_params = ValidatorParams { rollup_address: deployment.rollup_address, diff --git a/blueprints/arbitrum-orbit/src/main.rs b/blueprints/arbitrum-orbit/src/main.rs index 97e1a1f..eef01c7 100644 --- a/blueprints/arbitrum-orbit/src/main.rs +++ b/blueprints/arbitrum-orbit/src/main.rs @@ -3,10 +3,9 @@ use arbitrum_orbit_blueprint::{ deploy_rollup, jobs::{ AddExecutorsEventHandler, ConfigureFastWithdrawalsEventHandler, - ConfigureFeeRecipientsEventHandler, ManageBatchPostersEventHandler, ServiceContext, - SetValidatorsEventHandler, + ConfigureFeeRecipientsEventHandler, ServiceContext, SetValidatorsEventHandler, }, - setup_initial_configuration, OrbitRaaSBlueprint, RollupConfig, + setup_initial_configuration, OrbitRaaSBlueprint, OrbitRollupConfig, }; use color_eyre::Result; use gadget_sdk::{self as sdk, utils::evm::get_provider_http}; @@ -15,13 +14,18 @@ use sdk::runners::BlueprintRunner; #[sdk::main(env)] async fn main() -> Result<()> { + let context = ServiceContext { + config: env.clone(), + }; + let service_id = env.service_id().unwrap(); let provider = get_provider_http(&env.http_rpc_endpoint); let blueprint_address = Address::from([0; 20]); let contract = OrbitRaaSBlueprint::new(blueprint_address, provider); let rollup_config_return = contract.getRollupConfig(service_id).call().await?; - let rollup_config = RollupConfig { + let rollup_config = OrbitRollupConfig { + parent_chain_id: rollup_config_return.chainId, chain_id: rollup_config_return.chainId, owner: rollup_config_return.owner, validators: rollup_config_return.validators, @@ -47,10 +51,6 @@ async fn main() -> Result<()> { let deployment_result = deploy_rollup(rollup_config.clone()).await?; gadget_sdk::info!("Rollup deployed at: {}", deployment_result.rollup_address); - let context = ServiceContext { - config: env.clone(), - }; - // Setup initial configuration setup_initial_configuration(&deployment_result, &rollup_config, &context).await?; gadget_sdk::info!("Initial configuration completed"); @@ -60,7 +60,6 @@ async fn main() -> Result<()> { let add_executors = AddExecutorsEventHandler::new(&env, context.clone()).await?; let configure_fast_withdrawals = ConfigureFastWithdrawalsEventHandler::new(&env, context.clone()).await?; - let manage_batch_posters = ManageBatchPostersEventHandler::new(&env, context.clone()).await?; let configure_fee_recipients = ConfigureFeeRecipientsEventHandler::new(&env, context).await?; // Start the event watcher @@ -69,7 +68,6 @@ async fn main() -> Result<()> { .job(set_validators) .job(add_executors) .job(configure_fast_withdrawals) - .job(manage_batch_posters) .job(configure_fee_recipients) .run() .await?; diff --git a/blueprints/arbitrum-orbit/tsconfig.json b/blueprints/arbitrum-orbit/tsconfig.json index 2fcf6cc..ad209e2 100644 --- a/blueprints/arbitrum-orbit/tsconfig.json +++ b/blueprints/arbitrum-orbit/tsconfig.json @@ -1,10 +1,10 @@ { - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "./dist", - "rootDir": "./scripts", - "baseUrl": "." - }, - "include": ["scripts/**/*"], - "exclude": ["node_modules", "dist"] - } \ No newline at end of file + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": "./scripts", + "baseUrl": "." + }, + "include": ["scripts/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/blueprints/arbitrum-orbit/tsconfig.tsbuildinfo b/blueprints/arbitrum-orbit/tsconfig.tsbuildinfo new file mode 100644 index 0000000..109ae05 --- /dev/null +++ b/blueprints/arbitrum-orbit/tsconfig.tsbuildinfo @@ -0,0 +1 @@ +{"root":["./scripts/add-executors.ts","./scripts/configure-fast-withdrawals.ts","./scripts/configure-token-bridge.ts","./scripts/deploy-rollup.ts","./scripts/set-validators.ts"],"version":"5.6.3"} \ No newline at end of file diff --git a/package.json b/package.json index b6f2fff..be8a0dd 100644 --- a/package.json +++ b/package.json @@ -7,12 +7,14 @@ "packages/*" ], "scripts": { - "build": "yarn workspaces run build", + "build": "yarn workspace arbitrum-orbit-blueprint build", "type-check": "yarn workspaces run type-check", - "dev": "yarn workspaces run dev" + "dev": "yarn workspaces run dev", + "format": "prettier --write \"**/*.{ts,tsx,json}\"" }, "devDependencies": { "@types/node": "^20.11.5", + "prettier": "^3.2.5", "typescript": "^5.3.3" } } diff --git a/packages/arbitrum-orbit-toolkit/package.json b/packages/arbitrum-orbit-toolkit/package.json index 187d9bd..1c25952 100644 --- a/packages/arbitrum-orbit-toolkit/package.json +++ b/packages/arbitrum-orbit-toolkit/package.json @@ -9,6 +9,8 @@ "type": "git", "url": "https://github.com/tangle-network/raas-blueprints" }, + "main": "src/index.ts", + "types": "src/index.ts", "keywords": [ "tangle", "blueprint", @@ -24,5 +26,9 @@ "dependencies": { "@arbitrum/orbit-sdk": "^0.21.2", "viem": "^2.21.47" + }, + "devDependencies": { + "@types/node": "^20.11.5", + "typescript": "^5.3.3" } } diff --git a/packages/arbitrum-orbit-toolkit/src/bridge/fast.ts b/packages/arbitrum-orbit-toolkit/src/bridge/fast.ts index 8e03174..406299f 100644 --- a/packages/arbitrum-orbit-toolkit/src/bridge/fast.ts +++ b/packages/arbitrum-orbit-toolkit/src/bridge/fast.ts @@ -1,17 +1,20 @@ -import { Address, PublicClient, Hash, TransactionRequest, PrivateKeyAccount } from 'viem'; +import { + Address, + PublicClient, + Hash, + TransactionRequest, + PrivateKeyAccount, +} from "viem"; import { createRollupPrepareTransactionReceipt, setAnyTrustFastConfirmerPrepareTransactionRequest, rollupAdminLogicPublicActions, -} from '@arbitrum/orbit-sdk'; -import { getTimeDelayFromBlocks } from '../utils/helpers'; +} from "@arbitrum/orbit-sdk"; +import { getTimeDelayFromBlocks } from "../utils/helpers"; export interface FastWithdrawalConfig { rollupAddress: Address; - owner: { - address: Address; - account: PrivateKeyAccount; - }; + owner: PrivateKeyAccount; upgradeExecutor: Address; minimumAssertionPeriod: bigint; fastConfirmer: Address; @@ -34,27 +37,29 @@ export interface FastWithdrawalSetupResult { */ export async function setupFastWithdrawal( config: FastWithdrawalConfig, - parentChainClient: PublicClient + parentChainClient: PublicClient, ): Promise { const client = parentChainClient.extend( rollupAdminLogicPublicActions({ rollup: config.rollupAddress, - }) + }), ); // Get current minimum assertion period - const currentMinimumAssertionPeriod = await client.rollupAdminLogicReadContract({ - functionName: 'minimumAssertionPeriod', - }) as bigint; + const currentMinimumAssertionPeriod = + (await client.rollupAdminLogicReadContract({ + functionName: "minimumAssertionPeriod", + })) as bigint; // Set minimum assertion period if needed if (currentMinimumAssertionPeriod !== config.minimumAssertionPeriod) { - const setMinimumPeriodRequest = await client.rollupAdminLogicPrepareTransactionRequest({ - functionName: 'setMinimumAssertionPeriod', - args: [config.minimumAssertionPeriod], - upgradeExecutor: config.upgradeExecutor, - account: config.owner.address, - }) as TransactionRequest; + const setMinimumPeriodRequest = + (await client.rollupAdminLogicPrepareTransactionRequest({ + functionName: "setMinimumAssertionPeriod", + args: [config.minimumAssertionPeriod], + upgradeExecutor: config.upgradeExecutor, + account: config.owner.address, + })) as TransactionRequest; const txHash = await parentChainClient.sendRawTransaction({ serializedTransaction: setMinimumPeriodRequest as `0x${string}`, @@ -63,30 +68,33 @@ export async function setupFastWithdrawal( } // Set fast confirmer configuration - const fastConfirmerRequest = await setAnyTrustFastConfirmerPrepareTransactionRequest({ - publicClient: parentChainClient, - rollup: config.rollupAddress, - fastConfirmer: config.fastConfirmer, - account: config.owner.account, - upgradeExecutor: config.upgradeExecutor, - }) as TransactionRequest; + const fastConfirmerRequest = + (await setAnyTrustFastConfirmerPrepareTransactionRequest({ + publicClient: parentChainClient, + rollup: config.rollupAddress, + fastConfirmer: config.fastConfirmer, + account: config.owner, + upgradeExecutor: config.upgradeExecutor, + })) as TransactionRequest; const fastConfirmerTxHash = await parentChainClient.sendRawTransaction({ serializedTransaction: fastConfirmerRequest as `0x${string}`, }); const receipt = createRollupPrepareTransactionReceipt( - await parentChainClient.waitForTransactionReceipt({ hash: fastConfirmerTxHash }) + await parentChainClient.waitForTransactionReceipt({ + hash: fastConfirmerTxHash, + }), ); if (!parentChainClient.chain) { - throw new Error('Parent chain client must have a chain configured'); + throw new Error("Parent chain client must have a chain configured"); } // Calculate time delay for node configurations const timeDelay = getTimeDelayFromBlocks( parentChainClient.chain.id, - config.minimumAssertionPeriod + config.minimumAssertionPeriod, ); return { @@ -105,18 +113,18 @@ export async function setupFastWithdrawal( export async function isFastConfirmer( rollupAddress: Address, confirmerAddress: Address, - parentChainClient: PublicClient + parentChainClient: PublicClient, ): Promise { const client = parentChainClient.extend( rollupAdminLogicPublicActions({ rollup: rollupAddress, - }) + }), ); - const result = await client.rollupAdminLogicReadContract({ - functionName: 'isFastConfirmer', + const result = (await client.rollupAdminLogicReadContract({ + functionName: "isFastConfirmer", args: [confirmerAddress], - }) as boolean; + })) as boolean; return result; -} \ No newline at end of file +} diff --git a/packages/arbitrum-orbit-toolkit/src/bridge/token.ts b/packages/arbitrum-orbit-toolkit/src/bridge/token.ts index 89b983d..c58f5c8 100644 --- a/packages/arbitrum-orbit-toolkit/src/bridge/token.ts +++ b/packages/arbitrum-orbit-toolkit/src/bridge/token.ts @@ -1,4 +1,4 @@ -import { Address, PublicClient, PrivateKeyAccount } from 'viem'; +import { Address, PublicClient, PrivateKeyAccount } from "viem"; import { createTokenBridgeEnoughCustomFeeTokenAllowance, createTokenBridgePrepareCustomFeeTokenApprovalTransactionRequest, @@ -6,15 +6,12 @@ import { createTokenBridgePrepareTransactionReceipt, createTokenBridgePrepareSetWethGatewayTransactionRequest, createTokenBridgePrepareSetWethGatewayTransactionReceipt, -} from '@arbitrum/orbit-sdk'; -import type { TokenBridgeContracts } from '../core/types'; +} from "@arbitrum/orbit-sdk"; +import type { TokenBridgeContracts } from "../core/types"; export interface CreateTokenBridgeParams { rollupAddress: Address; - owner: { - address: Address; - account: PrivateKeyAccount; - }; + owner: PrivateKeyAccount; nativeToken?: Address; retryableGasOverrides?: { gasLimit?: { @@ -35,7 +32,7 @@ export interface CreateTokenBridgeResult { export async function createTokenBridge( params: CreateTokenBridgeParams, parentChainClient: PublicClient, - orbitChainClient: PublicClient + orbitChainClient: PublicClient, ): Promise { // Handle custom fee token if specified if (params.nativeToken) { @@ -45,17 +42,23 @@ export async function createTokenBridge( publicClient: parentChainClient, }; - if (!(await createTokenBridgeEnoughCustomFeeTokenAllowance(allowanceParams))) { - const approvalRequest = await createTokenBridgePrepareCustomFeeTokenApprovalTransactionRequest( - allowanceParams - ); + if ( + !(await createTokenBridgeEnoughCustomFeeTokenAllowance(allowanceParams)) + ) { + const approvalRequest = + await createTokenBridgePrepareCustomFeeTokenApprovalTransactionRequest( + allowanceParams, + ); - const approvalSerialized = await params.owner.account.signTransaction(approvalRequest); + const approvalSerialized = + await params.owner.signTransaction(approvalRequest); const approvalTxHash = await parentChainClient.sendRawTransaction({ serializedTransaction: approvalSerialized, }); - await parentChainClient.waitForTransactionReceipt({ hash: approvalTxHash }); + await parentChainClient.waitForTransactionReceipt({ + hash: approvalTxHash, + }); } } @@ -70,13 +73,13 @@ export async function createTokenBridge( account: params.owner.address, }); - const txSerialized = await params.owner.account.signTransaction(txRequest); + const txSerialized = await params.owner.signTransaction(txRequest); const txHash = await parentChainClient.sendRawTransaction({ serializedTransaction: txSerialized, }); const receipt = createTokenBridgePrepareTransactionReceipt( - await parentChainClient.waitForTransactionReceipt({ hash: txHash }) + await parentChainClient.waitForTransactionReceipt({ hash: txHash }), ); // Wait for retryables to execute @@ -86,22 +89,24 @@ export async function createTokenBridge( // Set WETH gateway if using ETH as fee token if (!params.nativeToken) { - const wethRequest = await createTokenBridgePrepareSetWethGatewayTransactionRequest({ - rollup: params.rollupAddress, - parentChainPublicClient: parentChainClient, - orbitChainPublicClient: orbitChainClient, - account: params.owner.address, - retryableGasOverrides: params.retryableGasOverrides, - }); + const wethRequest = + await createTokenBridgePrepareSetWethGatewayTransactionRequest({ + rollup: params.rollupAddress, + parentChainPublicClient: parentChainClient, + orbitChainPublicClient: orbitChainClient, + account: params.owner.address, + retryableGasOverrides: params.retryableGasOverrides, + }); - const wethSerialized = await params.owner.account.signTransaction(wethRequest); + const wethSerialized = await params.owner.signTransaction(wethRequest); const wethTxHash = await parentChainClient.sendRawTransaction({ serializedTransaction: wethSerialized, }); - const wethReceipt = createTokenBridgePrepareSetWethGatewayTransactionReceipt( - await parentChainClient.waitForTransactionReceipt({ hash: wethTxHash }) - ); + const wethReceipt = + createTokenBridgePrepareSetWethGatewayTransactionReceipt( + await parentChainClient.waitForTransactionReceipt({ hash: wethTxHash }), + ); const wethRetryableReceipts = await wethReceipt.waitForRetryables({ orbitPublicClient: orbitChainClient, @@ -117,6 +122,6 @@ export async function createTokenBridge( return { transactionHash: receipt.transactionHash, contracts, - retryableHashes: retryableReceipts.map(r => r.transactionHash), + retryableHashes: retryableReceipts.map((r) => r.transactionHash), }; -} \ No newline at end of file +} diff --git a/packages/arbitrum-orbit-toolkit/src/config/executor.ts b/packages/arbitrum-orbit-toolkit/src/config/executor.ts index ab45c82..2ffc558 100644 --- a/packages/arbitrum-orbit-toolkit/src/config/executor.ts +++ b/packages/arbitrum-orbit-toolkit/src/config/executor.ts @@ -1,17 +1,14 @@ -import { Address, PrivateKeyAccount, PublicClient } from 'viem'; +import { Address, PrivateKeyAccount, PublicClient } from "viem"; import { upgradeExecutorFetchPrivilegedAccounts, upgradeExecutorPrepareAddExecutorTransactionRequest, createTokenBridgeFetchTokenBridgeContracts, -} from '@arbitrum/orbit-sdk'; -import { sanitizeAddresses } from '../utils/helpers'; +} from "@arbitrum/orbit-sdk"; +import { sanitizeAddresses } from "../utils/helpers"; export interface ExecutorConfig { rollupAddress: Address; - owner: { - address: Address; - account: PrivateKeyAccount; - }; + owner: PrivateKeyAccount; upgradeExecutor: Address; newExecutors: Address[]; } @@ -25,13 +22,15 @@ export interface ExecutorSetupResult { export async function addPrivilegedExecutors( config: ExecutorConfig, parentChainClient: PublicClient, - orbitChainClient: PublicClient + orbitChainClient: PublicClient, ): Promise { // Get token bridge contracts to access upgrade executors - const tokenBridgeContracts = await createTokenBridgeFetchTokenBridgeContracts({ - inbox: config.rollupAddress, - parentChainPublicClient: parentChainClient, - }); + const tokenBridgeContracts = await createTokenBridgeFetchTokenBridgeContracts( + { + inbox: config.rollupAddress, + parentChainPublicClient: parentChainClient, + }, + ); // Store transaction hashes const parentChainTxHashes: string[] = []; @@ -40,33 +39,42 @@ export async function addPrivilegedExecutors( // Process each new executor for (const newExecutor of sanitizeAddresses(config.newExecutors)) { // Add executor on parent chain - const parentChainRequest = await upgradeExecutorPrepareAddExecutorTransactionRequest({ - account: newExecutor, - upgradeExecutorAddress: config.upgradeExecutor, - executorAccountAddress: config.owner.address, - publicClient: parentChainClient, - }); + const parentChainRequest = + await upgradeExecutorPrepareAddExecutorTransactionRequest({ + account: newExecutor, + upgradeExecutorAddress: config.upgradeExecutor, + executorAccountAddress: config.owner.address, + publicClient: parentChainClient, + }); - const parentChainSerialized = await config.owner.account.signTransaction(parentChainRequest); + const parentChainSerialized = + await config.owner.signTransaction(parentChainRequest); const parentChainTxHash = await parentChainClient.sendRawTransaction({ serializedTransaction: parentChainSerialized, }); - await parentChainClient.waitForTransactionReceipt({ hash: parentChainTxHash }); + await parentChainClient.waitForTransactionReceipt({ + hash: parentChainTxHash, + }); parentChainTxHashes.push(parentChainTxHash); // Add executor on orbit chain - const orbitChainRequest = await upgradeExecutorPrepareAddExecutorTransactionRequest({ - account: newExecutor, - upgradeExecutorAddress: tokenBridgeContracts.orbitChainContracts.upgradeExecutor, - executorAccountAddress: config.owner.address, - publicClient: orbitChainClient, - }); + const orbitChainRequest = + await upgradeExecutorPrepareAddExecutorTransactionRequest({ + account: newExecutor, + upgradeExecutorAddress: + tokenBridgeContracts.orbitChainContracts.upgradeExecutor, + executorAccountAddress: config.owner.address, + publicClient: orbitChainClient, + }); - const orbitChainSerialized = await config.owner.account.signTransaction(orbitChainRequest); + const orbitChainSerialized = + await config.owner.signTransaction(orbitChainRequest); const orbitChainTxHash = await orbitChainClient.sendRawTransaction({ serializedTransaction: orbitChainSerialized, }); - await orbitChainClient.waitForTransactionReceipt({ hash: orbitChainTxHash }); + await orbitChainClient.waitForTransactionReceipt({ + hash: orbitChainTxHash, + }); orbitChainTxHashes.push(orbitChainTxHash); } @@ -81,4 +89,4 @@ export async function addPrivilegedExecutors( orbitChainTxHashes, privilegedAccounts: Object.keys(privilegedAccounts) as Address[], }; -} \ No newline at end of file +} diff --git a/packages/arbitrum-orbit-toolkit/src/config/node.ts b/packages/arbitrum-orbit-toolkit/src/config/node.ts index 6b5cb1b..bf39175 100644 --- a/packages/arbitrum-orbit-toolkit/src/config/node.ts +++ b/packages/arbitrum-orbit-toolkit/src/config/node.ts @@ -1,13 +1,15 @@ -import { Address, Hash, PublicClient } from 'viem'; -import { writeFile } from 'fs/promises'; +import { Address, Hash, PublicClient } from "viem"; +import { writeFile } from "fs/promises"; import { ChainConfig, PrepareNodeConfigParams, createRollupPrepareTransaction, createRollupPrepareTransactionReceipt, prepareNodeConfig, -} from '@arbitrum/orbit-sdk'; -import { getParentChainLayer } from '@arbitrum/orbit-sdk/utils'; +} from "@arbitrum/orbit-sdk"; +import { getParentChainLayer } from "@arbitrum/orbit-sdk/utils"; +import { ParentChainId } from "@arbitrum/orbit-sdk"; +import { validateParentChain } from "@arbitrum/orbit-sdk/dist/types/ParentChain"; export interface NodeConfigParams { chainName: string; @@ -42,55 +44,62 @@ export interface NodeConfigResult { */ export async function prepareNodeConfiguration( params: NodeConfigParams, - parentChainClient: PublicClient + parentChainClient: PublicClient, ): Promise { // Get deployment transaction const tx = await createRollupPrepareTransaction( await parentChainClient.getTransaction({ hash: params.deploymentTxHash as Hash, - }) + }), ); // Get transaction receipt const txReceipt = createRollupPrepareTransactionReceipt( - await parentChainClient.waitForTransactionReceipt({ - hash: params.deploymentTxHash as Hash - }) + await parentChainClient.waitForTransactionReceipt({ + hash: params.deploymentTxHash as Hash, + }), ); // Get chain config from transaction inputs - const chainConfig: ChainConfig = JSON.parse(tx.getInputs()[0].config.chainConfig); - + const chainConfig: ChainConfig = JSON.parse( + tx.getInputs()[0].config.chainConfig, + ); + const coreContracts = { ...txReceipt.getCoreContracts(), - utils: '0x0' as Address, + utils: "0x0" as Address, deployedAt: Math.floor(Date.now() / 1000), }; // Prepare node config parameters + let parentChainId = validateParentChain(params.parentChainId) + .chainId as ParentChainId; const nodeConfigParameters: PrepareNodeConfigParams = { chainName: params.chainName, chainConfig, coreContracts, batchPosterPrivateKey: params.batchPosterPrivateKey, validatorPrivateKey: params.validatorPrivateKey, - parentChainId: params.parentChainId, + parentChainId: parentChainId, parentChainRpcUrl: params.parentChainRpcUrl, }; // Add beacon RPC URL for L2 Orbit chains settling to Ethereum - if (getParentChainLayer(params.parentChainId) === 1) { + if (getParentChainLayer(parentChainId) === 1) { if (!params.parentChainBeaconRpcUrl) { - throw new Error('Parent chain beacon RPC URL required for L2 Orbit chains'); + throw new Error( + "Parent chain beacon RPC URL required for L2 Orbit chains", + ); } - nodeConfigParameters.parentChainBeaconRpcUrl = params.parentChainBeaconRpcUrl; + nodeConfigParameters.parentChainBeaconRpcUrl = + params.parentChainBeaconRpcUrl; } // Generate node config const nodeConfig = prepareNodeConfig(nodeConfigParameters); // Write config to file - const outputPath = params.outputPath || 'node-config.json'; + const outputPath = params.outputPath || "node-config.json"; await writeFile(outputPath, JSON.stringify(nodeConfig, null, 2)); return { @@ -98,4 +107,4 @@ export async function prepareNodeConfiguration( coreContracts, configPath: outputPath, }; -} \ No newline at end of file +} diff --git a/packages/arbitrum-orbit-toolkit/src/core/clients.ts b/packages/arbitrum-orbit-toolkit/src/core/clients.ts index 6ea8267..3940226 100644 --- a/packages/arbitrum-orbit-toolkit/src/core/clients.ts +++ b/packages/arbitrum-orbit-toolkit/src/core/clients.ts @@ -1,18 +1,18 @@ -import { createPublicClient, http, Chain, PublicClient } from 'viem'; -import { arbitrumSepolia } from 'viem/chains'; -import { - arbOwnerPublicActions, +import { createPublicClient, http, Chain, PublicClient } from "viem"; +import { arbitrumSepolia } from "viem/chains"; +import { + arbOwnerPublicActions, arbGasInfoPublicActions, - rollupAdminLogicPublicActions -} from '@arbitrum/orbit-sdk'; -import type { ClientConfig } from './types'; + rollupAdminLogicPublicActions, +} from "@arbitrum/orbit-sdk"; +import type { ClientConfig } from "./types"; /** * Creates a public client for the parent chain with optional RPC URL */ export function createParentChainClient( chain: Chain = arbitrumSepolia, - rpcUrl?: string + rpcUrl?: string, ): PublicClient { return createPublicClient({ chain, @@ -25,22 +25,26 @@ export function createParentChainClient( */ export function createOrbitChainClient( chainId: number, + chainName: string, + chainNetworkName: string, + nativeCurrency: { name: string; symbol: string; decimals: number }, rpcUrl: string, - rollupAddress?: `0x${string}` + rollupAddress?: `0x${string}`, ): PublicClient { const client = createPublicClient({ chain: { id: chainId, - name: 'Orbit Chain', - network: 'orbit', - nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 }, + name: chainName, + network: chainNetworkName, + nativeCurrency, rpcUrls: { default: { http: [rpcUrl] }, public: { http: [rpcUrl] }, }, }, transport: http(), - }).extend(arbOwnerPublicActions) + }) + .extend(arbOwnerPublicActions) .extend(arbGasInfoPublicActions); // Add rollup admin actions if rollup address is provided @@ -48,7 +52,7 @@ export function createOrbitChainClient( return client.extend( rollupAdminLogicPublicActions({ rollup: rollupAddress, - }) + }), ); } @@ -61,15 +65,22 @@ export function createOrbitChainClient( export function createChainClients(config: ClientConfig) { const parentClient = createParentChainClient( config.parentChain, - config.parentChainRpc + config.parentChainRpc, ); - const orbitClient = config.orbitChainId && config.orbitChainRpc - ? createOrbitChainClient(config.orbitChainId, config.orbitChainRpc) - : undefined; + const orbitClient = + config.orbitChainId && config.orbitChainRpc + ? createOrbitChainClient( + config.orbitChainId, + config.orbitChainName, + config.orbitChainNetworkName, + config.orbitChainNativeCurrency, + config.orbitChainRpc, + ) + : undefined; return { parentChainClient: parentClient, orbitChainClient: orbitClient, }; -} \ No newline at end of file +} diff --git a/packages/arbitrum-orbit-toolkit/src/core/constants.ts b/packages/arbitrum-orbit-toolkit/src/core/constants.ts index fd05ff3..4a01a9a 100644 --- a/packages/arbitrum-orbit-toolkit/src/core/constants.ts +++ b/packages/arbitrum-orbit-toolkit/src/core/constants.ts @@ -1,5 +1,9 @@ -import { Chain } from 'viem'; -import { arbitrumSepolia, arbitrum as arbitrumOne, arbitrumNova } from 'viem/chains'; +import { Chain } from "viem"; +import { + arbitrumSepolia, + arbitrum as arbitrumOne, + arbitrumNova, +} from "viem/chains"; export const CHAIN_IDS = { ARBITRUM_ONE: arbitrumOne.id, @@ -15,7 +19,7 @@ export const DEFAULT_CHAINS: Record = { export const CHAIN_BLOCK_TIMES = { ETHEREUM: 12n, // ~12 seconds - OPTIMISM: 2n, // ~2 seconds + OPTIMISM: 2n, // ~2 seconds ARBITRUM: 12n, // Uses L1 block time } as const; @@ -40,11 +44,11 @@ export const DEFAULT_CONFIG = { } as const; export const ERROR_MESSAGES = { - INVALID_CHAIN_ID: 'Invalid chain ID provided', - INVALID_ADDRESS: 'Invalid address format', - INVALID_PRIVATE_KEY: 'Invalid private key format', - INVALID_FEE_WEIGHTS: 'Fee weights must sum to 10000 basis points', - INVALID_VALIDATOR_COUNT: 'Invalid number of validators', - INVALID_BATCH_POSTER_COUNT: 'Invalid number of batch posters', - INVALID_CONFIRMATION_COUNT: 'Invalid number of confirmations', -} as const; \ No newline at end of file + INVALID_CHAIN_ID: "Invalid chain ID provided", + INVALID_ADDRESS: "Invalid address format", + INVALID_PRIVATE_KEY: "Invalid private key format", + INVALID_FEE_WEIGHTS: "Fee weights must sum to 10000 basis points", + INVALID_VALIDATOR_COUNT: "Invalid number of validators", + INVALID_BATCH_POSTER_COUNT: "Invalid number of batch posters", + INVALID_CONFIRMATION_COUNT: "Invalid number of confirmations", +} as const; diff --git a/packages/arbitrum-orbit-toolkit/src/core/types.ts b/packages/arbitrum-orbit-toolkit/src/core/types.ts index 098192a..5e2540a 100644 --- a/packages/arbitrum-orbit-toolkit/src/core/types.ts +++ b/packages/arbitrum-orbit-toolkit/src/core/types.ts @@ -1,4 +1,4 @@ -import { Address, Chain } from 'viem'; +import { Address, Chain } from "viem"; export interface CoreContracts { rollup: Address; @@ -59,6 +59,9 @@ export interface FeeRecipient { export interface ClientConfig { parentChain: Chain; parentChainRpc?: string; - orbitChainId?: number; - orbitChainRpc?: string; -} \ No newline at end of file + orbitChainId: number; + orbitChainRpc: string; + orbitChainName: string; + orbitChainNetworkName: string; + orbitChainNativeCurrency: { name: string; symbol: string; decimals: number }; +} diff --git a/packages/arbitrum-orbit-toolkit/src/index.ts b/packages/arbitrum-orbit-toolkit/src/index.ts index 3e548ca..f757309 100644 --- a/packages/arbitrum-orbit-toolkit/src/index.ts +++ b/packages/arbitrum-orbit-toolkit/src/index.ts @@ -1,24 +1,55 @@ -import { Chain, Address } from 'viem'; -import { RollupConfig, ChainConfig } from './core/types'; +import { Chain, Address } from "viem"; +import { RollupConfig, ChainConfig } from "./core/types"; // Export all types -export * from './core/types'; -export * from './core/constants'; +export * from "./core/types"; +export * from "./core/constants"; // Export core functionality -export { createParentChainClient, createOrbitChainClient, createChainClients } from './core/clients'; +export { + createParentChainClient, + createOrbitChainClient, + createChainClients, +} from "./core/clients"; // Export rollup management -export { createRollup } from './rollup/create'; -export { setValidators, getValidatorStatus, isValidator } from './rollup/validators'; +export { + createRollup, + CreateRollupParams, + CreateRollupResult, +} from "./rollup/create"; +export { + setValidators, + getValidatorStatus, + isValidator, + SetValidatorsParams, + ValidatorStatus, +} from "./rollup/validators"; // Export bridge functionality -export { createTokenBridge } from './bridge/token'; -export { setupFastWithdrawal, isFastConfirmer } from './bridge/fast'; +export { + createTokenBridge, + CreateTokenBridgeParams, + CreateTokenBridgeResult, +} from "./bridge/token"; +export { + setupFastWithdrawal, + isFastConfirmer, + FastWithdrawalConfig, + FastWithdrawalSetupResult, +} from "./bridge/fast"; // Export configuration utilities -export { prepareNodeConfiguration } from './config/node'; -export { addPrivilegedExecutors } from './config/executor'; +export { + prepareNodeConfiguration, + NodeConfigParams, + NodeConfigResult, +} from "./config/node"; +export { + addPrivilegedExecutors, + ExecutorConfig, + ExecutorSetupResult, +} from "./config/executor"; // Export helper functions export { @@ -28,7 +59,7 @@ export { sanitizeAddresses, validateFeeWeights, formatTxHash, -} from './utils/helpers'; +} from "./utils/helpers"; // Export environment utilities export { @@ -36,12 +67,12 @@ export { validateRequiredEnvVars, validateOptionalEnvVars, validateRollupAddress, -} from './utils/env'; +} from "./utils/env"; export const createDefaultConfig = ( chainId: number | string, deployer: { address: Address }, - chainConfig: Partial = {} + chainConfig: Partial = {}, ): RollupConfig => ({ chainId: BigInt(chainId), owner: deployer.address, @@ -56,4 +87,4 @@ export const createDefaultConfig = ( }); // Re-export commonly used types from viem -export type { Chain, Address }; \ No newline at end of file +export type { Chain, Address }; diff --git a/packages/arbitrum-orbit-toolkit/src/rollup/create.ts b/packages/arbitrum-orbit-toolkit/src/rollup/create.ts index 4e1c478..e772ff1 100644 --- a/packages/arbitrum-orbit-toolkit/src/rollup/create.ts +++ b/packages/arbitrum-orbit-toolkit/src/rollup/create.ts @@ -1,19 +1,16 @@ -import { Address, Chain, PrivateKeyAccount, PublicClient } from 'viem'; -import { prepareChainConfig } from '@arbitrum/orbit-sdk'; +import { Address, Chain, PrivateKeyAccount, PublicClient } from "viem"; +import { prepareChainConfig } from "@arbitrum/orbit-sdk"; import { createRollupPrepareDeploymentParamsConfig, createRollupEnoughCustomFeeTokenAllowance, createRollupPrepareCustomFeeTokenApprovalTransactionRequest, createRollupPrepareTransactionRequest, createRollupPrepareTransactionReceipt, -} from '@arbitrum/orbit-sdk'; +} from "@arbitrum/orbit-sdk"; export interface CreateRollupParams { chainId: number | bigint; - owner: { - address: Address; - account: PrivateKeyAccount; - }; + owner: PrivateKeyAccount; validators: Address[]; batchPosters: Address[]; nativeToken?: Address; @@ -61,11 +58,12 @@ export async function createRollup( // Check and approve token allowance if needed if (!(await createRollupEnoughCustomFeeTokenAllowance(allowanceParams))) { - const approvalRequest = await createRollupPrepareCustomFeeTokenApprovalTransactionRequest( - allowanceParams - ); + const approvalRequest = + await createRollupPrepareCustomFeeTokenApprovalTransactionRequest( + allowanceParams + ); - const signedApprovalTx = await params.owner.account.signTransaction({ + const signedApprovalTx = await params.owner.signTransaction({ to: approvalRequest.to, data: approvalRequest.data, chainId: await parentChainClient.getChainId(), @@ -73,14 +71,16 @@ export async function createRollup( maxPriorityFeePerGas: approvalRequest.maxPriorityFeePerGas, gas: approvalRequest.gas, nonce: approvalRequest.nonce, - type: 'eip1559' as const, + type: "eip1559" as const, }); const approvalTxHash = await parentChainClient.sendRawTransaction({ serializedTransaction: signedApprovalTx, }); - await parentChainClient.waitForTransactionReceipt({ hash: approvalTxHash }); + await parentChainClient.waitForTransactionReceipt({ + hash: approvalTxHash, + }); } } @@ -96,7 +96,7 @@ export async function createRollup( publicClient: parentChainClient, }); - const signedTx = await params.owner.account.signTransaction({ + const signedTx = await params.owner.signTransaction({ to: txRequest.to, data: txRequest.data, chainId: await parentChainClient.getChainId(), @@ -104,7 +104,7 @@ export async function createRollup( maxPriorityFeePerGas: txRequest.maxPriorityFeePerGas, gas: txRequest.gas, nonce: txRequest.nonce, - type: 'eip1559' as const, + type: "eip1559" as const, }); const txHash = await parentChainClient.sendRawTransaction({ diff --git a/packages/arbitrum-orbit-toolkit/src/rollup/validators.ts b/packages/arbitrum-orbit-toolkit/src/rollup/validators.ts index e43b86b..1178120 100644 --- a/packages/arbitrum-orbit-toolkit/src/rollup/validators.ts +++ b/packages/arbitrum-orbit-toolkit/src/rollup/validators.ts @@ -1,19 +1,16 @@ -import { Address, PrivateKeyAccount, PublicClient, Chain } from 'viem'; +import { Address, PrivateKeyAccount, PublicClient, Chain } from "viem"; import { rollupAdminLogicPublicActions, getValidators, -} from '@arbitrum/orbit-sdk'; -import type { ValidatorConfig } from '../core/types'; -import { sanitizeAddresses } from '../utils/helpers'; +} from "@arbitrum/orbit-sdk"; +import type { ValidatorConfig } from "../core/types"; +import { getBlockExplorerUrl, sanitizeAddresses } from "../utils/helpers"; export interface SetValidatorsParams { rollupAddress: Address; validators: Address[]; isActive: boolean; - owner: { - address: Address; - account: PrivateKeyAccount; - }; + owner: PrivateKeyAccount; upgradeExecutor: Address; } @@ -30,9 +27,9 @@ export async function getValidatorStatus( rollup: rollupAddress, }); - return validators.validators.map(addr => ({ + return validators.validators.map((addr) => ({ address: addr, - isActive: validators.validators.includes(addr) + isActive: validators.validators.includes(addr), })); } @@ -50,16 +47,29 @@ export async function setValidators( const validatorAddresses = sanitizeAddresses(params.validators); const validatorStatuses = validatorAddresses.map(() => params.isActive); + // Check the status of each validator address before executing + for (const validatorAddress of validatorAddresses) { + const beforeStatus = await client.rollupAdminLogicReadContract({ + functionName: "isValidator", + args: [validatorAddress], + rollup: params.rollupAddress, + }); + + console.log( + `Before executing, validator ${validatorAddress} status is ${beforeStatus}` + ); + } + // Prepare transaction request const txRequest = await client.rollupAdminLogicPrepareTransactionRequest({ - functionName: 'setValidator', + functionName: "setValidator", args: [validatorAddresses, validatorStatuses], upgradeExecutor: params.upgradeExecutor, account: params.owner.address, }); // Sign and send transaction - const signedTx = await params.owner.account.signTransaction({ + const signedTx = await params.owner.signTransaction({ to: txRequest.to, data: txRequest.data, chainId: await client.getChainId(), @@ -67,7 +77,7 @@ export async function setValidators( maxPriorityFeePerGas: txRequest.maxPriorityFeePerGas, gas: txRequest.gas, nonce: txRequest.nonce, - type: 'eip1559' as const, + type: "eip1559" as const, }); const txHash = await client.sendRawTransaction({ @@ -75,7 +85,26 @@ export async function setValidators( }); // Wait for receipt - await client.waitForTransactionReceipt({ hash: txHash }); + const receipt = await client.waitForTransactionReceipt({ hash: txHash }); + + console.log( + `New validator address set in ${getBlockExplorerUrl(parentChainClient.chain)}/tx/${ + receipt.transactionHash + }` + ); + + // Check the status of each validator address after executing + for (const validatorAddress of validatorAddresses) { + const isValidatorStatus = await client.rollupAdminLogicReadContract({ + functionName: "isValidator", + args: [validatorAddress], + rollup: params.rollupAddress, + }); + + console.log( + `After executing, validator ${validatorAddress} status is ${isValidatorStatus}` + ); + } return txHash; } @@ -89,4 +118,4 @@ export async function isValidator( rollup: rollupAddress, }); return validators.validators.includes(address); -} \ No newline at end of file +} diff --git a/packages/arbitrum-orbit-toolkit/src/utils/env.ts b/packages/arbitrum-orbit-toolkit/src/utils/env.ts index a14787b..36e08f7 100644 --- a/packages/arbitrum-orbit-toolkit/src/utils/env.ts +++ b/packages/arbitrum-orbit-toolkit/src/utils/env.ts @@ -1,4 +1,4 @@ -import { Address } from 'viem'; +import { Address } from "viem"; export interface RequiredEnvVars { DEPLOYER_PRIVATE_KEY: string; @@ -18,19 +18,21 @@ export type EnvVars = RequiredEnvVars & OptionalEnvVars; /** * Validates required environment variables */ -export function validateRequiredEnvVars(envVars: NodeJS.ProcessEnv): RequiredEnvVars { +export function validateRequiredEnvVars( + envVars: NodeJS.ProcessEnv, +): RequiredEnvVars { const required: (keyof RequiredEnvVars)[] = [ - 'DEPLOYER_PRIVATE_KEY', - 'PARENT_CHAIN_RPC', - 'BATCH_POSTER_PRIVATE_KEY', - 'VALIDATOR_PRIVATE_KEY', + "DEPLOYER_PRIVATE_KEY", + "PARENT_CHAIN_RPC", + "BATCH_POSTER_PRIVATE_KEY", + "VALIDATOR_PRIVATE_KEY", ]; - const missing = required.filter(key => !envVars[key]); + const missing = required.filter((key) => !envVars[key]); if (missing.length > 0) { throw new Error( - `Missing required environment variables: ${missing.join(', ')}` + `Missing required environment variables: ${missing.join(", ")}`, ); } @@ -45,7 +47,9 @@ export function validateRequiredEnvVars(envVars: NodeJS.ProcessEnv): RequiredEnv /** * Validates optional environment variables */ -export function validateOptionalEnvVars(envVars: NodeJS.ProcessEnv): OptionalEnvVars { +export function validateOptionalEnvVars( + envVars: NodeJS.ProcessEnv, +): OptionalEnvVars { return { ROLLUP_ADDRESS: envVars.ROLLUP_ADDRESS, ETHEREUM_BEACON_RPC_URL: envVars.ETHEREUM_BEACON_RPC_URL, @@ -58,9 +62,9 @@ export function validateOptionalEnvVars(envVars: NodeJS.ProcessEnv): OptionalEnv */ export function validateRollupAddress(address?: string): Address | undefined { if (!address) return undefined; - - if (!address.startsWith('0x') || address.length !== 42) { - throw new Error('Invalid rollup address format'); + + if (!address.startsWith("0x") || address.length !== 42) { + throw new Error("Invalid rollup address format"); } return address as Address; @@ -74,4 +78,4 @@ export function validateEnv(env: NodeJS.ProcessEnv = process.env): EnvVars { ...validateRequiredEnvVars(env), ...validateOptionalEnvVars(env), }; -} \ No newline at end of file +} diff --git a/packages/arbitrum-orbit-toolkit/src/utils/helpers.ts b/packages/arbitrum-orbit-toolkit/src/utils/helpers.ts index e9cc014..c09a4a9 100644 --- a/packages/arbitrum-orbit-toolkit/src/utils/helpers.ts +++ b/packages/arbitrum-orbit-toolkit/src/utils/helpers.ts @@ -1,6 +1,6 @@ -import { Chain, Address } from 'viem'; -import { sanitizePrivateKey as orbitSanitizePrivateKey } from '@arbitrum/orbit-sdk/utils'; -import crypto from 'crypto'; +import { Chain, Address } from "viem"; +import { sanitizePrivateKey as orbitSanitizePrivateKey } from "@arbitrum/orbit-sdk/utils"; +import crypto from "crypto"; /** * Gets the block explorer URL for a given chain @@ -12,8 +12,13 @@ export function getBlockExplorerUrl(chain: Chain): string | undefined { /** * Calculates time delay from number of blocks for different chains */ -export function getTimeDelayFromBlocks(chainId: number, blocks: bigint): string { - const seconds = Number(chainId === 8453 || chainId === 84532 ? blocks * 2n : blocks * 12n); +export function getTimeDelayFromBlocks( + chainId: number, + blocks: bigint, +): string { + const seconds = Number( + chainId === 8453 || chainId === 84532 ? blocks * 2n : blocks * 12n, + ); const h = Math.floor(seconds / 3600); const m = Math.floor((seconds % 3600) / 60); const s = seconds % 60; @@ -23,10 +28,12 @@ export function getTimeDelayFromBlocks(chainId: number, blocks: bigint): string /** * Sanitizes a private key or generates a new one if undefined */ -export function withFallbackPrivateKey(privateKey: string | undefined): `0x${string}` { - if (typeof privateKey === 'undefined' || privateKey === '') { +export function withFallbackPrivateKey( + privateKey: string | undefined, +): `0x${string}` { + if (typeof privateKey === "undefined" || privateKey === "") { const randomBytes = crypto.randomBytes(32); - return `0x${randomBytes.toString('hex')}` as `0x${string}`; + return `0x${randomBytes.toString("hex")}` as `0x${string}`; } return orbitSanitizePrivateKey(privateKey); } @@ -35,7 +42,7 @@ export function withFallbackPrivateKey(privateKey: string | undefined): `0x${str * Validates an array of addresses and removes duplicates */ export function sanitizeAddresses(addresses: string[]): Address[] { - return [...new Set(addresses)].map(addr => addr as Address); + return [...new Set(addresses)].map((addr) => addr as Address); } /** @@ -52,4 +59,4 @@ export function validateFeeWeights(weights: bigint[]): boolean { export function formatTxHash(chain: Chain, hash: string): string { const explorer = getBlockExplorerUrl(chain); return explorer ? `${explorer}/tx/${hash}` : hash; -} \ No newline at end of file +} diff --git a/packages/arbitrum-orbit-toolkit/tsconfig.json b/packages/arbitrum-orbit-toolkit/tsconfig.json index 40a27f7..b483cc1 100644 --- a/packages/arbitrum-orbit-toolkit/tsconfig.json +++ b/packages/arbitrum-orbit-toolkit/tsconfig.json @@ -1,10 +1,10 @@ { - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "./dist", - "rootDir": "src", - "baseUrl": "." - }, - "include": ["src/**/*"], - "exclude": ["node_modules", "dist"] - } \ No newline at end of file + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": "src", + "baseUrl": "." + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/arbitrum-orbit-toolkit/tsconfig.tsbuildinfo b/packages/arbitrum-orbit-toolkit/tsconfig.tsbuildinfo new file mode 100644 index 0000000..1b0af53 --- /dev/null +++ b/packages/arbitrum-orbit-toolkit/tsconfig.tsbuildinfo @@ -0,0 +1 @@ +{"root":["./src/index.ts","./src/bridge/fast.ts","./src/bridge/token.ts","./src/config/executor.ts","./src/config/node.ts","./src/core/clients.ts","./src/core/constants.ts","./src/core/types.ts","./src/rollup/create.ts","./src/rollup/validators.ts","./src/utils/env.ts","./src/utils/helpers.ts"],"version":"5.6.3"} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index acdf8b2..6022c6b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,25 +1,14 @@ { - "compilerOptions": { - "target": "ES2020", - "module": "ESNext", - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "skipLibCheck": true, - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true, - "useDefineForClassFields": true, - "allowJs": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "paths": { - "@/*": ["./src/*"] - } - }, - "exclude": ["node_modules"] - } \ No newline at end of file + "compilerOptions": { + "target": "es2020", + "module": "commonjs", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "outDir": "dist", + "declaration": true, + "resolveJsonModule": true + }, + "exclude": ["node_modules"] +} diff --git a/yarn.lock b/yarn.lock index dda3a64..0666c8b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1356,6 +1356,11 @@ picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +prettier@^3.2.5: + version "3.3.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.3.tgz#30c54fe0be0d8d12e6ae61dbb10109ea00d53105" + integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew== + proper-lockfile@^4.1.1: version "4.1.2" resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz#c8b9de2af6b2f1601067f98e01ac66baa223141f"