This project demonstrates how to perform cross-chain token transfers using the Wormhole SDK. It supports transferring tokens across different blockchain networks, including EVM-compatible chains (e.g., Ethereum, Avalanche), Solana, and Sui. The solution uses Wormhole's Testnet environment for demonstration purposes.
For a complete tutorial on performing cross-chain token transfers using the Token Bridge from scratch, please take a look at the Wormhole Token Bridge Tutorial.
The project is organized as follows:
demo-basic-ts-sdk/
├── src/
│ ├── helpers/
│ │ └── helpers.ts # Helper functions for signer setup and environment variables
│ ├── scripts/
│ ├── token-transfer.ts # Script to perform a token transfer between chains
│ └── tx-recover.ts # Script to recover and manually complete a token transfer using a transaction ID
│ ├── create-wrapped.ts # Script to create a wrapped token on the destination chain
│ └── convert.ts # Script to convert Solana private keys to base58 format
├── .env # Environment variables for private keys (not included in the repo)
├── package.json # Project dependencies and scripts
└── tsconfig.json # TypeScript configuration
Ensure you have the following installed:
- Node.js and npm installed on your machine
- A wallet with a private key, funded with native tokens (Testnet or Mainnet) for gas fees
Follow these steps to clone the repository, set up environment variables, and perform token transfers.
1. Clone the Repository
git clone https://github.com/wormhole-foundation/demo-basic-ts-sdk.git
cd demo-basic-ts-sdk2. Install Dependencies
npm install3. Set Up Environment Variables
Create a .env file in the root directory and add your private keys:
ETH_PRIVATE_KEY="INSERT_PRIVATE_KEY"
SOL_PRIVATE_KEY="INSERT_PRIVATE_KEY"
SUI_MNEMONIC="INSERT_SUI_MNEMONIC"
APTOS_PRIVATE_KEY="INSERT_PRIVATE_KEY"- ETH_PRIVATE_KEY - private key for an Ethereum-compatible wallet
- SOL_PRIVATE_KEY - private key for a Solana wallet
- SUI_MNEMONIC - mnemonic for a Sui wallet
- APTOS_PRIVATE_KEY - private key for an Aptos wallet
Important: For Sui, you must provide a mnemonic instead of a private key. Ensure these keys are valid and have the necessary permissions to perform transfers.
If you have a Solana private key in byte array format, you can use the convert.ts script to convert it to base58 format. For example, if you have a key like:
[89,245,29,210,238,159,81,...] // 64-byte arrayTo use the convert script:
- Open
src/scripts/convert.ts - Replace the
byteArraywith your private key array - Run the conversion:
npm run convertThe script will output the base58-encoded private key that you can use in your .env file as SOL_PRIVATE_KEY.
You must create a wrapped version if a token is not yet recognized on the destination chain. The create-wrapped.ts script automates this process using the Wormhole SDK.
Before running the script, open src/scripts/create-wrapped.ts and set the source and destination chains. By default, it wraps a token from Arbitrum Sepolia to Base Sepolia, but you can modify this as needed.
Run the script:
npm run create:wrappedThe script retrieves the wrapped token ID, creates an attestation, fetches the signed VAA, and submits it to the destination chain. If the token is already wrapped, it returns:
Token already wrapped on Base SepoliaYou can customize the following options within the scripts:
- Source and Destination Chains - modify
sendChainandrcvChainintoken-transfer.ts - Amount and Transfer Settings - adjust
amt,automatic, andnativeGasto suit your needs - Token Address - set the
tokenIdto specify which token to transfer - Transfer Protocol - choose between
TokenBridge,AutomaticTokenBridgeorExecutorTokenBridgefor the transfer
To initiate a token transfer across chains, run:
npm run transfer:tokenNote: This script is set up to transfer a token from Solana to Berachain using the Wormhole SDK. You can modify the source and destination chains within
src/token-transfer.ts.
If a token transfer has been initiated but not completed, you can manually recover it and attempt to finish it using the transaction ID. This can be helpful in cases where the automatic process does not finalize the transfer.
a. Set the Transaction ID:
Open src/tx-recover.ts and provide the correct transaction ID (txid) for the transfer you want to recover. This ID will fetch the transfer details and attempt to complete it on the destination chain.
// In src/tx-recover.ts
let recoverTxid = 'INSERT_YOUR_TRANSACTION_ID';b. Run the Recovery Command:
Once you have set the transaction ID, run the following command:
npm run transfer:recover- Unlike other platforms, Sui requires a mnemonic instead of a private key for authentication. Ensure your
.envfile includes this correctly - Please make sure that the Wormhole Testnet is operational when running scripts
- Check your wallet balances and transfer fees before initiating transfers
- For production use, switch from Testnet to Mainnet and update the configuration accordingly
- Missing environment variables - ensure
.envis correctly set up and keys are valid - Unsupported platform error - verify that the chains are compatible and supported by the Wormhole SDK
- Transaction Not Going Through - if the transaction doesn't go through, check if the wrapped token exists on the destination chain. This issue is more common with native tokens
- Incomplete Transfers - if a transfer was not completed, use
tx-recover.tsto manually finish the transaction by providing thetxid