Get Started#
Settlement is Wormhole’s intent-based execution layer, enabling fast, multichain token transfers. It coordinates routing logic, relayers, and on-chain infrastructure to let users express what they want to be done, not how.
This guide walks you through performing a real token swap using the Mayan Swift route, one of the three integrated Settlement protocols, with the Wormhole TypeScript SDK.
By the end, you'll have a working script that:
- Resolves token transfer routes using Mayan Swift
- Quotes and validates the best route
- Initiates a swap on a source chain and completes the transfer on a destination chain
Note
Mayan Swift currently supports mainnet only. Attempting to run this demo on a testnet will fail.
Prerequisites#
Before you begin, ensure you have the following:
- Node.js and npm installed on your machine
- Wallets funded with tokens on two supported chains
This example uses Ethereum as the source chain and Solana as the destination. As a result, you'll need an Ethereum wallet with ETH for gas and a Solana wallet with SOL for fees. You can adapt the example to match your preferred chains.
Set Up a Project#
Start by scaffolding a basic Node.js project and installing the required SDKs.
-
Create a new project folder:
-
Install the required dependencies:
-
Create the file structure:
-
Set up secure access to your wallets. This guide assumes you are loading your
MAINNET_ETH_PRIVATE_KEY
andMAINNET_SOL_PRIVATE_KEY
from a secure keystore of your choice, such as a secrets manager or a CLI-based tool like cast wallet.Warning
If you use a .env file during development, add it to your .gitignore to exclude it from version control. Never commit private keys or mnemonics to your repository.
Perform a Token Swap#
This section shows you how to perform a token swap using the Mayan Swift route. You will define a helper function to configure the source and destination chain signers.
Then, you'll create a script that initiates a transfer on Ethereum, uses the Mayan Swift resolver to find valid routes, sends the transaction, and completes the transfer on Solana.
-
Open
helper.ts
and define thegetSigner
utility function to load private keys, instantiate signers for Ethereum and Solana, and return the signers along with the Wormhole-formatted address:src/helpers.tsimport { Chain, ChainAddress, ChainContext, Network, Signer, Wormhole, } from '@wormhole-foundation/sdk-connect'; import { getEvmSignerForKey } from '@wormhole-foundation/sdk-evm'; import { getSolanaSigner } from '@wormhole-foundation/sdk-solana'; /** * Returns a signer for the given chain using locally scoped credentials. * The required values (MAINNET_ETH_PRIVATE_KEY, MAINNET_SOL_PRIVATE_KEY) * must be loaded securely beforehand, for example via a keystore, * secrets manager, or environment variables (not recommended). */ // Define Transfer Interface export interface SignerContext<N extends Network, C extends Chain> { signer: Signer<N, C>; address: ChainAddress<C>; } export async function getSigner<N extends Network, C extends Chain>( chain: ChainContext<N, C> ): Promise<SignerContext<N, C>> { let signer: Signer; const platform = chain.platform.utils()._platform; switch (platform) { case 'Solana': signer = await getSolanaSigner( await chain.getRpc(), getEnv('MAINNET_SOL_PRIVATE_KEY') ); break; case 'Evm': signer = await getEvmSignerForKey( await chain.getRpc(), getEnv('MAINNET_ETH_PRIVATE_KEY') ); break; default: throw new Error('Unrecognized platform: ' + platform); } return { signer: signer as Signer<N, C>, address: Wormhole.chainAddress(chain.chain, signer.address()), }; }
-
In
swap.ts
, add the following script, which will handle all of the logic required to perform the token swap:src/swap.tsimport { Wormhole, routes } from '@wormhole-foundation/sdk-connect'; import { EvmPlatform } from '@wormhole-foundation/sdk-evm'; import { SolanaPlatform } from '@wormhole-foundation/sdk-solana'; import { MayanRouteSWIFT } from '@mayanfinance/wormhole-sdk-route'; import { getSigner } from './helpers'; (async function () { // Setup const wh = new Wormhole('Mainnet', [EvmPlatform, SolanaPlatform]); const sendChain = wh.getChain('Ethereum'); const destChain = wh.getChain('Solana'); // To transfer native ETH on Ethereum to native SOL on Solana const source = Wormhole.tokenId(sendChain.chain, 'native'); const destination = Wormhole.tokenId(destChain.chain, 'native'); // Create a new Wormhole route resolver, adding the Mayan route to the default list // @ts-ignore: Suppressing TypeScript error because the resolver method expects a specific type, // but MayanRouteSWIFT is compatible and works as intended in this context. const resolver = wh.resolver([MayanRouteSWIFT]); // Show supported tokens const dstTokens = await resolver.supportedDestinationTokens( source, sendChain, destChain ); console.log(dstTokens.slice(0, 5)); // Load signers and addresses from helpers const sender = await getSigner(sendChain); const receiver = await getSigner(destChain); // Creating a transfer request fetches token details // since all routes will need to know about the tokens const tr = await routes.RouteTransferRequest.create(wh, { source, destination, }); // Resolve the transfer request to a set of routes that can perform it const foundRoutes = await resolver.findRoutes(tr); const bestRoute = foundRoutes[0]!; // Specify the amount as a decimal string const transferParams = { amount: '0.002', options: bestRoute.getDefaultOptions(), }; // Validate the queries route let validated = await bestRoute.validate(tr, transferParams); if (!validated.valid) { console.error(validated.error); return; } console.log('Validated: ', validated); const quote = await bestRoute.quote(tr, validated.params); if (!quote.success) { console.error(`Error fetching a quote: ${quote.error.message}`); return; } console.log('Quote: ', quote); // Initiate the transfer const receipt = await bestRoute.initiate( tr, sender.signer, quote, receiver.address ); console.log('Initiated transfer with receipt: ', receipt); await routes.checkAndCompleteTransfer( bestRoute, receipt, receiver.signer, 15 * 60 * 1000 ); })();
-
Execute the script to initiate and complete the transfer:
If successful, you’ll see terminal output like this:
npx tsx src/swap.ts Validated: { valid: true, ... } Quote: { success: true, ... } Initiated transfer with receipt: ... Checking transfer state... Current Transfer State: SourceInitiated Current Transfer State: SourceInitiated Current Transfer State: SourceInitiated Current Transfer State: DestinationFinalized
Congratulations! You've just completed a cross-chain token swap from Ethereum to Solana using Settlement.
Customize the Integration#
You can tailor the example to your use case by adjusting:
- Tokens and chains: Use
getSupportedTokens()
to explore what's available. - Source and destination chains: Modify
sendChain
anddestChain
inswap.ts
. - Transfer settings: Update the amount or route parameters.
- Signer management: Modify
src/helpers.ts
to integrate with your preferred wallet setup.
Next Steps#
Once you've chosen a path, follow the corresponding guide to start building:
demo-mayanswift
: Check out the repository for the full code example.