diff --git a/examples/create-rollup-custom-fee-token/index.ts b/examples/create-rollup-custom-fee-token/index.ts index 835066ec..f22a358a 100644 --- a/examples/create-rollup-custom-fee-token/index.ts +++ b/examples/create-rollup-custom-fee-token/index.ts @@ -1,6 +1,6 @@ -import { Chain, createPublicClient, http, Address } from 'viem'; -import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; -import { arbitrumSepolia } from 'viem/chains'; +import { Chain, http, Address } from "viem"; +import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; +import { arbitrumSepolia } from "viem/chains"; import { createRollupPrepareConfig, prepareChainConfig, @@ -8,11 +8,12 @@ import { createRollupPrepareCustomFeeTokenApprovalTransactionRequest, createRollupPrepareTransactionRequest, createRollupPrepareTransactionReceipt, -} from '@arbitrum/orbit-sdk'; -import { generateChainId } from '@arbitrum/orbit-sdk/utils'; + createOrbitClient, +} from "@arbitrum/orbit-sdk"; +import { generateChainId } from "@arbitrum/orbit-sdk/utils"; function sanitizePrivateKey(privateKey: string): `0x${string}` { - if (!privateKey.startsWith('0x')) { + if (!privateKey.startsWith("0x")) { return `0x${privateKey}`; } @@ -20,7 +21,7 @@ function sanitizePrivateKey(privateKey: string): `0x${string}` { } function withFallbackPrivateKey(privateKey: string | undefined): `0x${string}` { - if (typeof privateKey === 'undefined') { + if (typeof privateKey === "undefined") { return generatePrivateKey(); } @@ -31,33 +32,41 @@ function getBlockExplorerUrl(chain: Chain) { return chain.blockExplorers?.default.url; } -if (typeof process.env.DEPLOYER_PRIVATE_KEY === 'undefined') { - throw new Error(`Please provide the "DEPLOYER_PRIVATE_KEY" environment variable`); +if (typeof process.env.DEPLOYER_PRIVATE_KEY === "undefined") { + throw new Error( + `Please provide the "DEPLOYER_PRIVATE_KEY" environment variable` + ); } // load or generate a random batch poster account -const batchPosterPrivateKey = withFallbackPrivateKey(process.env.BATCH_POSTER_PRIVATE_KEY); +const batchPosterPrivateKey = withFallbackPrivateKey( + process.env.BATCH_POSTER_PRIVATE_KEY +); const batchPoster = privateKeyToAccount(batchPosterPrivateKey).address; // load or generate a random validator account -const validatorPrivateKey = withFallbackPrivateKey(process.env.VALIDATOR_PRIVATE_KEY); +const validatorPrivateKey = withFallbackPrivateKey( + process.env.VALIDATOR_PRIVATE_KEY +); const validator = privateKeyToAccount(validatorPrivateKey).address; // set the parent chain and create a public client for it const parentChain = arbitrumSepolia; -const parentChainPublicClient = createPublicClient({ +const parentChainPublicClient = createOrbitClient({ chain: parentChain, transport: http(), }); // load the deployer account -const deployer = privateKeyToAccount(sanitizePrivateKey(process.env.DEPLOYER_PRIVATE_KEY)); +const deployer = privateKeyToAccount( + sanitizePrivateKey(process.env.DEPLOYER_PRIVATE_KEY) +); async function main() { // generate a random chain id const chainId = generateChainId(); // set the custom fee token - const nativeToken: Address = '0xf861378b543525ae0c47d33c90c954dc774ac1f9'; + const nativeToken: Address = "0xf861378b543525ae0c47d33c90c954dc774ac1f9"; // create the chain config const chainConfig = prepareChainConfig({ @@ -75,9 +84,10 @@ async function main() { }; if (!(await createRollupEnoughCustomFeeTokenAllowance(allowanceParams))) { - const approvalTxRequest = await createRollupPrepareCustomFeeTokenApprovalTransactionRequest( - allowanceParams - ); + const approvalTxRequest = + await createRollupPrepareCustomFeeTokenApprovalTransactionRequest( + allowanceParams + ); // sign and send the transaction const approvalTxHash = await parentChainPublicClient.sendRawTransaction({ @@ -125,7 +135,11 @@ async function main() { await parentChainPublicClient.waitForTransactionReceipt({ hash: txHash }) ); - console.log(`Deployed in ${getBlockExplorerUrl(parentChain)}/tx/${txReceipt.transactionHash}`); + console.log( + `Deployed in ${getBlockExplorerUrl(parentChain)}/tx/${ + txReceipt.transactionHash + }` + ); } main(); diff --git a/examples/create-rollup-eth/index.ts b/examples/create-rollup-eth/index.ts index 8f7e23f0..a19ef46c 100644 --- a/examples/create-rollup-eth/index.ts +++ b/examples/create-rollup-eth/index.ts @@ -1,16 +1,17 @@ -import { Chain, createPublicClient, http } from 'viem'; -import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; -import { arbitrumSepolia } from 'viem/chains'; +import { Chain, http } from "viem"; +import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; +import { arbitrumSepolia } from "viem/chains"; import { createRollupPrepareConfig, prepareChainConfig, createRollupPrepareTransactionRequest, createRollupPrepareTransactionReceipt, -} from '@arbitrum/orbit-sdk'; -import { generateChainId } from '@arbitrum/orbit-sdk/utils'; + createOrbitClient, +} from "@arbitrum/orbit-sdk"; +import { generateChainId } from "@arbitrum/orbit-sdk/utils"; function sanitizePrivateKey(privateKey: string): `0x${string}` { - if (!privateKey.startsWith('0x')) { + if (!privateKey.startsWith("0x")) { return `0x${privateKey}`; } @@ -18,7 +19,7 @@ function sanitizePrivateKey(privateKey: string): `0x${string}` { } function withFallbackPrivateKey(privateKey: string | undefined): `0x${string}` { - if (typeof privateKey === 'undefined') { + if (typeof privateKey === "undefined") { return generatePrivateKey(); } @@ -29,24 +30,35 @@ function getBlockExplorerUrl(chain: Chain) { return chain.blockExplorers?.default.url; } -if (typeof process.env.DEPLOYER_PRIVATE_KEY === 'undefined') { - throw new Error(`Please provide the "DEPLOYER_PRIVATE_KEY" environment variable`); +if (typeof process.env.DEPLOYER_PRIVATE_KEY === "undefined") { + throw new Error( + `Please provide the "DEPLOYER_PRIVATE_KEY" environment variable` + ); } // load or generate a random batch poster account -const batchPosterPrivateKey = withFallbackPrivateKey(process.env.BATCH_POSTER_PRIVATE_KEY); +const batchPosterPrivateKey = withFallbackPrivateKey( + process.env.BATCH_POSTER_PRIVATE_KEY +); const batchPoster = privateKeyToAccount(batchPosterPrivateKey).address; // load or generate a random validator account -const validatorPrivateKey = withFallbackPrivateKey(process.env.VALIDATOR_PRIVATE_KEY); +const validatorPrivateKey = withFallbackPrivateKey( + process.env.VALIDATOR_PRIVATE_KEY +); const validator = privateKeyToAccount(validatorPrivateKey).address; // set the parent chain and create a public client for it const parentChain = arbitrumSepolia; -const parentChainPublicClient = createPublicClient({ chain: parentChain, transport: http() }); +const parentChainPublicClient = createOrbitClient({ + chain: parentChain, + transport: http(), +}); // load the deployer account -const deployer = privateKeyToAccount(sanitizePrivateKey(process.env.DEPLOYER_PRIVATE_KEY)); +const deployer = privateKeyToAccount( + sanitizePrivateKey(process.env.DEPLOYER_PRIVATE_KEY) +); async function main() { // generate a random chain id @@ -55,7 +67,10 @@ async function main() { // create the chain config const chainConfig = prepareChainConfig({ chainId, - arbitrum: { InitialChainOwner: deployer.address, DataAvailabilityCommittee: true }, + arbitrum: { + InitialChainOwner: deployer.address, + DataAvailabilityCommittee: true, + }, }); // prepare the transaction for deploying the core contracts @@ -83,7 +98,11 @@ async function main() { await parentChainPublicClient.waitForTransactionReceipt({ hash: txHash }) ); - console.log(`Deployed in ${getBlockExplorerUrl(parentChain)}/tx/${txReceipt.transactionHash}`); + console.log( + `Deployed in ${getBlockExplorerUrl(parentChain)}/tx/${ + txReceipt.transactionHash + }` + ); } main(); diff --git a/examples/prepare-node-config/index.ts b/examples/prepare-node-config/index.ts index 2b995599..5c2f0a47 100644 --- a/examples/prepare-node-config/index.ts +++ b/examples/prepare-node-config/index.ts @@ -1,13 +1,14 @@ -import { Chain, createPublicClient, http } from 'viem'; -import { arbitrumSepolia } from 'viem/chains'; +import { Chain, http } from "viem"; +import { arbitrumSepolia } from "viem/chains"; import { ChainConfig, createRollupPrepareTransaction, createRollupPrepareTransactionReceipt, prepareNodeConfig, -} from '@arbitrum/orbit-sdk'; + createOrbitClient, +} from "@arbitrum/orbit-sdk"; -import { writeFile } from 'fs/promises'; +import { writeFile } from "fs/promises"; function getRpcUrl(chain: Chain) { return chain.rpcUrls.default.http[0]; @@ -15,14 +16,15 @@ function getRpcUrl(chain: Chain) { // set the parent chain and create a public client for it const parentChain = arbitrumSepolia; -const parentChainPublicClient = createPublicClient({ +const parentChainPublicClient = createOrbitClient({ chain: parentChain, transport: http(), }); async function main() { // tx hash for the transaction to create rollup - const txHash = '0x22bb24020ee839e4a266960aa73c6bf5b02621e2de3f2a755c9f2869014140d7'; + const txHash = + "0x22bb24020ee839e4a266960aa73c6bf5b02621e2de3f2a755c9f2869014140d7"; // get the transaction const tx = createRollupPrepareTransaction( @@ -35,22 +37,24 @@ async function main() { ); // get the chain config from the transaction inputs - const chainConfig: ChainConfig = JSON.parse(tx.getInputs()[0].config.chainConfig); + const chainConfig: ChainConfig = JSON.parse( + tx.getInputs()[0].config.chainConfig + ); // get the core contracts from the transaction receipt const coreContracts = txReceipt.getCoreContracts(); // prepare the node config const nodeConfig = prepareNodeConfig({ - chainName: 'My Orbit Chain', + chainName: "My Orbit Chain", chainConfig, coreContracts, - batchPosterPrivateKey: 'INSERT_BATCH_POSTER_PRIVATE_KEY_HERE', - validatorPrivateKey: 'INSERT_VALIDATOR_PRIVATE_KEY_HERE', + batchPosterPrivateKey: "INSERT_BATCH_POSTER_PRIVATE_KEY_HERE", + validatorPrivateKey: "INSERT_VALIDATOR_PRIVATE_KEY_HERE", parentChainId: parentChain.id, parentChainRpcUrl: getRpcUrl(parentChain), }); - await writeFile('node-config.json', JSON.stringify(nodeConfig, null, 2)); + await writeFile("node-config.json", JSON.stringify(nodeConfig, null, 2)); console.log(`Node config written to "node-config.json"`); } diff --git a/examples/set-valid-keyset/index.ts b/examples/set-valid-keyset/index.ts index 2dede0e5..224112ad 100644 --- a/examples/set-valid-keyset/index.ts +++ b/examples/set-valid-keyset/index.ts @@ -1,10 +1,11 @@ -import { Chain, createPublicClient, http } from 'viem'; -import { privateKeyToAccount } from 'viem/accounts'; -import { arbitrumSepolia } from 'viem/chains'; -import { setValidKeysetPrepareTransactionRequest } from '@arbitrum/orbit-sdk'; +import { Chain, http } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import { arbitrumSepolia } from "viem/chains"; +import { setValidKeysetPrepareTransactionRequest } from "@arbitrum/orbit-sdk"; +import { createOrbitClient } from "@arbitrum/orbit-sdk/dist"; function sanitizePrivateKey(privateKey: string): `0x${string}` { - if (!privateKey.startsWith('0x')) { + if (!privateKey.startsWith("0x")) { return `0x${privateKey}`; } @@ -15,26 +16,33 @@ function getBlockExplorerUrl(chain: Chain) { return chain.blockExplorers?.default.url; } -if (typeof process.env.DEPLOYER_PRIVATE_KEY === 'undefined') { - throw new Error(`Please provide the "DEPLOYER_PRIVATE_KEY" environment variable`); +if (typeof process.env.DEPLOYER_PRIVATE_KEY === "undefined") { + throw new Error( + `Please provide the "DEPLOYER_PRIVATE_KEY" environment variable` + ); } const keyset = - '0x00000000000000010000000000000001012160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'; + "0x00000000000000010000000000000001012160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; // set the parent chain and create a public client for it const parentChain = arbitrumSepolia; -const parentChainPublicClient = createPublicClient({ chain: parentChain, transport: http() }); +const parentChainPublicClient = createOrbitClient({ + chain: parentChain, + transport: http(), +}); // load the deployer account -const deployer = privateKeyToAccount(sanitizePrivateKey(process.env.DEPLOYER_PRIVATE_KEY)); +const deployer = privateKeyToAccount( + sanitizePrivateKey(process.env.DEPLOYER_PRIVATE_KEY) +); async function main() { // prepare the transaction setting the keyset const txRequest = await setValidKeysetPrepareTransactionRequest({ coreContracts: { - upgradeExecutor: '0x82c42d2cdcbe6b4482900e299b3532082e217132', - sequencerInbox: '0x42b5da0625cf278067955f07045f63cafd79274f', + upgradeExecutor: "0x82c42d2cdcbe6b4482900e299b3532082e217132", + sequencerInbox: "0x42b5da0625cf278067955f07045f63cafd79274f", }, keyset, account: deployer.address, @@ -47,10 +55,14 @@ async function main() { }); // wait for the transaction receipt - const txReceipt = await parentChainPublicClient.waitForTransactionReceipt({ hash: txHash }); + const txReceipt = await parentChainPublicClient.waitForTransactionReceipt({ + hash: txHash, + }); console.log( - `Keyset updated in ${getBlockExplorerUrl(parentChain)}/tx/${txReceipt.transactionHash}` + `Keyset updated in ${getBlockExplorerUrl(parentChain)}/tx/${ + txReceipt.transactionHash + }` ); } diff --git a/src/contracts.ts b/src/contracts.ts index 660175bf..c5f48f55 100644 --- a/src/contracts.ts +++ b/src/contracts.ts @@ -1,4 +1,4 @@ -import { parseAbi } from 'viem'; +import { parseAbi } from "viem"; import { erc20ABI, @@ -6,7 +6,7 @@ import { arbOwnerPublicConfig, rollupCreatorConfig, tokenBridgeCreatorConfig, -} from './generated'; +} from "./generated"; export const erc20 = { abi: erc20ABI, @@ -25,9 +25,13 @@ export const arbOwnerPublic = { export const rollupCreator = rollupCreatorConfig; export const tokenBridgeCreator = tokenBridgeCreatorConfig; +export const getRollupCreatorAddressForChainId = ( + chainId: keyof typeof rollupCreator.address +) => rollupCreator.address[chainId]; + export const upgradeExecutor = { abi: parseAbi([ - 'function execute(address upgrade, bytes upgradeCallData)', - 'function executeCall(address target, bytes targetCallData)', + "function execute(address upgrade, bytes upgradeCallData)", + "function executeCall(address target, bytes targetCallData)", ]), }; diff --git a/src/createRollup.integration.test.ts b/src/createRollup.integration.test.ts index 8cb400d9..9ff4c244 100644 --- a/src/createRollup.integration.test.ts +++ b/src/createRollup.integration.test.ts @@ -1,22 +1,23 @@ -import { it, expect } from 'vitest'; -import { createPublicClient, http, parseGwei, zeroAddress } from 'viem'; +import { it, expect } from "vitest"; +import { createPublicClient, http, parseGwei, zeroAddress } from "viem"; -import { nitroTestnodeL2 } from './chains'; -import { generateChainId } from './utils'; -import { prepareChainConfig } from './prepareChainConfig'; -import { createRollupPrepareConfig } from './createRollupPrepareConfig'; -import { createRollupPrepareTransaction } from './createRollupPrepareTransaction'; -import { createRollupPrepareTransactionRequest } from './createRollupPrepareTransactionRequest'; -import { createRollupPrepareTransactionReceipt } from './createRollupPrepareTransactionReceipt'; +import { nitroTestnodeL2 } from "./chains"; +import { generateChainId } from "./utils"; +import { prepareChainConfig } from "./prepareChainConfig"; +import { createRollupPrepareConfig } from "./createRollupPrepareConfig"; +import { createRollupPrepareTransaction } from "./createRollupPrepareTransaction"; +import { createRollupPrepareTransactionRequest } from "./createRollupPrepareTransactionRequest"; +import { createRollupPrepareTransactionReceipt } from "./createRollupPrepareTransactionReceipt"; -import { getTestPrivateKeyAccount } from './testHelpers'; +import { getTestPrivateKeyAccount } from "./testHelpers"; +import { createOrbitClient } from "./orbitClient"; const deployer = getTestPrivateKeyAccount(); const batchPoster = deployer.address; const validators = [deployer.address]; -const publicClient = createPublicClient({ +const publicClient = createOrbitClient({ chain: nitroTestnodeL2, transport: http(), }); @@ -66,12 +67,12 @@ it(`successfully deploys core contracts through rollup creator`, async () => { expect(arg.maxDataSize).toEqual(104_857n); expect(arg.nativeToken).toEqual(zeroAddress); expect(arg.deployFactoriesToL2).toEqual(true); - expect(arg.maxFeePerGasForRetryables).toEqual(parseGwei('0.1')); + expect(arg.maxFeePerGasForRetryables).toEqual(parseGwei("0.1")); // get the transaction receipt after waiting for the transaction to complete const txReceipt = createRollupPrepareTransactionReceipt( await publicClient.waitForTransactionReceipt({ hash: txHash }) ); - expect(txReceipt.status).toEqual('success'); + expect(txReceipt.status).toEqual("success"); }); diff --git a/src/createRollup.ts b/src/createRollup.ts index 2bbbd3a8..4a105a3d 100644 --- a/src/createRollup.ts +++ b/src/createRollup.ts @@ -1,24 +1,24 @@ -import { PublicClient, WalletClient, GetFunctionArgs } from 'viem'; +import { PublicClient, WalletClient, GetFunctionArgs } from "viem"; -import { rollupCreator } from './contracts'; -import { validParentChainId } from './types/ParentChain'; -import { defaults } from './createRollupDefaults'; -import { createRollupGetCallValue } from './createRollupGetCallValue'; -import { createRollupGetMaxDataSize } from './createRollupGetMaxDataSize'; +import { getRollupCreatorAddressForChainId, rollupCreator } from "./contracts"; +import { validParentChainId } from "./types/ParentChain"; +import { defaults } from "./createRollupDefaults"; +import { createRollupGetCallValue } from "./createRollupGetCallValue"; +import { createRollupGetMaxDataSize } from "./createRollupGetMaxDataSize"; import { createRollupPrepareTransactionReceipt, CreateRollupTransactionReceipt, -} from './createRollupPrepareTransactionReceipt'; -import { isCustomFeeTokenAddress } from './utils/isCustomFeeTokenAddress'; -import { ChainConfig } from './types/ChainConfig'; -import { isAnyTrustChainConfig } from './utils/isAnyTrustChainConfig'; +} from "./createRollupPrepareTransactionReceipt"; +import { isCustomFeeTokenAddress } from "./utils/isCustomFeeTokenAddress"; +import { ChainConfig } from "./types/ChainConfig"; +import { isAnyTrustChainConfig } from "./utils/isAnyTrustChainConfig"; export type CreateRollupFunctionInputs = GetFunctionArgs< typeof rollupCreator.abi, - 'createRollup' ->['args']; + "createRollup" +>["args"]; -type RequiredKeys = 'config' | 'batchPoster' | 'validators'; +type RequiredKeys = "config" | "batchPoster" | "validators"; export type CreateRollupParams = Pick< CreateRollupFunctionInputs[0], @@ -39,11 +39,11 @@ export async function createRollup({ const account = walletClient.account?.address; if (!validParentChainId(chainId)) { - throw new Error('chainId is undefined'); + throw new Error("chainId is undefined"); } - if (typeof account === 'undefined') { - throw new Error('account is undefined'); + if (typeof account === "undefined") { + throw new Error("account is undefined"); } const chainConfig: ChainConfig = JSON.parse(params.config.chainConfig); @@ -60,9 +60,9 @@ export async function createRollup({ const maxDataSize = createRollupGetMaxDataSize(chainId); const { request } = await publicClient.simulateContract({ - address: rollupCreator.address[chainId], + address: getRollupCreatorAddressForChainId(chainId), abi: rollupCreator.abi, - functionName: 'createRollup', + functionName: "createRollup", args: [{ ...defaults, ...params, maxDataSize }], value: createRollupGetCallValue(params), account, diff --git a/src/createRollupEnoughCustomFeeTokenAllowance.ts b/src/createRollupEnoughCustomFeeTokenAllowance.ts index f7c2eb20..80ee8d6f 100644 --- a/src/createRollupEnoughCustomFeeTokenAllowance.ts +++ b/src/createRollupEnoughCustomFeeTokenAllowance.ts @@ -1,9 +1,9 @@ -import { Address, PublicClient } from 'viem'; +import { Address, PublicClient } from "viem"; -import { rollupCreator } from './contracts'; -import { validParentChainId } from './types/ParentChain'; -import { fetchAllowance } from './utils/erc20'; -import { deterministicFactoriesDeploymentEstimatedFees } from './constants'; +import { getRollupCreatorAddressForChainId, rollupCreator } from "./contracts"; +import { validParentChainId } from "./types/ParentChain"; +import { fetchAllowance } from "./utils/erc20"; +import { deterministicFactoriesDeploymentEstimatedFees } from "./constants"; export type CreateRollupEnoughCustomFeeTokenAllowanceParams = { nativeToken: Address; @@ -19,13 +19,13 @@ export async function createRollupEnoughCustomFeeTokenAllowance({ const chainId = publicClient.chain?.id; if (!validParentChainId(chainId)) { - throw new Error('chainId is undefined'); + throw new Error("chainId is undefined"); } const allowance = await fetchAllowance({ address: nativeToken, owner: account, - spender: rollupCreator.address[chainId], + spender: getRollupCreatorAddressForChainId(chainId), publicClient, }); diff --git a/src/createRollupPrepareCustomFeeTokenApprovalTransactionRequest.ts b/src/createRollupPrepareCustomFeeTokenApprovalTransactionRequest.ts index 593cd45a..17288ec1 100644 --- a/src/createRollupPrepareCustomFeeTokenApprovalTransactionRequest.ts +++ b/src/createRollupPrepareCustomFeeTokenApprovalTransactionRequest.ts @@ -1,15 +1,16 @@ -import { Address, PublicClient, maxInt256 } from 'viem'; +import { Address, PublicClient, maxInt256 } from "viem"; -import { approvePrepareTransactionRequest } from './utils/erc20'; -import { validParentChainId } from './types/ParentChain'; -import { rollupCreator } from './contracts'; +import { approvePrepareTransactionRequest } from "./utils/erc20"; +import { validParentChainId } from "./types/ParentChain"; +import { getRollupCreatorAddressForChainId, rollupCreator } from "./contracts"; +import { OrbitClient } from "./orbitClient"; export type CreateRollupPrepareCustomFeeTokenApprovalTransactionRequestParams = { amount?: bigint; nativeToken: Address; account: Address; - publicClient: PublicClient; + publicClient: OrbitClient; }; export async function createRollupPrepareCustomFeeTokenApprovalTransactionRequest({ @@ -18,16 +19,13 @@ export async function createRollupPrepareCustomFeeTokenApprovalTransactionReques account, publicClient, }: CreateRollupPrepareCustomFeeTokenApprovalTransactionRequestParams) { - const chainId = publicClient.chain?.id; - - if (!validParentChainId(chainId)) { - throw new Error('chainId is undefined'); - } + const chainId = publicClient.getValidChainId(); + const spender = publicClient.getRollupCreatorAddress(); const request = await approvePrepareTransactionRequest({ address: nativeToken, owner: account, - spender: rollupCreator.address[chainId], + spender, amount, publicClient, }); diff --git a/src/createRollupPrepareTransactionRequest.ts b/src/createRollupPrepareTransactionRequest.ts index 42b75bdf..e7d2e0ea 100644 --- a/src/createRollupPrepareTransactionRequest.ts +++ b/src/createRollupPrepareTransactionRequest.ts @@ -1,21 +1,22 @@ -import { Address, PublicClient, encodeFunctionData } from 'viem'; - -import { CreateRollupParams } from './createRollup'; -import { defaults } from './createRollupDefaults'; -import { createRollupGetCallValue } from './createRollupGetCallValue'; -import { createRollupGetMaxDataSize } from './createRollupGetMaxDataSize'; -import { rollupCreator } from './contracts'; -import { validParentChainId } from './types/ParentChain'; -import { isCustomFeeTokenAddress } from './utils/isCustomFeeTokenAddress'; -import { ChainConfig } from './types/ChainConfig'; -import { isAnyTrustChainConfig } from './utils/isAnyTrustChainConfig'; +import { Address, PublicClient, encodeFunctionData } from "viem"; + +import { CreateRollupParams } from "./createRollup"; +import { defaults } from "./createRollupDefaults"; +import { createRollupGetCallValue } from "./createRollupGetCallValue"; +import { createRollupGetMaxDataSize } from "./createRollupGetMaxDataSize"; +import { rollupCreator } from "./contracts"; +import { validParentChainId } from "./types/ParentChain"; +import { isCustomFeeTokenAddress } from "./utils/isCustomFeeTokenAddress"; +import { ChainConfig } from "./types/ChainConfig"; +import { isAnyTrustChainConfig } from "./utils/isAnyTrustChainConfig"; +import { OrbitClient } from "./orbitClient"; function createRollupEncodeFunctionData( params: CreateRollupParams & { maxDataSize: bigint } ) { return encodeFunctionData({ abi: rollupCreator.abi, - functionName: 'createRollup', + functionName: "createRollup", args: [{ ...defaults, ...params }], }); } @@ -27,13 +28,9 @@ export async function createRollupPrepareTransactionRequest({ }: { params: CreateRollupParams; account: Address; - publicClient: PublicClient; + publicClient: OrbitClient; }) { - const chainId = publicClient.chain?.id; - - if (!validParentChainId(chainId)) { - throw new Error('chainId is undefined'); - } + const chainId = publicClient.getValidChainId(); const chainConfig: ChainConfig = JSON.parse(params.config.chainConfig); @@ -50,7 +47,7 @@ export async function createRollupPrepareTransactionRequest({ const request = await publicClient.prepareTransactionRequest({ chain: publicClient.chain, - to: rollupCreator.address[chainId], + to: publicClient.getRollupCreatorAddress(), data: createRollupEncodeFunctionData({ ...params, maxDataSize }), value: createRollupGetCallValue(params), account, diff --git a/src/index.ts b/src/index.ts index b62d67ff..a38c3e19 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,48 +1,49 @@ -import { createRollup } from './createRollup'; +import { createRollup } from "./createRollup"; import { createRollupPrepareConfig, CreateRollupPrepareConfigParams, CreateRollupPrepareConfigResult, -} from './createRollupPrepareConfig'; +} from "./createRollupPrepareConfig"; import { prepareChainConfig, PrepareChainConfigParams, -} from './prepareChainConfig'; +} from "./prepareChainConfig"; import { createRollupEnoughCustomFeeTokenAllowance, CreateRollupEnoughCustomFeeTokenAllowanceParams, -} from './createRollupEnoughCustomFeeTokenAllowance'; +} from "./createRollupEnoughCustomFeeTokenAllowance"; import { createRollupPrepareCustomFeeTokenApprovalTransactionRequest, CreateRollupPrepareCustomFeeTokenApprovalTransactionRequestParams, -} from './createRollupPrepareCustomFeeTokenApprovalTransactionRequest'; -import { createRollupPrepareTransactionRequest } from './createRollupPrepareTransactionRequest'; +} from "./createRollupPrepareCustomFeeTokenApprovalTransactionRequest"; +import { createRollupPrepareTransactionRequest } from "./createRollupPrepareTransactionRequest"; import { createRollupPrepareTransaction, CreateRollupTransaction, -} from './createRollupPrepareTransaction'; +} from "./createRollupPrepareTransaction"; import { createRollupPrepareTransactionReceipt, CreateRollupTransactionReceipt, -} from './createRollupPrepareTransactionReceipt'; -import { setValidKeyset, SetValidKeysetParams } from './setValidKeyset'; +} from "./createRollupPrepareTransactionReceipt"; +import { setValidKeyset, SetValidKeysetParams } from "./setValidKeyset"; import { setValidKeysetPrepareTransactionRequest, SetValidKeysetPrepareTransactionRequestParams, -} from './setValidKeysetPrepareTransactionRequest'; +} from "./setValidKeysetPrepareTransactionRequest"; import { UpgradeExecutorAbi, UpgradeExecutorFunctionName, upgradeExecutorEncodeFunctionData, UpgradeExecutorEncodeFunctionDataParameters, -} from './upgradeExecutor'; +} from "./upgradeExecutor"; -import { ChainConfig, ChainConfigArbitrumParams } from './types/ChainConfig'; -import { CoreContracts } from './types/CoreContracts'; -import { ParentChain, ParentChainId } from './types/ParentChain'; -import { NodeConfig, NodeConfigChainInfoJson } from './types/NodeConfig'; -import { prepareNodeConfig } from './prepareNodeConfig'; -import * as utils from './utils'; +import { ChainConfig, ChainConfigArbitrumParams } from "./types/ChainConfig"; +import { CoreContracts } from "./types/CoreContracts"; +import { ParentChain, ParentChainId } from "./types/ParentChain"; +import { NodeConfig, NodeConfigChainInfoJson } from "./types/NodeConfig"; +import { prepareNodeConfig } from "./prepareNodeConfig"; +import * as utils from "./utils"; +import { createOrbitClient, OrbitClient } from "./orbitClient"; export { createRollup, @@ -79,4 +80,7 @@ export { NodeConfigChainInfoJson, prepareNodeConfig, utils, + createOrbitClient, }; + +export type { OrbitClient }; diff --git a/src/orbitClient.ts b/src/orbitClient.ts new file mode 100644 index 00000000..52ae6303 --- /dev/null +++ b/src/orbitClient.ts @@ -0,0 +1,39 @@ +import { + Chain, + PublicClient, + PublicClientConfig, + Transport, + createPublicClient, +} from "viem"; +import { rollupCreator } from "./contracts"; +import { ParentChainId, validParentChainId } from "./types/ParentChain"; + +export interface OrbitClient extends PublicClient { + getRollupCreatorAddress(): `0x${string}`; + getValidChainId(): ParentChainId; +} + +export function createOrbitClient({ + chain, + transport, +}: PublicClientConfig): OrbitClient { + return createPublicClient({ + chain, + transport, + }).extend((client) => ({ + getRollupCreatorAddress: () => { + const chainId = client.chain?.id; + if (!validParentChainId(chainId)) { + throw new Error("chainId is undefined"); + } + return rollupCreator.address[chainId]; + }, + getValidChainId: () => { + const chainId = client.chain?.id; + if (!validParentChainId(chainId)) { + throw new Error("chainId is undefined"); + } + return chainId; + }, + })); +} diff --git a/src/prepareNodeConfig.ts b/src/prepareNodeConfig.ts index 9089e375..96189262 100644 --- a/src/prepareNodeConfig.ts +++ b/src/prepareNodeConfig.ts @@ -2,19 +2,19 @@ import { NodeConfig, NodeConfigChainInfoJson, NodeConfigDataAvailabilityRpcAggregatorBackendsJson, -} from './types/NodeConfig'; -import { ChainConfig } from './types/ChainConfig'; -import { CoreContracts } from './types/CoreContracts'; -import { ParentChainId, validParentChainId } from './types/ParentChain'; +} from "./types/NodeConfig"; +import { ChainConfig } from "./types/ChainConfig"; +import { CoreContracts } from "./types/CoreContracts"; +import { ParentChainId, validParentChainId } from "./types/ParentChain"; import { sepolia, arbitrumSepolia, nitroTestnodeL1, nitroTestnodeL2, -} from './chains'; +} from "./chains"; function sanitizePrivateKey(privateKey: string) { - return privateKey.startsWith('0x') ? privateKey.slice(2) : privateKey; + return privateKey.startsWith("0x") ? privateKey.slice(2) : privateKey; } function stringifyInfoJson(infoJson: NodeConfigChainInfoJson): string { @@ -29,6 +29,7 @@ function stringifyBackendsJson( function parentChainIsArbitrum(parentChainId: ParentChainId): boolean { // doing switch here to make sure it's exhaustive when checking against `ParentChainId` + switch (parentChainId) { case sepolia.id: case nitroTestnodeL1.id: @@ -64,89 +65,89 @@ export function prepareNodeConfig({ } const config: NodeConfig = { - 'chain': { - 'info-json': stringifyInfoJson([ + chain: { + "info-json": stringifyInfoJson([ { - 'chain-id': chainConfig.chainId, - 'parent-chain-id': parentChainId, - 'parent-chain-is-arbitrum': parentChainIsArbitrum(parentChainId), - 'chain-name': chainName, - 'chain-config': chainConfig, - 'rollup': { - 'bridge': coreContracts.bridge, - 'inbox': coreContracts.inbox, - 'sequencer-inbox': coreContracts.sequencerInbox, - 'rollup': coreContracts.rollup, - 'validator-utils': coreContracts.validatorUtils, - 'validator-wallet-creator': coreContracts.validatorWalletCreator, - 'deployed-at': coreContracts.deployedAtBlockNumber, + "chain-id": chainConfig.chainId, + "parent-chain-id": parentChainId, + "parent-chain-is-arbitrum": parentChainIsArbitrum(parentChainId), + "chain-name": chainName, + "chain-config": chainConfig, + rollup: { + bridge: coreContracts.bridge, + inbox: coreContracts.inbox, + "sequencer-inbox": coreContracts.sequencerInbox, + rollup: coreContracts.rollup, + "validator-utils": coreContracts.validatorUtils, + "validator-wallet-creator": coreContracts.validatorWalletCreator, + "deployed-at": coreContracts.deployedAtBlockNumber, }, }, ]), - 'name': chainName, + name: chainName, }, - 'parent-chain': { + "parent-chain": { connection: { url: parentChainRpcUrl, }, }, - 'http': { - addr: '0.0.0.0', + http: { + addr: "0.0.0.0", port: 8449, - vhosts: '*', - corsdomain: '*', - api: ['eth', 'net', 'web3', 'arb', 'debug'], + vhosts: "*", + corsdomain: "*", + api: ["eth", "net", "web3", "arb", "debug"], }, - 'node': { - 'forwarding-target': '', - 'sequencer': { - 'max-tx-data-size': 85000, - 'enable': true, - 'dangerous': { - 'no-coordinator': true, + node: { + "forwarding-target": "", + sequencer: { + "max-tx-data-size": 85000, + enable: true, + dangerous: { + "no-coordinator": true, }, - 'max-block-speed': '250ms', + "max-block-speed": "250ms", }, - 'delayed-sequencer': { + "delayed-sequencer": { enable: true, }, - 'batch-poster': { - 'max-size': 90000, - 'enable': true, - 'parent-chain-wallet': { - 'private-key': sanitizePrivateKey(batchPosterPrivateKey), + "batch-poster": { + "max-size": 90000, + enable: true, + "parent-chain-wallet": { + "private-key": sanitizePrivateKey(batchPosterPrivateKey), }, }, - 'staker': { - 'enable': true, - 'strategy': 'MakeNodes', - 'parent-chain-wallet': { - 'private-key': sanitizePrivateKey(validatorPrivateKey), + staker: { + enable: true, + strategy: "MakeNodes", + "parent-chain-wallet": { + "private-key": sanitizePrivateKey(validatorPrivateKey), }, }, - 'caching': { + caching: { archive: true, }, }, }; if (chainConfig.arbitrum.DataAvailabilityCommittee) { - config.node['data-availability'] = { - 'enable': true, - 'sequencer-inbox-address': coreContracts.sequencerInbox, - 'parent-chain-node-url': parentChainRpcUrl, - 'rest-aggregator': { + config.node["data-availability"] = { + enable: true, + "sequencer-inbox-address": coreContracts.sequencerInbox, + "parent-chain-node-url": parentChainRpcUrl, + "rest-aggregator": { enable: true, - urls: 'http://localhost:9876', + urls: "http://localhost:9876", }, - 'rpc-aggregator': { - 'enable': true, - 'assumed-honest': 1, - 'backends': stringifyBackendsJson([ + "rpc-aggregator": { + enable: true, + "assumed-honest": 1, + backends: stringifyBackendsJson([ { - url: 'http://localhost:9876', + url: "http://localhost:9876", pubkey: - 'YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==', + "YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", signermask: 1, }, ]),