How to Deploy an Orbit chain using the Orbit SDK
This document explains how to use the Orbit SDK to deploy a Orbit chain
.
This document is under construction and may change significantly as we incorporate style guidance and feedback from readers. Feel free to request specific clarifications by clicking the Request an update
button at the top of this document.
The Arbitrum Orbit SDK lets you programmatically create and manage your own Orbit chain(s)
. Its capabilities include:
- Configuration and deployment of your Orbit chain's core contracts
- Initialization of your chain and management of its configuration post-deployment
Select a chain type
There are three types of Orbit chains. Select the chain type that best fits your needs:
- Chain type:
- Rollup chain
- AnyTrust chain
- Custom token chain
- Rollup chains offer Ethereum-grade security by batching, compressing, and posting data to the parent chain, similarly to Arbitrum One.
Use case: Ideal for applications that require high security guarantees.
Prepare your Rollup Orbit chain configuration object parameters
prepareChainConfig API:
For an easier config preparation, the Orbit SDK provides the prepareChainConfig
API, which takes config parameters as arguments and returns a chainConfig
JSON
string. Any parameters not provided will default to standard values, which are detailed in the Orbit SDK repository.
Here are the parameters you can use with prepareChainConfig
:
Parameter | Description |
---|---|
chainId | Your Orbit chain's unique identifier. It differentiates your chain from others in the ecosystem. |
DataAvailabilityCommittee | Set to false , this boolean makes your chain as a Rollup, set to true configures it as an AnyTrust chain. |
InitialChainOwner | Identifies who owns and controls the chain. |
MaxCodeSize | Sets the maximum size for contract bytecodes on the Orbit chain. e.g. Ethereum mainnet has a limit of 24,576 Bytes. |
MaxInitCodeSize | Similar to MaxCodeSize , defines the maximum size for your Orbit chain's initialization code. e.g. Ethereum mainnet limit is 49,152 Bytes. |
Below is an example of how to use prepareChainConfig
to set up a Rollup chain with a specific chainId
, an InitialChainOwner
(named as deployer_address
):
import { prepareChainConfig } from '@arbitrum/orbit-sdk';
const chainConfig = prepareChainConfig({
chainId: Some_Chain_ID,
arbitrum: { InitialChainOwner: deployer_address, DataAvailabilityCommittee: false },
});
createRollupPrepareConfig API:
This API is designed to take parameters defined in the Config struct and fill in the rest with default values. It outputs a complete Config struct that is ready for use.
For example, to create a Config struct with a specific chain ID (chainId
), an owner address (deployer_address
), and a chainConfig
as described in the previous section, you would use the Orbit SDK as follows:
import { createRollupPrepareConfig } from '@arbitrum/orbit-sdk';
const config = createRollupPrepareConfig({
chainId: BigInt(chainId),
owner: deployer.address,
chainConfig,
});
Deploy your Orbit chain
Orbit SDK provides the createRollupPrepareTransactionRequest
helper to prepare your transaction:
createRollupPrepareTransactionRequest API:
This API accepts parameters defined in the RollupDeploymentParams
struct, applying defaults where necessary, and generates the RollupDeploymentParams
. This struct is then used to create a raw transaction which calls the createRollup
function of the RollupCreator
contract. As discussed in previous sections, this function deploys and initializes all core Orbit contracts.
For instance, to deploy using the Orbit SDK with a Config equal to config
, a batchPoster
, and a set of validators such as [validator]
, the process would look like this:
import { createRollupPrepareTransactionRequest } from '@arbitrum/orbit-sdk';
const request = await createRollupPrepareTransactionRequest({
params: {
config,
batchPoster,
validators: [validator],
},
account: deployer_address,
publicClient,
});
After creating the raw transaction, you need to sign and broadcast it to the network, as shown in the create-rollup-eth
example.
Get the orbit chain information after deployment
Once you've successfully deployed your Orbit chain, the next step is to retrieve detailed information about the deployment. The Orbit SDK provides a convenient way to do this through the createRollupPrepareTransactionReceipt
API.
After sending the signed transaction and receiving the transaction receipt, you can use the createRollupPrepareTransactionReceipt
API to parse this receipt and extract the relevant data. This process will provide comprehensive details about the deployed chain, such as contract addresses, configuration settings, and other information.
Here's an example of how to use the Orbit SDK to get data from a deployed Orbit chain:
import { createRollupPrepareTransactionReceipt } from '@arbitrum/orbit-sdk';
const data = createRollupPrepareTransactionReceipt(txReceipt);
In this example, txReceipt
refers to the transaction receipt you received after deploying the chain. By passing this receipt to the createRollupPrepareTransactionReceipt
function, you can easily access a wealth of information about your Orbit chain. This feature of the Orbit SDK simplifies the post-deployment process, allowing you to quickly and efficiently gather all necessary details about your chain for further use or reference.
Configure a Node running your Rollup Orbit chain
Once you have successfully deployed and initialized the Orbit core contracts, the next step is configuring and running your Orbit chain using a Node Config JSON
file describing all the configurations for the Arbitrum Node, including settings for the Batch-poster, Validator, and the chain itself.
Example for a Rollup Orbit Chain:
{
'chain': {
'info-json': stringifyInfoJson([...]),
'name': chainName,
// Additional chain-specific configurations
},
'parent-chain': {
connection: {
url: parentChainRpcUrl,
},
},
'http': {
addr: '0.0.0.0',
port: 8449,
vhosts: '*',
corsdomain: '*',
api: ['eth', 'net', 'web3', 'arb', 'debug'],
},
'node': {
// Node-specific settings including sequencer, batch-poster, staker configurations
},
};
Here are some inputs details from the example above:
Parameters | Description |
---|---|
chain | Details about the hosted chain, including chain ID, name, and core contracts. |
parent-chain | Information for connecting to the parent chain. |
http | Configuration parameters for the HTTP server. |
node | Specific node settings, including sequencer and batch-poster configurations. |
Preparing your node config file
The Node Config file includes three fields types:
- Information from the Orbit deployment chain: Such as the addresses of the core contracts.
- Parameters configurable by the chain deployer: These parameters, like
max-block-speed
, can be adjusted to modify your chain's behavior. - Fields not typically configured: Like the HTTP section, which usually remains standard.
Let's explore the parameters allowing you to set up a stable, and secure Orbit chain tailored to your project's requirements:
Node config generation with Orbit SDK
Generating a Node Config JSON
file to initiate your Orbit chain is a step in the deployment process. The Orbit SDK simplifies this task with an API named prepareNodeConfig
. This API takes specific parameters for your Orbit chain and returns a JSON
file that can be used as the Node Config to initiate the chain.
Here’s an example of using the prepareNodeConfig
API to generate the node config:
const nodeConfig = prepareNodeConfig({
chainName: 'My Orbit Chain',
chainConfig,
coreContracts,
batchPosterPrivateKey: 'BATCH_POSTER_PRIVATE_KEY_HERE',
validatorPrivateKey: 'VALIDATOR_PRIVATE_KEY_HERE',
parentChainId: parentChain_chain_id,
parentChainRpcUrl: parentChain_RPC_URL,
});
Here are some details about the parameters used in the example above:
Parameters | Description |
---|---|
chainName | The name you have chosen for your Orbit chain. |
chainConfig | Configuration used for chain deployment, returned from the createRollupPrepareTransactionReceipt API. |
coreContracts | Addresses of your newly deployed Orbit chain's, also returned from the createRollupPrepareTransactionReceipt API. |
batchPosterPrivateKey | Private key of the batch-poster account, used for signing batch-posting transactions and related functions. |
validatorPrivateKey | Private key of the validator(s), used for validating state, posting Rollup Blocks (RBlocks ) to the parent chain, and initiating challenges if necessary. |
parentChainId | Chain ID of the parent chain where your Orbit chain is deployed. |
parentChainRpcUrl | Parent chain's RPC URL. |
If you don't have the chainConfig
and coreContracts
readily available, you can obtain them using the createRollupPrepareTransaction
and createRollupPrepareTransactionReceipt
APIs.
Here's an example of how to extract chainConfig
and coreContracts
using just the transaction hash from your deployment:
import {
ChainConfig,
createRollupPrepareTransaction,
createRollupPrepareTransactionReceipt,
} from '@arbitrum/orbit-sdk';
const tx = createRollupPrepareTransaction({ hash: txHash });
const txReceipt = createRollupPrepareTransactionReceipt({ hash: txHash });
const chainConfig: ChainConfig = JSON.parse(tx.getInputs()[0].config.chainConfig);
const coreContracts = txReceipt.getCoreContracts();
This process ensures that all necessary configurations and contract details are included in your Node Config.
Deploy a token bridge
The Arbitrum Nitro stack doesn't natively support specific token bridging standards at the protocol level. Instead, Offchain Labs designed a "canonical bridge" that ensures seamless token transfers between the parent and child chains.
The token bridge architecture includes contracts deployed on the parent chain and on your Orbit chain.These entities communicate via the Retryable Ticket protocol, ensuring efficient and secure interactions.
Token bridge deployment steps
Once an Orbit chain has been deployed and initialized, the bridge contracts need to be deployed on both the parent and child chains. This process involves several steps:
- Token bridge contract deployment
- Transaction recipient and checking for deployment on child chain
- Deployment information and contract addresses
- Setting up the WETH gateway
1. Token bridge contract deployment
Deploying token bridge contracts is the first step in creating a bridge between the parent and the Orbit chain.
The deployment process is the same as Orbit chain contracts', where a primary contract facilitates the deployment of core contracts. The token bridge contracts are deployed on the parent and child chains by TokenBridgeCreator
. TokenBridgeCreator
does it in a single transaction using the Retryable Tickets protocol .
Orbit SDK provides an API that automates the deployment by interacting with the TokenBridgeCreator
contract. The API is createTokenBridgePrepareTransactionRequest
, which processes the necessary inputs and generates a transaction request tailored for token bridge deployment.
Example:
const txRequest = await createTokenBridgePrepareTransactionRequest({
params: {
rollup: rollupContractAddress,
rollupOwner: rollupOwnerAddress,
},
parentChainPublicClient,
orbitChainPublicClient,
account: rollupOwnerAddress,
});
Here are the parameters used in the above example:
Parameter | Description |
---|---|
rollupContractAddress | Orbit chain's Rollup contract address. |
rollupOwnerAddress | Rollup owner's address. |
parentChainPublicClient | Parent chain's public client, as defined by Viem. |
orbitChainPublicClient | Orbit chain's public client, as defined by Viem. |
For more insights into these variables and their usage, consider exploring this token bridge deployment example.
Following the creation of the raw transaction, the next steps involve signing it and broadcasting it to the relevant blockchain network to complete the deployment process.
2. Transaction recipient and checking for deployment on child chain
After sending the deployment transaction, you will need to retrieve the transaction receipt and verify the successful deployment of the contracts on both the parent and child chains.
Our Orbit SDK includes a dedicated API for this purpose, named createTokenBridgePrepareTransactionReceipt
, which simplifies the process of obtaining the deployment transaction's recipient.
Example:
const txReceipt = createTokenBridgePrepareTransactionReceipt(
await parentChainPublicClient.waitForTransactionReceipt({ hash: txHash }),
);
In this scenario, txHash
represents the hash of the deployment transaction initiated in the previous step. The waitForTransactionReceipt
API from Viem captures the transaction's recipient on the parent chain. The createTokenBridgePrepareTransactionReceipt
API enhances the basic functionality provided by Viem's waitForTransactionReceipt
, introducing a specialized method named waitForRetryables
to handle the outcome (in this case, txReceipt
).
By employing the waitForRetryables
method, you can ensure the success of Retryable Tickets on the parent chain.
Example:
const orbitChainRetryableReceipts = await txReceipt.waitForRetryables({
orbitPublicClient: orbitChainPublicClient,
});
if (orbitChainRetryableReceipts[0].status !== 'success') {
throw new Error(
`Retryable status is not success: ${orbitChainRetryableReceipts[0].status}. Aborting...`,
);
}
console.log(`Retryable executed successfully`);
In this example, the waitForRetryables
method is invoked on the txReceipt
to monitor the execution of Retryable Tickets and verify their status. A success
status indicates that the Retryable Tickets have been executed successfully, ensuring the contracts' deployment. It's important to note that this process involves two Retryable Tickets. You can check out a more comprehensive walkthrough of the example. This enhanced approach not only simplifies the retrieval of transaction receipts but also provides a reliable method for verifying contract deployment across chains.
3. Deployment information and contract addresses
Once you have completed the deployment and are assured that the Retryable Tickets are successful, you can use getTokenBridgeContracts
to retrieve the deployment information and all the token bridge contracts' addresses.
Here's an example of how to get the contract addresses from the txReceipt
generated in the previous steps:
const tokenBridgeContracts = await txReceipt.getTokenBridgeContracts({
parentChainPublicClient,
});
4. Setting up the WETH gateway
The last step in spinning up the token bridge for an ETH
- based Orbit chain is setting up the WETH
Gateway.
That step only applies to ETH
-based Orbit chains, not Custom fee token orbit chains. Our canonical bridge design has a separate custom gateway for WETH
to bridge it in and out of the Orbit chain.
You can find more info about WETH
gateways in our "other gateways flavors" documentation.
So, after the token bridge has been deployed and you have secured a successful deployment on both parent and child chains, it's time to set the WETH
gateway on both parent and child chains. To handle that, we have two APIs on our Orbit SDK:
1. createTokenBridgePrepareSetWethGatewayTransactionRequest
:
This API helps you create the raw transaction which handles the WETH
gateway on both parent and child chains.
Example:
const setWethGatewayTxRequest = await createTokenBridgePrepareSetWethGatewayTransactionRequest({
rollup: rollupContractAddress,
parentChainPublicClient,
orbitChainPublicClient,
account: rollupOwnerAddress,
retryableGasOverrides: {
gasLimit: {
percentIncrease: 200n,
},
},
});
In this example, rollupContractAddress
is the address of Orbit chain's Rollup contract, and rollupOwnerAddress
is the address of the Rollup owner. parentChainPublicClient and orbitChainPublicClient are the public clients of the parent and orbit chains. This API also has optional fields to override the Retryable ticket setups. In this example, percentIncrease is the buffer to increase the gas limit, thus securing successful retryable tickets.
After creating the raw transaction, you need to use Viem to sign it and broadcast it to the network.
2. createTokenBridgePrepareSetWethGatewayTransactionReceipt
After sending the transaction, you need to assess if the Retryable Tickets you just created have been successful. To do that we are using createTokenBridgePrepareSetWethGatewayTransactionReceipt
API and thewaitForRetryables
method of it to check for the success status of retryable tickets. For the example in this doc we can use this API as follow:
const setWethGatewayTxReceipt = createTokenBridgePrepareSetWethGatewayTransactionReceipt(
await parentChainPublicClient.waitForTransactionReceipt({
hash: setWethGatewayTxHash,
}),
);
const orbitChainSetWethGatewayRetryableReceipt = await setWethGatewayTxReceipt.waitForRetryables({
orbitPublicClient: orbitChainPublicClient,
});
if (orbitChainSetWethGatewayRetryableReceipt[0].status !== 'success') {
throw new Error(
`Retryable status is not success: ${orbitChainSetWethGatewayRetryableReceipt[0].status}. Aborting...`,
);
}
console.log(`Retryables executed successfully`);
In this example setWethGatewayTxHash
is the hash of the transaction you sent, setting the WETH
gateway on your Orbit chain.
- Implements the AnyTrust protocol, relying on an external Data Availability Committee (DAC) to store data and provide it on-demand instead of using their parent chain as the Data Availability (DA) layer.
- Use case: Suitable for applications that require lower transaction fees.
Prepare your Orbit chain configuration object parameters
prepareChainConfig API:
For an easier config preparation, the Orbit SDK provides the prepareChainConfig
API, which takes config parameters as arguments and returns a chainConfig
JSON
string. Any parameters not provided will default to standard values, which are detailed in the Orbit SDK repository.
The chainConfig
parameter within the Config
structure is an essential element for tailoring your Orbit chain according to specific needs. This parameter is particularly significant when setting up an AnyTrust Orbit chain, as it includes configurations that distinguish it from a Rollup chain. The key parameter that differentiates an AnyTrust chain in this context is the DataAvailabilityCommittee
.
Here are the parameters you can use with prepareChainConfig
:
Parameter | Description |
---|---|
chainId | Your Orbit chain's unique identifier. It differentiates your chain from others in the ecosystem. |
DataAvailabilityCommittee | Set to false , this boolean makes your chain as a Rollup, set to true configures it as an AnyTrust chain. |
InitialChainOwner | Identifies who owns and controls the chain. |
MaxCodeSize | Sets the maximum size for contract bytecodes on the Orbit chain. e.g. Ethereum mainnet has a limit of 24,576 Bytes. |
MaxInitCodeSize | Similar to MaxCodeSize , defines the maximum size for your Orbit chain's initialization code. e.g. Ethereum mainnet limit is 49,152 Bytes. |
For an AnyTrust chain, you need to set the DataAvailabilityCommittee
to true. This setting is crucial as it indicates the chain's reliance on a committee for data availability, which is a hallmark of the AnyTrust model.
Here’s an example of how to configure the chainConfig
for an AnyTrust chain using the Orbit SDK:
import { prepareChainConfig } from '@arbitrum/orbit-sdk';
const chainConfig = prepareChainConfig({
chainId: Some_Chain_ID,
arbitrum: { InitialChainOwner: deployer_address, DataAvailabilityCommittee: true },
});
In this example, you set up the chain configuration with a specific chainId
, the InitialChainOwner
as the deployer's address, and importantly, you configure the DataAvailabilityCommittee
as true
. This configuration ensures that your Orbit chain is set up as an AnyTrust chain, utilizing the unique features and operational model of the AnyTrust system within the Arbitrum Orbit framework.
createRollupPrepareConfig API:
This API is designed to take parameters defined in the Config struct and fill in the rest with default values. It outputs a complete Config struct that is ready for use.
For example, to create a Config struct with a specific chain ID (chainId
), an owner address (deployer_address
), and a chainConfig
as described in the previous section, you would use the Orbit SDK as follows:
import { createRollupPrepareConfig } from '@arbitrum/orbit-sdk';
const config = createRollupPrepareConfig({
chainId: BigInt(chainId),
owner: deployer.address,
chainConfig,
});
Deploy your Orbit chain
Orbit SDK provides the createRollupPrepareTransactionRequest
helper to prepare your transaction:
createRollupPrepareTransactionRequest API:
This API accepts parameters defined in the RollupDeploymentParams
struct, applying defaults where necessary, and generates the RollupDeploymentParams
. This struct is then used to create a raw transaction which calls the createRollup
function of the RollupCreator
contract. As discussed in previous sections, this function deploys and initializes all core Orbit contracts.
For instance, to deploy using the Orbit SDK with a Config equal to config
, a batchPoster
, and a set of validators such as [validator]
, the process would look like this:
import { createRollupPrepareTransactionRequest } from '@arbitrum/orbit-sdk';
const request = await createRollupPrepareTransactionRequest({
params: {
config,
batchPoster,
validators: [validator],
},
account: deployer_address,
publicClient,
});
After creating the raw transaction, you need to sign and broadcast it to the network, as shown in the create-rollup-eth
example.
Get the orbit chain information after deployment
Once you've successfully deployed your Orbit chain, the next step is to retrieve detailed information about the deployment. The Orbit SDK provides a convenient way to do this through the createRollupPrepareTransactionReceipt
API.
After sending the signed transaction and receiving the transaction receipt, you can use the createRollupPrepareTransactionReceipt
API to parse this receipt and extract the relevant data. This process will provide comprehensive details about the deployed chain, such as contract addresses, configuration settings, and other information.
Here's an example of how to use the Orbit SDK to get data from a deployed Orbit chain:
import { createRollupPrepareTransactionReceipt } from '@arbitrum/orbit-sdk';
const data = createRollupPrepareTransactionReceipt(txReceipt);
In this example, txReceipt
refers to the transaction receipt you received after deploying the chain. By passing this receipt to the createRollupPrepareTransactionReceipt
function, you can easily access a wealth of information about your Orbit chain. This feature of the Orbit SDK simplifies the post-deployment process, allowing you to quickly and efficiently gather all necessary details about your chain for further use or reference.
Set valid keyset on parent chain
The final step in deploying your AnyTrust Orbit chain is to set up the valid keyset for your Data Availability Committee (DAC) on the parent chain. This keyset is essential for ensuring the integrity of the certificates that the DAC signs when storing Orbit chain's data. The process of generating keys and the keyset for your committee is comprehensively explained in our documentation. Once you have your keyset, it needs to be established on the SequencerInbox
contract of your Orbit chain on the parent chain.
To facilitate this, we provide an API in Orbit SDK named setValidKeysetPrepareTransactionRequest
. This API aids in setting the keyset on the parent chain. To use this API, you need specific information that you gathered in step 3. This includes the upgradeExecutor
and sequencerInbox
addresses of your Orbit chain, the generated keyset for your committee, and the account of the owner.
Here's an example of how you can use the Orbit SDK to set the keyset:
const txRequest = await setValidKeysetPrepareTransactionRequest({
coreContracts: {
upgradeExecutor: 'upgradeExecutor_address',
sequencerInbox: 'sequencerInbox_address',
},
keyset,
account: deployer.address,
publicClient: parentChainPublicClient,
});
In this example, upgradeExecutor_address
and sequencerInbox_address
are placeholders for the actual addresses of the respective contracts in your Orbit chain. keyset
is the keyset you generated for your committee, and deployer.address
refers to the owner's account address.
After you create the transaction request using the above API, the next step is to sign and send the transaction. This action will effectively set the keyset on the parent chain, allowing it to recognize and verify the valid keyset for your AnyTrust Orbit chain. This step is crucial for the operational integrity and security of your AnyTrust chain, ensuring that the data verified by the DAC is recognized and accepted by the parent chain.
Configure a Node running your AnyTrust Orbit chain
Once you have successfully deployed and initialized the Orbit core contracts, the next step is configuring and running your Orbit chain using a Node Config JSON
file describing all the configurations for the Arbitrum Node, including settings for the Batch-poster, Validator, and the chain itself.
Example for a Rollup Orbit Chain:
{
'chain': {
'info-json': stringifyInfoJson([...]),
'name': chainName,
// Additional chain-specific configurations
},
'parent-chain': {
connection: {
url: parentChainRpcUrl,
},
},
'http': {
addr: '0.0.0.0',
port: 8449,
vhosts: '*',
corsdomain: '*',
api: ['eth', 'net', 'web3', 'arb', 'debug'],
},
'node': {
// Node-specific settings including sequencer, batch-poster, staker configurations
},
};
Here are some inputs details from the example above:
Parameters | Description |
---|---|
chain | Details about the hosted chain, including chain ID, name, and core contracts. |
parent-chain | Information for connecting to the parent chain. |
http | Configuration parameters for the HTTP server. |
node | Specific node settings, including sequencer and batch-poster configurations. |
Additional configuration for AnyTrust Orbit chains:
For AnyTrust Orbit chains, the Node Config JSON
has an additional segment under the node
field. This addition includes settings specific to the AnyTrust model, such as:
- Sequencer's inbox address
- Parent chain node URL
- RPC aggregators
Example addition for AnyTrust Node Config:
{
...
'node': {
...
'sequencer-inbox-address': coreContracts.sequencerInbox,
'parent-chain-node-url': parentChainRpcUrl,
'rest-aggregator': {
enable: true,
urls: 'http://localhost:9876',
},
'rpc-aggregator': {
'enable': true,
'assumed-honest': 1,
'backends': stringifyBackendsJson([...]),
},
}
...
};
Preparing your node config file
The Node Config file includes three fields types:
- Information from the Orbit deployment chain: Such as the addresses of the core contracts.
- Parameters configurable by the chain deployer: These parameters, like
max-block-speed
, can be adjusted to modify your chain's behavior. - Fields not typically configured: Like the HTTP section, which usually remains standard.
Let's explore the parameters allowing you to set up a stable, and secure Orbit chain tailored to your project's requirements:
Node config generation with Orbit SDK
Generating a Node Config JSON
file to initiate your Orbit chain is a step in the deployment process. The Orbit SDK simplifies this task with an API named prepareNodeConfig
. This API takes specific parameters for your Orbit chain and returns a JSON
file that can be used as the Node Config to initiate the chain.
Here’s an example of using the prepareNodeConfig
API to generate the node config:
const nodeConfig = prepareNodeConfig({
chainName: 'My Orbit Chain',
chainConfig,
coreContracts,
batchPosterPrivateKey: 'BATCH_POSTER_PRIVATE_KEY_HERE',
validatorPrivateKey: 'VALIDATOR_PRIVATE_KEY_HERE',
parentChainId: parentChain_chain_id,
parentChainRpcUrl: parentChain_RPC_URL,
});
Here are some details about the parameters used in the example above:
Parameters | Description |
---|---|
chainName | The name you have chosen for your Orbit chain. |
chainConfig | Configuration used for chain deployment, returned from the createRollupPrepareTransactionReceipt API. |
coreContracts | Addresses of your newly deployed Orbit chain's, also returned from the createRollupPrepareTransactionReceipt API. |
batchPosterPrivateKey | Private key of the batch-poster account, used for signing batch-posting transactions and related functions. |
validatorPrivateKey | Private key of the validator(s), used for validating state, posting Rollup Blocks (RBlocks ) to the parent chain, and initiating challenges if necessary. |
parentChainId | Chain ID of the parent chain where your Orbit chain is deployed. |
parentChainRpcUrl | Parent chain's RPC URL. |
If you don't have the chainConfig
and coreContracts
readily available, you can obtain them using the createRollupPrepareTransaction
and createRollupPrepareTransactionReceipt
APIs.
Here's an example of how to extract chainConfig
and coreContracts
using just the transaction hash from your deployment:
import {
ChainConfig,
createRollupPrepareTransaction,
createRollupPrepareTransactionReceipt,
} from '@arbitrum/orbit-sdk';
const tx = createRollupPrepareTransaction({ hash: txHash });
const txReceipt = createRollupPrepareTransactionReceipt({ hash: txHash });
const chainConfig: ChainConfig = JSON.parse(tx.getInputs()[0].config.chainConfig);
const coreContracts = txReceipt.getCoreContracts();
This process ensures that all necessary configurations and contract details are included in your Node Config.
Deploy a token bridge
The Arbitrum Nitro stack doesn't natively support specific token bridging standards at the protocol level. Instead, Offchain Labs designed a "canonical bridge" that ensures seamless token transfers between the parent and child chains.
The token bridge architecture includes contracts deployed on the parent chain and on your Orbit chain.These entities communicate via the Retryable Ticket protocol, ensuring efficient and secure interactions.
Token bridge deployment steps
Once an Orbit chain has been deployed and initialized, the bridge contracts need to be deployed on both the parent and child chains. This process involves several steps:
- Token bridge contract deployment
- Transaction recipient and checking for deployment on child chain
- Deployment information and contract addresses
- Setting up the WETH gateway
1. Token bridge contract deployment
Deploying token bridge contracts is the first step in creating a bridge between the parent and the Orbit chain.
The deployment process is the same as Orbit chain contracts', where a primary contract facilitates the deployment of core contracts. The token bridge contracts are deployed on the parent and child chains by TokenBridgeCreator
. TokenBridgeCreator
does it in a single transaction using the Retryable Tickets protocol .
Orbit SDK provides an API that automates the deployment by interacting with the TokenBridgeCreator
contract. The API is createTokenBridgePrepareTransactionRequest
, which processes the necessary inputs and generates a transaction request tailored for token bridge deployment.
Example:
const txRequest = await createTokenBridgePrepareTransactionRequest({
params: {
rollup: rollupContractAddress,
rollupOwner: rollupOwnerAddress,
},
parentChainPublicClient,
orbitChainPublicClient,
account: rollupOwnerAddress,
});
Here are the parameters used in the above example:
Parameter | Description |
---|---|
rollupContractAddress | Orbit chain's Rollup contract address. |
rollupOwnerAddress | Rollup owner's address. |
parentChainPublicClient | Parent chain's public client, as defined by Viem. |
orbitChainPublicClient | Orbit chain's public client, as defined by Viem. |
For more insights into these variables and their usage, consider exploring this token bridge deployment example.
Following the creation of the raw transaction, the next steps involve signing it and broadcasting it to the relevant blockchain network to complete the deployment process.
2. Transaction recipient and checking for deployment on child chain
After sending the deployment transaction, you will need to retrieve the transaction receipt and verify the successful deployment of the contracts on both the parent and child chains.
Our Orbit SDK includes a dedicated API for this purpose, named createTokenBridgePrepareTransactionReceipt
, which simplifies the process of obtaining the deployment transaction's recipient.
Example:
const txReceipt = createTokenBridgePrepareTransactionReceipt(
await parentChainPublicClient.waitForTransactionReceipt({ hash: txHash }),
);
In this scenario, txHash
represents the hash of the deployment transaction initiated in the previous step. The waitForTransactionReceipt
API from Viem captures the transaction's recipient on the parent chain. The createTokenBridgePrepareTransactionReceipt
API enhances the basic functionality provided by Viem's waitForTransactionReceipt
, introducing a specialized method named waitForRetryables
to handle the outcome (in this case, txReceipt
).
By employing the waitForRetryables
method, you can ensure the success of Retryable Tickets on the parent chain.
Example:
const orbitChainRetryableReceipts = await txReceipt.waitForRetryables({
orbitPublicClient: orbitChainPublicClient,
});
if (orbitChainRetryableReceipts[0].status !== 'success') {
throw new Error(
`Retryable status is not success: ${orbitChainRetryableReceipts[0].status}. Aborting...`,
);
}
console.log(`Retryable executed successfully`);
In this example, the waitForRetryables
method is invoked on the txReceipt
to monitor the execution of Retryable Tickets and verify their status. A success
status indicates that the Retryable Tickets have been executed successfully, ensuring the contracts' deployment. It's important to note that this process involves two Retryable Tickets. You can check out a more comprehensive walkthrough of the example. This enhanced approach not only simplifies the retrieval of transaction receipts but also provides a reliable method for verifying contract deployment across chains.
3. Deployment information and contract addresses
Once you have completed the deployment and are assured that the Retryable Tickets are successful, you can use getTokenBridgeContracts
to retrieve the deployment information and all the token bridge contracts' addresses.
Here's an example of how to get the contract addresses from the txReceipt
generated in the previous steps:
const tokenBridgeContracts = await txReceipt.getTokenBridgeContracts({
parentChainPublicClient,
});
4. Setting up the WETH gateway
The last step in spinning up the token bridge for an ETH
- based Orbit chain is setting up the WETH
Gateway.
That step only applies to ETH
-based Orbit chains, not Custom fee token orbit chains. Our canonical bridge design has a separate custom gateway for WETH
to bridge it in and out of the Orbit chain.
You can find more info about WETH
gateways in our "other gateways flavors" documentation.
So, after the token bridge has been deployed and you have secured a successful deployment on both parent and child chains, it's time to set the WETH
gateway on both parent and child chains. To handle that, we have two APIs on our Orbit SDK:
1. createTokenBridgePrepareSetWethGatewayTransactionRequest
:
This API helps you create the raw transaction which handles the WETH
gateway on both parent and child chains.
Example:
const setWethGatewayTxRequest = await createTokenBridgePrepareSetWethGatewayTransactionRequest({
rollup: rollupContractAddress,
parentChainPublicClient,
orbitChainPublicClient,
account: rollupOwnerAddress,
retryableGasOverrides: {
gasLimit: {
percentIncrease: 200n,
},
},
});
In this example, rollupContractAddress
is the address of Orbit chain's Rollup contract, and rollupOwnerAddress
is the address of the Rollup owner. parentChainPublicClient and orbitChainPublicClient are the public clients of the parent and orbit chains. This API also has optional fields to override the Retryable ticket setups. In this example, percentIncrease is the buffer to increase the gas limit, thus securing successful retryable tickets.
After creating the raw transaction, you need to use Viem to sign it and broadcast it to the network.
2. createTokenBridgePrepareSetWethGatewayTransactionReceipt
After sending the transaction, you need to assess if the Retryable Tickets you just created have been successful. To do that we are using createTokenBridgePrepareSetWethGatewayTransactionReceipt
API and thewaitForRetryables
method of it to check for the success status of retryable tickets. For the example in this doc we can use this API as follow:
const setWethGatewayTxReceipt = createTokenBridgePrepareSetWethGatewayTransactionReceipt(
await parentChainPublicClient.waitForTransactionReceipt({
hash: setWethGatewayTxHash,
}),
);
const orbitChainSetWethGatewayRetryableReceipt = await setWethGatewayTxReceipt.waitForRetryables({
orbitPublicClient: orbitChainPublicClient,
});
if (orbitChainSetWethGatewayRetryableReceipt[0].status !== 'success') {
throw new Error(
`Retryable status is not success: ${orbitChainSetWethGatewayRetryableReceipt[0].status}. Aborting...`,
);
}
console.log(`Retryables executed successfully`);
In this example setWethGatewayTxHash
is the hash of the transaction you sent, setting the WETH
gateway on your Orbit chain.
- An AnyTrust Orbit chain with the ability to specify a custom
ERC-20
gas token. - Use case: Ideal for applications that require custom gas fee tokens and lower transaction fees.
Prepare your Orbit chain configuration object parameters
prepareChainConfig API:
For an easier config preparation, the Orbit SDK provides the prepareChainConfig
API, which takes config parameters as arguments and returns a chainConfig
JSON
string. Any parameters not provided will default to standard values, which are detailed in the Orbit SDK repository.
The chainConfig
parameter within the Config
structure is an essential element for tailoring your Orbit chain according to specific needs. This parameter is particularly significant when setting up an AnyTrust Orbit chain, as it includes configurations that distinguish it from a Rollup chain. The key parameter that differentiates an AnyTrust chain in this context is the DataAvailabilityCommittee
.
Here are the parameters you can use with prepareChainConfig
:
Parameter | Description |
---|---|
chainId | Your Orbit chain's unique identifier. It differentiates your chain from others in the ecosystem. |
DataAvailabilityCommittee | Set to false , this boolean makes your chain as a Rollup, set to true configures it as an AnyTrust chain. |
InitialChainOwner | Identifies who owns and controls the chain. |
MaxCodeSize | Sets the maximum size for contract bytecodes on the Orbit chain. e.g. Ethereum mainnet has a limit of 24,576 Bytes. |
MaxInitCodeSize | Similar to MaxCodeSize , defines the maximum size for your Orbit chain's initialization code. e.g. Ethereum mainnet limit is 49,152 Bytes. |
For an AnyTrust chain, you need to set the DataAvailabilityCommittee
to true. This setting is crucial as it indicates the chain's reliance on a committee for data availability, which is a hallmark of the AnyTrust model.
Here’s an example of how to configure the chainConfig
for an AnyTrust chain using the Orbit SDK:
import { prepareChainConfig } from '@arbitrum/orbit-sdk';
const chainConfig = prepareChainConfig({
chainId: Some_Chain_ID,
arbitrum: { InitialChainOwner: deployer_address, DataAvailabilityCommittee: true },
});
In this example, you set up the chain configuration with a specific chainId
, the InitialChainOwner
as the deployer's address, and importantly, you configure the DataAvailabilityCommittee
as true
. This configuration ensures that your Orbit chain is set up as an AnyTrust chain, utilizing the unique features and operational model of the AnyTrust system within the Arbitrum Orbit framework.
createRollupPrepareConfig API:
This API is designed to take parameters defined in the Config struct and fill in the rest with default values. It outputs a complete Config struct that is ready for use.
For example, to create a Config struct with a specific chain ID (chainId
), an owner address (deployer_address
), and a chainConfig
as described in the previous section, you would use the Orbit SDK as follows:
import { createRollupPrepareConfig } from '@arbitrum/orbit-sdk';
const config = createRollupPrepareConfig({
chainId: BigInt(chainId),
owner: deployer.address,
chainConfig,
});
Approve ERC-20 token
Initiating the deployment of a token bridge for Custom Fee Token on orbit chains begins with ensuring the TokenBridgeCreator
contract is granted sufficient approvals of the native token. To facilitate this process, the Orbit SDK provides two APIs:
createTokenBridgeEnoughCustomFeeTokenAllowance
: This method verifies that the deployer's address has enough allowance to pay for the fees associated with the token bridge deployment.createTokenBridgePrepareCustomFeeTokenApprovalTransactionRequest
: This function assists in generating the raw transaction required to approve the native token for theTokenBridgeCreator
contract.
The following example demonstrates how to leverage these APIs effectively to check for and, if necessary, grant approval to the TokenBridgeCreator
contract:
const allowanceParams = {
nativeToken,
owner: rollupOwner.address,
publicClient: parentChainPublicClient,
};
if (!(await createTokenBridgeEnoughCustomFeeTokenAllowance(allowanceParams))) {
const approvalTxRequest = await createTokenBridgePrepareCustomFeeTokenApprovalTransactionRequest(
allowanceParams,
);
}
In this scenario, allowanceParams
includes:
- The native token's details:
nativeToken
. - The Rollup owner's address:
rollupOwner.address
. - The parent chain's publicClient:
parentChainPublicClient
.
First, createTokenBridgeEnoughCustomFeeTokenAllowance
checks if the deployer has been granted enough allowance.
If the allowance is insufficient, createTokenBridgePrepareCustomFeeTokenApprovalTransactionRequest
is called to create the necessary approval transaction.
Please note that after generating the raw transaction, the deployer must still sign and broadcast it to the network to finalize the approval process.
Deploy your Orbit chain
Orbit SDK provides the createRollupPrepareTransactionRequest
helper to prepare your transaction:
createRollupPrepareTransactionRequest API:
This API accepts parameters defined in the RollupDeploymentParams
struct, applying defaults where necessary, and generates the RollupDeploymentParams
. This struct is then used to create a raw transaction which calls the createRollup
function of the RollupCreator
contract. As discussed in previous sections, this function deploys and initializes all core Orbit contracts.
For instance, to deploy using the Orbit SDK with a Config equal to config
, a batchPoster
, and a set of validators such as [validator]
, the process would look like this:
import { createRollupPrepareTransactionRequest } from '@arbitrum/orbit-sdk';
const request = await createRollupPrepareTransactionRequest({
params: {
config,
batchPoster,
validators: [validator],
},
account: deployer_address,
publicClient,
});
After creating the raw transaction, you need to sign and broadcast it to the network, as shown in the create-rollup-eth
example.
Get the orbit chain information after deployment
Once you've successfully deployed your Orbit chain, the next step is to retrieve detailed information about the deployment. The Orbit SDK provides a convenient way to do this through the createRollupPrepareTransactionReceipt
API.
After sending the signed transaction and receiving the transaction receipt, you can use the createRollupPrepareTransactionReceipt
API to parse this receipt and extract the relevant data. This process will provide comprehensive details about the deployed chain, such as contract addresses, configuration settings, and other information.
Here's an example of how to use the Orbit SDK to get data from a deployed Orbit chain:
import { createRollupPrepareTransactionReceipt } from '@arbitrum/orbit-sdk';
const data = createRollupPrepareTransactionReceipt(txReceipt);
In this example, txReceipt
refers to the transaction receipt you received after deploying the chain. By passing this receipt to the createRollupPrepareTransactionReceipt
function, you can easily access a wealth of information about your Orbit chain. This feature of the Orbit SDK simplifies the post-deployment process, allowing you to quickly and efficiently gather all necessary details about your chain for further use or reference.
Set valid keyset on parent chain
The final step in deploying your AnyTrust Orbit chain is to set up the valid keyset for your Data Availability Committee (DAC) on the parent chain. This keyset is essential for ensuring the integrity of the certificates that the DAC signs when storing Orbit chain's data. The process of generating keys and the keyset for your committee is comprehensively explained in our documentation. Once you have your keyset, it needs to be established on the SequencerInbox
contract of your Orbit chain on the parent chain.
To facilitate this, we provide an API in Orbit SDK named setValidKeysetPrepareTransactionRequest
. This API aids in setting the keyset on the parent chain. To use this API, you need specific information that you gathered in step 3. This includes the upgradeExecutor
and sequencerInbox
addresses of your Orbit chain, the generated keyset for your committee, and the account of the owner.
Here's an example of how you can use the Orbit SDK to set the keyset:
const txRequest = await setValidKeysetPrepareTransactionRequest({
coreContracts: {
upgradeExecutor: 'upgradeExecutor_address',
sequencerInbox: 'sequencerInbox_address',
},
keyset,
account: deployer.address,
publicClient: parentChainPublicClient,
});
In this example, upgradeExecutor_address
and sequencerInbox_address
are placeholders for the actual addresses of the respective contracts in your Orbit chain. keyset
is the keyset you generated for your committee, and deployer.address
refers to the owner's account address.
After you create the transaction request using the above API, the next step is to sign and send the transaction. This action will effectively set the keyset on the parent chain, allowing it to recognize and verify the valid keyset for your AnyTrust Orbit chain. This step is crucial for the operational integrity and security of your AnyTrust chain, ensuring that the data verified by the DAC is recognized and accepted by the parent chain.
Configure a Node running your AnyTrust Orbit chain
Once you have successfully deployed and initialized the Orbit core contracts, the next step is configuring and running your Orbit chain using a Node Config JSON
file describing all the configurations for the Arbitrum Node, including settings for the Batch-poster, Validator, and the chain itself.
Example for a Rollup Orbit Chain:
{
'chain': {
'info-json': stringifyInfoJson([...]),
'name': chainName,
// Additional chain-specific configurations
},
'parent-chain': {
connection: {
url: parentChainRpcUrl,
},
},
'http': {
addr: '0.0.0.0',
port: 8449,
vhosts: '*',
corsdomain: '*',
api: ['eth', 'net', 'web3', 'arb', 'debug'],
},
'node': {
// Node-specific settings including sequencer, batch-poster, staker configurations
},
};
Here are some inputs details from the example above:
Parameters | Description |
---|---|
chain | Details about the hosted chain, including chain ID, name, and core contracts. |
parent-chain | Information for connecting to the parent chain. |
http | Configuration parameters for the HTTP server. |
node | Specific node settings, including sequencer and batch-poster configurations. |
Additional configuration for AnyTrust Orbit chains:
For AnyTrust Orbit chains, the Node Config JSON
has an additional segment under the node
field. This addition includes settings specific to the AnyTrust model, such as:
- Sequencer's inbox address
- Parent chain node URL
- RPC aggregators
Example addition for AnyTrust Node Config:
{
...
'node': {
...
'sequencer-inbox-address': coreContracts.sequencerInbox,
'parent-chain-node-url': parentChainRpcUrl,
'rest-aggregator': {
enable: true,
urls: 'http://localhost:9876',
},
'rpc-aggregator': {
'enable': true,
'assumed-honest': 1,
'backends': stringifyBackendsJson([...]),
},
}
...
};
Preparing your node config file
The Node Config file includes three fields types:
- Information from the Orbit deployment chain: Such as the addresses of the core contracts.
- Parameters configurable by the chain deployer: These parameters, like
max-block-speed
, can be adjusted to modify your chain's behavior. - Fields not typically configured: Like the HTTP section, which usually remains standard.
Let's explore the parameters allowing you to set up a stable, and secure Orbit chain tailored to your project's requirements:
Node config generation with Orbit SDK
Generating a Node Config JSON
file to initiate your Orbit chain is a step in the deployment process. The Orbit SDK simplifies this task with an API named prepareNodeConfig
. This API takes specific parameters for your Orbit chain and returns a JSON
file that can be used as the Node Config to initiate the chain.
Here’s an example of using the prepareNodeConfig
API to generate the node config:
const nodeConfig = prepareNodeConfig({
chainName: 'My Orbit Chain',
chainConfig,
coreContracts,
batchPosterPrivateKey: 'BATCH_POSTER_PRIVATE_KEY_HERE',
validatorPrivateKey: 'VALIDATOR_PRIVATE_KEY_HERE',
parentChainId: parentChain_chain_id,
parentChainRpcUrl: parentChain_RPC_URL,
});
Here are some details about the parameters used in the example above:
Parameters | Description |
---|---|
chainName | The name you have chosen for your Orbit chain. |
chainConfig | Configuration used for chain deployment, returned from the createRollupPrepareTransactionReceipt API. |
coreContracts | Addresses of your newly deployed Orbit chain's, also returned from the createRollupPrepareTransactionReceipt API. |
batchPosterPrivateKey | Private key of the batch-poster account, used for signing batch-posting transactions and related functions. |
validatorPrivateKey | Private key of the validator(s), used for validating state, posting Rollup Blocks (RBlocks ) to the parent chain, and initiating challenges if necessary. |
parentChainId | Chain ID of the parent chain where your Orbit chain is deployed. |
parentChainRpcUrl | Parent chain's RPC URL. |
If you don't have the chainConfig
and coreContracts
readily available, you can obtain them using the createRollupPrepareTransaction
and createRollupPrepareTransactionReceipt
APIs.
Here's an example of how to extract chainConfig
and coreContracts
using just the transaction hash from your deployment:
import {
ChainConfig,
createRollupPrepareTransaction,
createRollupPrepareTransactionReceipt,
} from '@arbitrum/orbit-sdk';
const tx = createRollupPrepareTransaction({ hash: txHash });
const txReceipt = createRollupPrepareTransactionReceipt({ hash: txHash });
const chainConfig: ChainConfig = JSON.parse(tx.getInputs()[0].config.chainConfig);
const coreContracts = txReceipt.getCoreContracts();
This process ensures that all necessary configurations and contract details are included in your Node Config.
Deploy your custom token brige
The Arbitrum Nitro stack doesn't natively support specific token bridging standards at the protocol level. Instead, Offchain Labs designed a "canonical bridge" that ensures seamless token transfers between the parent and child chains.
The token bridge architecture includes contracts deployed on the parent chain and on the child chain. These entities communicate via the Retryable Ticket protocol, ensuring efficient and secure interactions.
See the ERC-20
token bridge overview for more information about the token bridge's design and operational dynamics, and the "create-token-bridge-eth" example for additional guidance.
Token bridge deployment steps
Once an Orbit chain has been deployed and initialized, the bridge contracts need to be deployed on both the parent and child chains. This process involves several steps:
- Token approval
- Token bridge contract deployment
- Transaction recipient and checking for deployment on child chain
- Deployment information and contract addresses
1. Token approval
This step is only required for custom fee token Orbit chains.
Initiating the deployment of a token bridge for Custom Fee Token on orbit chains begins with ensuring the TokenBridgeCreator
contract is granted sufficient approvals of the native token. To facilitate this process, the Orbit SDK provides two APIs:
createTokenBridgeEnoughCustomFeeTokenAllowance
: This method verifies that the deployer's address has enough allowance to pay for the fees associated with the token bridge deployment.createTokenBridgePrepareCustomFeeTokenApprovalTransactionRequest
: This function assists in generating the raw transaction required to approve the native token for theTokenBridgeCreator
contract.
The following example demonstrates how to leverage these APIs effectively to check for and, if necessary, grant approval to the TokenBridgeCreator
contract:
const allowanceParams = {
nativeToken,
owner: rollupOwner.address,
publicClient: parentChainPublicClient,
};
if (!(await createTokenBridgeEnoughCustomFeeTokenAllowance(allowanceParams))) {
const approvalTxRequest = await createTokenBridgePrepareCustomFeeTokenApprovalTransactionRequest(
allowanceParams,
);
}
In this scenario, allowanceParams
includes:
- The native token's details:
nativeToken
. - The Rollup owner's address:
rollupOwner.address
. - The parent chain's publicClient:
parentChainPublicClient
.
First, createTokenBridgeEnoughCustomFeeTokenAllowance
checks if the deployer has been granted enough allowance.
If the allowance is insufficient, createTokenBridgePrepareCustomFeeTokenApprovalTransactionRequest
is called to create the necessary approval transaction.
Please note that after generating the raw transaction, the deployer must still sign and broadcast it to the network to finalize the approval process.
2. Token bridge contract deployment
Deploying token bridge contracts is the first step in creating a bridge between the parent and the Orbit chain.
The deployment process is the same as Orbit chain contracts', where a primary contract facilitates the deployment of core contracts. The token bridge contracts are deployed on the parent and child chains by TokenBridgeCreator
. TokenBridgeCreator
does it in a single transaction using the Retryable Tickets protocol .
Orbit SDK provides an API that automates the deployment by interacting with the TokenBridgeCreator
contract. The API is createTokenBridgePrepareTransactionRequest
, which processes the necessary inputs and generates a transaction request tailored for token bridge deployment.
Example:
const txRequest = await createTokenBridgePrepareTransactionRequest({
params: {
rollup: rollupContractAddress,
rollupOwner: rollupOwnerAddress,
},
parentChainPublicClient,
orbitChainPublicClient,
account: rollupOwnerAddress,
});
Here are the parameters used in the above example:
Parameter | Description |
---|---|
rollupContractAddress | Orbit chain's Rollup contract address. |
rollupOwnerAddress | Rollup owner's address. |
parentChainPublicClient | Parent chain's public client, as defined by Viem. |
orbitChainPublicClient | Orbit chain's public client, as defined by Viem. |
For more insights into these variables and their usage, consider exploring this token bridge deployment example.
Following the creation of the raw transaction, the next steps involve signing it and broadcasting it to the relevant blockchain network to complete the deployment process.
3. Transaction recipient and checking for deployment on child chain
After sending the deployment transaction, you will need to retrieve the transaction receipt and verify the successful deployment of the contracts on both the parent and child chains.
Our Orbit SDK includes a dedicated API for this purpose, named createTokenBridgePrepareTransactionReceipt
, which simplifies the process of obtaining the deployment transaction's recipient.
Example:
const txReceipt = createTokenBridgePrepareTransactionReceipt(
await parentChainPublicClient.waitForTransactionReceipt({ hash: txHash }),
);
In this scenario, txHash
represents the hash of the deployment transaction initiated in the previous step. The waitForTransactionReceipt
API from Viem captures the transaction's recipient on the parent chain. The createTokenBridgePrepareTransactionReceipt
API enhances the basic functionality provided by Viem's waitForTransactionReceipt
, introducing a specialized method named waitForRetryables
to handle the outcome (in this case, txReceipt
).
By employing the waitForRetryables
method, you can ensure the success of Retryable Tickets on the parent chain.
Example:
const orbitChainRetryableReceipts = await txReceipt.waitForRetryables({
orbitPublicClient: orbitChainPublicClient,
});
if (orbitChainRetryableReceipts[0].status !== 'success') {
throw new Error(
`Retryable status is not success: ${orbitChainRetryableReceipts[0].status}. Aborting...`,
);
}
console.log(`Retryable executed successfully`);
In this example, the waitForRetryables
method is invoked on the txReceipt
to monitor the execution of Retryable Tickets and verify their status. A success
status indicates that the Retryable Tickets have been executed successfully, ensuring the contracts' deployment. It's important to note that this process involves two Retryable Tickets. You can check out a more comprehensive walkthrough of the example. This enhanced approach not only simplifies the retrieval of transaction receipts but also provides a reliable method for verifying contract deployment across chains.
4. Deployment information and contract addresses
Once you have completed the deployment and are assured that the Retryable Tickets are successful, you can use getTokenBridgeContracts
to retrieve the deployment information and all the token bridge contracts' addresses.
Here's an example of how to get the contract addresses from the txReceipt
generated in the previous steps:
const tokenBridgeContracts = await txReceipt.getTokenBridgeContracts({
parentChainPublicClient,
});