Before we continue, please ensure that you have had a look at our Supported Ethereum Chains, followed the steps in Install Etherspot SDK and how to Bootstrap Etherspot SDK. We're assuming that you have completed these steps before going forward.
In this example, we're going to show you how to send xDai to Dai using their TokenBridge and Etherspot.
Before we continue...
We're going to be using two Etherspot SDK instances here:
A mainnet version
We will use this instance to send our DAI from and ETH to pay the gas fees.
A xDai version
We will use this instance to receive our xDai on the xDai chain.
Make sure you've checked out Supported Ethereum Chains before you continue as we also show you the code to instantiate mainnet and xDai versions of the SDK. Remember to use the same private key for both SDK instances to get the same Ethereum address on both mainnet and xDai.
This example use case is more complex than the previous guide in this series: DAI - xDai Bridge, but completes the cycle of DAIxDai.
Please make sure your that your xDai Etherspot address is funded with enough xDAI to pay the gas fees required.
Sending xDai to TokenBridge
The first step in our journey to change xDai back to DAI is to send our xDai, using the xDai version of the Etherspot SDK, to the xDai TokenBridge.
Let's define our required variables:
/*** Note: Make sure that your `mainnet` and `xDai`* instances of the Etherspot SDK are available here.** For the purposes of this demonstration, we're going* to assume the following:* * The mainnet Etherspot SDK:* - const mainnetEtherspotSdk** The xDai Etherspot SDK:* - const xdaiEtherspotsdk*/import { ethers } from'etherspot';constxdaiBridgeAddress="0x7301CFA0e1756B71869E93d4e4Dca5c7d0eb0AA6";constxdaiBridgeContract="0x6A92e97A568f5F58590E8b1f56484e6268CdDC51";// Visit https://blockscout.com/xdai/mainnet/address/0x6A92e97A568f5F58590E8b1f56484e6268CdDC51/contracts.// Under the "Code" tab, scroll down to "Contract ABI" // and copy the code into a JSON file and import it here.constxdaiBridgeAbi=require('xDaiBridgeAbi.json');constdaiContractAddress="0x4aa42145Aa6Ebf72e164C9bBC74fbD3788045016";// Visit https://etherscan.io/address/0x7e7669bdff02f2ee75b68b91fb81c2b38f9228c2#code and scroll down to Contract ABI and copy the whole code and paste it in a JSON file and import it to this variable.constdaiContractAbi=require('daiContractAbi.json');
Next, let's specify how much xDai we would like to send.
// Note: TokenBridge requires a minimum of 10 xDailet xdaiTransferAmount =ethers.utils.parseEther("10");
Next, we're going to perform a series of steps to:
Add the transaction to the batch
Estimate the gas required to submit and execute this batch
Send the batch to Etherspot to be processed
Check to see when the transaction has been sent
/*** Step 1: Add the transaction to a clean* "batch" of transactions.** Note: You can batch many transactions together and* submit them as one request for a more gas-efficient* operation. Here, we're just adding 1 transaction to* this batch.*/constbatchResponse=await xdaiEtherspotsdk.batchExecuteAccountTransaction({ to: xdaiBridgeAddress, value: xdaiTransferAmount }).catch(console.error);/*** Step 2: Estimate the gas required to perform this* operation. This is useful for presenting to users* and allowing them to make a final decision.*/constestimateResponse=await xdaiEtherspotsdk.estimateGatewayBatch().catch(console.error);/*** Step 3: Next, send this batch to Etherspot for* processing. We'll manage the transaction, queuing,* retries and endevour to do whatever it takes to* get this transaction on the chosen blockchain.*/constsubmitGatewayResponse=await xdaiEtherspotsdk.submitGatewayBatch().catch(console.error);/*** Step 4: Let's keep checking on this batch submission* to check the status before we move on. Keep calling* this method below, using an Interval timer for example,* and move on to the next step when gatewayBatchStatus.state* is "Sent".*/constgatewayBatchStatus=await xdaiEtherspotsdk.getGatewaySubmittedBatch({ hash:submitGatewayResponse.hash, }).catch(console.error);
gatewayBatchStatus.state
meaning
"Sent"
The transactions that existed in the batch are due to be confirmed.
"Sending"
The transactions that existed in the batch are currently pending broadcast on the blockchain.
"Queued"
The transactions that existed in the batch are queued by Etherspot to be processed.
Get TokenBridge Signature
Once gatewayBatchStatus.state is equal to "Sent", indicating that the transactions in the batch are due to be confirmed, we'll lift the hash of the transaction into its own variable.
Next, we need to construct an instance of the xDai bridge contract from the ethers library. We'll communicate with the contract to fetch the required data to continue.
Query the contract for a corresponding message hash for xDai amount and the xDai Etherspot address
Use the message hash from the previous point to get a message payload from the contract
Check if the message payload is valid, and then get the required signature to continue.
/*** Step 1: Query the contract for the corresponding* message hash*/constmessageHash=awaitcontract.getMessageHash(xdaiEtherspotsdk.state.accountAddress,// Your xDai Etherspot addressxdaiTransferAmount.toString(), xDaiSubmissionHash,);/*** Step 2: Use the message hash to fetch the* message payload itself*/let messagePayload =awaitcontract.getMessage(messageHash);/*** Step 3: Let's do a basic check to ensure that the* available tokens are still available to withdraw*/let signature =null;if (messagePayload !="0x"&& messagePayload !="0x0") { signature =await contract.getSignatures(ethers.utils.keccak256(messagePayload) );} else {console.error('Please check the contract payload parameters.');}
Once the transaction above gets confirmed, pass the required parameters along with the hash of the transaction made earlier to the contract methods to get the signature from token bridge.
Withdraw DAI from TokenBridge to Etherspot address
In this final section, we're going to initiate a move from the DAI contract address to our own Etherspot address on mainnet - it's final destination.
First, let's construct a contract interface to communicate with the DAI contract:
// First, construct the interface...constdaiInterface=newethers.utils.Interface(daiContractAbi); // Next, encode the required data to perform the withdrawallet encodedData =awaitdaiInterface.encodeFunctionData("executeSignatures", [messagePayload, signature],);
Now, we have completed all the required prerequisites to withdraw the DAI from TokenBridge. We're going to perform a series of steps to:
Add the transaction to the batch
Estimate the gas required to submit and execute this batch
Send the batch to Etherspot to be processed
/*** Step 1: Add the transaction to a clean* "batch" of transactions.** Note: You can batch many transactions together and* submit them as one request for a more gas-efficient* operation. Here, we're just adding 1 transaction to* this batch.*/constdaiBatchResponse=await mainnetEtherspotSdk.batchExecuteAccountTransaction({ to: daiContractAddress, data: encodedData, }).catch(console.error);/*** Step 2: Estimate the gas required to perform this* operation. This is useful for presenting to users* and allowing them to make a final decision.*/constdaiBatchEstimation=await mainnetEtherspotSdk.estimateGatewayBatch().catch(console.error);/*** Step 3: Next, send this batch to Etherspot for* processing. We'll manage the transaction, queuing,* retries and endevour to do whatever it takes to* get this transaction on the chosen blockchain.*/constdaiBatchTransaction=await mainnetEtherspotSdk.submitGatewayBatch().catch(console.error);
Let's ensure that we have no batches of transactions waiting in the queue to be sent. We like to keep the house clean.
Let's ensure that we have no batches of transactions waiting in the queue to be sent. We like to keep the house clean.