# Wormhole Developer Documentation (LLMS Format)
This file contains documentation for Wormhole (https://wormhole.com). A cross-chain messaging protocol used to move data and assets between blockchains.
It is intended for use with large language models (LLMs) to support developers working with Wormhole. The content includes selected pages from the official docs, organized by product category and section.
This file includes documentation related to the product: Typescript-SDK
## AI Prompt Template
You are an AI developer assistant for Wormhole (https://wormhole.com). Your task is to assist developers in understanding and using the product described in this file.
- Provide accurate answers based on the included documentation.
- Do not assume undocumented features, behaviors, or APIs.
- If unsure, respond with “Not specified in the documentation.
## List of doc pages:
Doc-Page: https://raw.githubusercontent.com/wormhole-foundation/wormhole-docs/refs/heads/main/build/toolkit/cli.md [type: build]
Doc-Page: https://raw.githubusercontent.com/wormhole-foundation/wormhole-docs/refs/heads/main/build/toolkit/dev-env.md [type: build]
Doc-Page: https://raw.githubusercontent.com/wormhole-foundation/wormhole-docs/refs/heads/main/build/toolkit/faqs.md [type: build]
Doc-Page: https://raw.githubusercontent.com/wormhole-foundation/wormhole-docs/refs/heads/main/build/toolkit/typescript-sdk.md [type: build]
Doc-Page: https://raw.githubusercontent.com/wormhole-foundation/wormhole-docs/refs/heads/main/build/toolkit/typescript-sdk/protocols-payloads.md [type: build]
Doc-Page: https://raw.githubusercontent.com/wormhole-foundation/wormhole-docs/refs/heads/main/build/toolkit/typescript-sdk/sdk-layout.md [type: build]
Doc-Page: https://raw.githubusercontent.com/wormhole-foundation/wormhole-docs/refs/heads/main/build/toolkit/typescript-sdk/vaas-protocols.md [type: build]
Doc-Page: https://raw.githubusercontent.com/wormhole-foundation/wormhole-docs/refs/heads/main/build/toolkit/typescript-sdk/wormhole-sdk.md [type: build]
## Full content for each doc page
Doc-Content: https://wormhole.com/docs/build/toolkit/cli/
--- BEGIN CONTENT ---
---
title: Wormhole CLI
description: Learn how to install and use the Wormhole CLI, including commands and examples for managing multichain deployments, generating VAAs, and querying contract info.
categories: Solidity-SDK, Typescript-SDK
---
# Wormhole CLI
This tool is a command-line interface to Wormhole, allowing you to perform various actions, such as querying a transaction's status or submitting token transfers.
## Installation
Clone the repository and change directories to the appropriate directory:
```bash
git clone https://github.com/wormhole-foundation/wormhole &&
cd wormhole/clients/js
```
Build and install the CLI tool:
```bash
make install
```
This installs two binaries, `worm-fetch-governance` and `worm` on your `$PATH`. To use `worm`, set up `$HOME/.wormhole/.env` with your private keys, based on `.env.sample` in this folder.
## Usage
You can interact with the Wormhole CLI by typing `worm` and including the `command` and any necessary subcommands and parameters.
| Command | Description |
|--------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------|
| `worm aptos INSERT_COMMAND` | Aptos utilities |
| `worm edit-vaa INSERT_COMMAND` | Edits or generates a VAA |
| `worm evm INSERT_COMMAND` | EVM utilities |
| `worm generate INSERT_COMMAND` | Generate VAAs (Devnet and Testnet only) |
| `worm info INSERT_COMMAND` | Contract, chain, RPC, and address information utilities |
| `worm near INSERT_NETWORK, INSERT_ACCOUNT` | NEAR utilities |
| `worm parse INSERT_VAA` | Parse a VAA (can be in either hex or base64 format) |
| `worm recover INSERT_DIGEST INSERT_SIGNATURE` | Recover an address from a signature |
| `worm status INSERT_NETWORK, INSERT_CHAIN, INSERT_TXN_HASH` | Prints information about the automatic delivery initiated on the specified network, chain, and transaction hash |
| `worm submit INSERT_VAA` | Execute a VAA |
| `worm sui INSERT_COMMAND` | Sui utilities |
| `worm transfer INSERT_SOURCE_CHAIN, INSERT_DESTINATION_CHAIN, INSERT_DESTINATION_ADDRESS, INSERT_AMOUNT, INSERT_NETWORK` | Transfers a token |
| `worm verify-vaa INSERT_VAA, INSERT_NETWORK` | Verifies a VAA by querying the Core Contract on Ethereum |
You can also refer to the below options, available with all `worm` commands:
```bash
Options:
--help Show help [boolean]
--version Show version number [boolean]
```
### Subcommands
??? code "Aptos"
```bash
worm aptos INSERT_COMMAND
Commands:
worm aptos init-token-bridge Init token bridge contract
worm aptos init-wormhole Init Wormhole core contract
worm aptos deploy Deploy an Aptos package
worm aptos deploy-resource Deploy an Aptos package using a
resource account
worm aptos send-example-message Send example message
worm aptos derive-resource-account Derive resource account address
worm aptos derive-wrapped-address Derive wrapped coin type
worm aptos hash-contracts Hash contract bytecodes for upgrade
worm aptos upgrade Perform upgrade after VAA has been
submitted
worm aptos migrate Perform migration after contract
upgrade
worm aptos faucet Request money from the faucet for a
given account
worm aptos start-validator Start a local aptos validator
Options:
--help Show help [boolean]
--version Show version number [boolean]
```
??? code "Edit VAA"
```bash
worm edit-vaa INSERT_COMMAND
Options:
--help Show help [boolean]
--version Show version number [boolean]
-v, --vaa vaa in hex format [string] [required]
-n, --network Network
[required] [choices: "mainnet", "testnet", "devnet"]
--guardian-set-index, --gsi guardian set index [number]
--signatures, --sigs comma separated list of signatures [string]
--wormscanurl, --wsu url to wormscan entry for the vaa that
includes signatures [string]
--wormscan, --ws if specified, will query the wormscan entry
for the vaa to get the signatures [boolean]
--emitter-chain-id, --ec emitter chain id to be used in the vaa
[number]
--emitter-address, --ea emitter address to be used in the vaa[string]
--nonce, --no nonce to be used in the vaa [number]
--sequence, --seq sequence number to be used in the vaa[string]
--consistency-level, --cl consistency level to be used in the vaa
[number]
--timestamp, --ts timestamp to be used in the vaa in unix
seconds [number]
-p, --payload payload in hex format [string]
--guardian-secret, --gs Guardian's secret key [string]
```
??? code "EVM"
```bash
worm evm INSERT_COMMAND
Commands:
worm evm address-from-secret Compute a 20 byte eth address from a 32
byte private key
worm evm storage-update Update a storage slot on an EVM fork
during testing (anvil or hardhat)
worm evm chains Return all EVM chains
worm evm info Query info about the on-chain state of
the contract
worm evm hijack Override the guardian set of the core
bridge contract during testing (anvil
or hardhat)
worm evm start-validator Start a local EVM validator
Options:
--help Show help [boolean]
--version Show version number [boolean]
--rpc RPC endpoint [string]
```
??? code "Generate"
```bash
worm generate INSERT_COMMAND
Commands:
worm generate registration Generate registration VAA
worm generate upgrade Generate contract upgrade VAA
worm generate attestation Generate a token attestation VAA
worm generate recover-chain-id Generate a recover chain ID VAA
worm generate Sets the default delivery provider
set-default-delivery-provider for the Wormhole Relayer contract
Options:
--help Show help [boolean]
--version Show version number [boolean]
-g, --guardian-secret Guardians' secret keys (CSV) [string] [required]
```
??? code "Info"
```bash
worm info INSERT_COMMAND
Commands:
worm info chain-id Print the wormhole chain ID integer
associated with the specified chain
name
worm info contract Print contract address
worm info emitter Print address in emitter address
format
worm info origin Print the origin chain and address
of the asset that corresponds to the
given chain and address.
worm info registrations Print chain registrations
worm info rpc Print RPC address
worm info wrapped Print the wrapped address on the
target chain that corresponds with
the specified origin chain and
address.
Options:
--help Show help [boolean]
--version Show version number [boolean]
```
??? code "NEAR"
```bash
worm near INSERT_COMMAND
Commands:
worm near contract-update Submit a contract update using our specific
APIs
worm near deploy Submit a contract update using near APIs
Options:
--help Show help [boolean]
--version Show version number [boolean]
-m, --module Module to query [choices: "Core", "NFTBridge", "TokenBridge"]
-n, --network Network [required] [choices: "mainnet", "testnet", "devnet"]
--account Near deployment account [string] [required]
--attach Attach some near [string]
--target Near account to upgrade [string]
--mnemonic Near private keys [string]
--key Near private key [string]
-r, --rpc Override default rpc endpoint url [string]
```
??? code "Parse"
```bash
worm parse INSERT_VAA
Positionals:
vaa vaa [string]
Options:
--help Show help [boolean]
--version Show version number [boolean]
```
??? code "Recover"
```bash
worm recover INSERT_DIGEST INSERT_SIGNATURE
Positionals:
digest digest [string]
signature signature [string]
Options:
--help Show help [boolean]
--version Show version number [boolean]
```
??? code "Status"
```bash
worm status INSERT_NETWORK, INSERT_CHAIN, INSERT_TXN_HASH
Positionals:
network Network [choices:
'mainnet',
'testnet',
'devnet']
chain Source chain
[choices:
'unset',
'solana',
'ethereum',
'terra',
'bsc',
'polygon',
'avalanche',
'oasis',
'algorand',
'aurora',
'fantom',
'karura',
'acala',
'klaytn',
'celo',
'near',
'moonbeam',
'neon',
'terra2',
'injective',
'osmosis',
'sui',
'aptos',
'arbitrum',
'optimism',
'gnosis',
'pythnet',
'xpla',
'btc',
'base',
'sei',
'rootstock',
'scroll',
'mantle',
'blast',
'xlayer',
'linea',
'berachain',
'seievm',
'wormchain',
'cosmoshub',
'evmos',
'kujira',
'neutron',
'celestia',
'stargaze',
'seda',
'dymension',
'provenance',
'sepolia',
'arbitrum_sepolia',
'base_sepolia',
'optimism_sepolia',
'holesky',
'polygon_sepolia']
tx Source transaction hash [string]
Options:
--help Show help [boolean]
--version Show version number [boolean]
```
??? code "Submit"
```bash
worm submit INSERT_VAA
Positionals:
vaa vaa [string]
Options:
--help Show help [boolean]
--version Show version number [boolean]
-c, --chain chain name
[choices: 'unset',
'solana',
'ethereum',
'terra',
'bsc',
'polygon',
'avalanche',
'oasis',
'algorand',
'aurora',
'fantom',
'karura',
'acala',
'klaytn',
'celo',
'near',
'moonbeam',
'neon',
'terra2',
'injective',
'osmosis',
'sui',
'aptos',
'arbitrum',
'optimism',
'gnosis',
'pythnet',
'xpla',
'btc',
'base',
'sei',
'rootstock',
'scroll',
'mantle',
'blast',
'xlayer',
'linea',
'berachain',
'seievm',
'wormchain',
'cosmoshub',
'evmos',
'kujira',
'neutron',
'celestia',
'stargaze',
'seda',
'dymension',
'provenance',
'sepolia',
'arbitrum_sepolia',
'base_sepolia',
'optimism_sepolia',
'holesky',
'polygon_sepolia']
-n, --network Network
[required]
[choices:
'mainnet',
'testnet',
'devnet']
-a, --contract-address Contract to submit VAA to (override config) [string]
--rpc RPC endpoint [string]
--all-chains, --ac Submit the VAA to all chains except for the origin
chain specified in the payload
[boolean] [default: false]
```
??? code "Sui"
```bash
worm sui INSERT_COMMAND
Commands:
worm sui build-coin Build wrapped coin and dump bytecode.
Example:
worm sui build-coin -d 8 -v V__0_1_1 -n
testnet -r
"https://fullnode.testnet.sui.io:443"
worm sui deploy Deploy a Sui package
worm sui init-example-message-app Initialize example core message app
worm sui init-token-bridge Initialize token bridge contract
worm sui init-wormhole Initialize wormhole core contract
worm sui publish-example-message Publish message from example app via
core bridge
worm sui setup-devnet Setup devnet by deploying and
initializing core and token bridges and
submitting chain registrations.
worm sui objects Get owned objects by owner
worm sui package-id Get package ID from State object ID
worm sui tx Get transaction details
Options:
--help Show help [boolean]
--version Show version number [boolean]
```
??? code "Transfer"
```bash
worm transfer INSERT_SOURCE_CHAIN, INSERT_DESTINATION_CHAIN, INSERT_DESTINATION_ADDRESS, INSERT_AMOUNT, INSERT_NETWORK
Options:
--help Show help [boolean]
--version Show version number [boolean]
--src-chain source chain [required] [choices:
'solana',
'ethereum',
'terra',
'bsc',
'polygon',
'avalanche',
'oasis',
'algorand',
'aurora',
'fantom',
'karura',
'acala',
'klaytn',
'celo',
'near',
'moonbeam',
'neon',
'terra2',
'injective',
'osmosis',
'sui',
'aptos',
'arbitrum',
'optimism',
'gnosis',
'pythnet',
'xpla',
'btc',
'base',
'sei',
'rootstock',
'scroll',
'mantle',
'blast',
'xlayer',
'linea',
'berachain',
'seievm',
'wormchain',
'cosmoshub',
'evmos',
'kujira',
'neutron',
'celestia',
'stargaze',
'seda',
'dymension',
'provenance',
'sepolia',
'arbitrum_sepolia',
'base_sepolia',
'optimism_sepolia',
'holesky',
'polygon_sepolia']
--dst-chain destination chain
[required] [choices:
'solana',
'ethereum',
'terra',
'bsc',
'polygon',
'avalanche',
'oasis',
'algorand',
'aurora',
'fantom',
'karura',
'acala',
'klaytn',
'celo',
'near',
'moonbeam',
'neon',
'terra2',
'injective',
'osmosis',
'sui',
'aptos',
'arbitrum',
'optimism',
'gnosis',
'pythnet',
'xpla',
'btc',
'base',
'sei',
'rootstock',
'scroll',
'mantle',
'blast',
'xlayer',
'linea',
'berachain',
'seievm',
'wormchain',
'cosmoshub',
'evmos',
'kujira',
'neutron',
'celestia',
'stargaze',
'seda',
'dymension',
'provenance',
'sepolia',
'arbitrum_sepolia',
'base_sepolia',
'optimism_sepolia',
'holesky',
'polygon_sepolia']
--dst-addr destination address [string] [required]
--token-addr token address [string] [default: native token]
--amount token amount [string] [required]
-n, --network Network [required] [choices: "mainnet", "testnet", "devnet"]
--rpc RPC endpoint [string]
```
??? code "Verify VAA"
```bash
worm verify-vaa INSERT_VAA, INSERT_NETWORK
Options:
--help Show help [boolean]
--version Show version number [boolean]
-v, --vaa vaa in hex format [string] [required]
-n, --network Network [required] [choices: "mainnet", "testnet", "devnet"]
```
## Examples
### VAA generation
Use `generate` to create VAAs for testing. For example, use the following command to create an NFT bridge registration VAA:
```bash
worm generate registration --module NFTBridge \
--chain bsc \
--contract-address 0x706abc4E45D419950511e474C7B9Ed348A4a716c \
--guardian-secret cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0
```
The below example generates a token attestation VAA:
```bash
worm generate attestation --emitter-chain ethereum \
--emitter-address 11111111111111111111111111111115 \
--chain ethereum \
--token-address 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 \
--decimals 6 \
--symbol USDC \
--name USDC \
--guardian-secret cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0
```
### VAA parsing
Use `parse` to parse a VAA into JSON:
```bash
worm parse $(worm-fetch-governance 13940208096455381020)
```
This example will fetch governance VAA `13940208096455381020` and print it as JSON:
```bash
# ...signatures elided
timestamp: 1651416474,
nonce: 1570649151,
emitterChain: 1,
emitterAddress: '0000000000000000000000000000000000000000000000000000000000000004',
sequence: 13940208096455381020n,
consistencyLevel: 32,
payload: {
module: 'Core',
type: 'GuardianSetUpgrade',
chain: 0,
newGuardianSetIndex: 2,
newGuardianSetLength: 19,
newGuardianSet: [
'58cc3ae5c097b213ce3c81979e1b9f9570746aa5',
'ff6cb952589bde862c25ef4392132fb9d4a42157',
'114de8460193bdf3a2fcf81f86a09765f4762fd1',
'107a0086b32d7a0977926a205131d8731d39cbeb',
'8c82b2fd82faed2711d59af0f2499d16e726f6b2',
'11b39756c042441be6d8650b69b54ebe715e2343',
'54ce5b4d348fb74b958e8966e2ec3dbd4958a7cd',
'66b9590e1c41e0b226937bf9217d1d67fd4e91f5',
'74a3bf913953d695260d88bc1aa25a4eee363ef0',
'000ac0076727b35fbea2dac28fee5ccb0fea768e',
'af45ced136b9d9e24903464ae889f5c8a723fc14',
'f93124b7c738843cbb89e864c862c38cddcccf95',
'd2cc37a4dc036a8d232b48f62cdd4731412f4890',
'da798f6896a3331f64b48c12d1d57fd9cbe70811',
'71aa1be1d36cafe3867910f99c09e347899c19c3',
'8192b6e7387ccd768277c17dab1b7a5027c0b3cf',
'178e21ad2e77ae06711549cfbb1f9c7a9d8096e8',
'5e1487f35515d02a92753504a8d75471b9f49edb',
'6fbebc898f403e4773e95feb15e80c9a99c8348d'
]
}
```
### Submitting VAAs
Use `submit` to submit a VAA to a chain. It first parses the VAA and determines the destination chain and module. For example, a contract upgrade contains both the target chain and module, so the only required argument is the network moniker (`mainnet` or `testnet`):
```bash
worm submit $(cat my-nft-registration.txt) --network mainnet
```
The script will ask you to specify the target chain for VAAs that don't have a specific target chain (like registrations or Guardian set upgrades). For example, to submit a Guardian set upgrade on all chains, simply run:
```bash
worm-fetch-governance 13940208096455381020 > guardian-upgrade.txt
worm submit $(cat guardian-upgrade.txt) --network mainnet --chain oasis
worm submit $(cat guardian-upgrade.txt) --network mainnet --chain aurora
worm submit $(cat guardian-upgrade.txt) --network mainnet --chain fantom
worm submit $(cat guardian-upgrade.txt) --network mainnet --chain karura
worm submit $(cat guardian-upgrade.txt) --network mainnet --chain acala
worm submit $(cat guardian-upgrade.txt) --network mainnet --chain klaytn
worm submit $(cat guardian-upgrade.txt) --network mainnet --chain avalanche
worm submit $(cat guardian-upgrade.txt) --network mainnet --chain polygon
worm submit $(cat guardian-upgrade.txt) --network mainnet --chain bsc
worm submit $(cat guardian-upgrade.txt) --network mainnet --chain solana
worm submit $(cat guardian-upgrade.txt) --network mainnet --chain terra
worm submit $(cat guardian-upgrade.txt) --network mainnet --chain ethereum
worm submit $(cat guardian-upgrade.txt) --network mainnet --chain celo
```
The VAA payload type (Guardian set upgrade) specifies that this VAA should go to the core bridge, and the tool directs it there.
### Getting Info
To get info about a contract (only EVM supported at this time), use the following command:
```bash
worm evm info -c bsc -n mainnet -m TokenBridge
```
Running this command generates the following output:
```bash
{
"address": "0xB6F6D86a8f9879A9c87f643768d9efc38c1Da6E7",
"wormhole": "0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B",
"implementation": "0x621199f6beB2ba6fbD962E8A52A320EA4F6D4aA3",
"isInitialized": true,
"tokenImplementation": "0x7f8C5e730121657E17E452c5a1bA3fA1eF96f22a",
"chainId": 4,
"finality": 15,
"evmChainId": "56",
"isFork": false,
"governanceChainId": 1,
"governanceContract": "0x0000000000000000000000000000000000000000000000000000000000000004",
"WETH": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
"registrations": {
"Solana": "0xec7372995d5cc8732397fb0ad35c0121e0eaa90d26f828a534cab54391b3a4f5",
"Ethereum": "0x0000000000000000000000003ee18b2214aff97000d974cf647e7c347e8fa585",
"Terra": "0x0000000000000000000000007cf7b764e38a0a5e967972c1df77d432510564e2",
"Polygon": "0x0000000000000000000000005a58505a96d1dbf8df91cb21b54419fc36e93fde",
"Avalanche": "0x0000000000000000000000000e082f06ff657d94310cb8ce8b0d9a04541d8052",
"Oasis": "0x0000000000000000000000005848c791e09901b40a9ef749f2a6735b418d7564",
"Algorand": "0x67e93fa6c8ac5c819990aa7340c0c16b508abb1178be9b30d024b8ac25193d45",
"Aurora": "0x00000000000000000000000051b5123a7b0f9b2ba265f9c4c8de7d78d52f510f",
"Fantom": "0x0000000000000000000000007c9fc5741288cdfdd83ceb07f3ea7e22618d79d2",
"Karura": "0x000000000000000000000000ae9d7fe007b3327aa64a32824aaac52c42a6e624",
"Acala": "0x000000000000000000000000ae9d7fe007b3327aa64a32824aaac52c42a6e624",
"Klaytn": "0x0000000000000000000000005b08ac39eaed75c0439fc750d9fe7e1f9dd0193f",
"Celo": "0x000000000000000000000000796dff6d74f3e27060b71255fe517bfb23c93eed",
"Near": "0x148410499d3fcda4dcfd68a1ebfcdddda16ab28326448d4aae4d2f0465cdfcb7",
"Moonbeam": "0x000000000000000000000000b1731c586ca89a23809861c6103f0b96b3f57d92",
"Neon": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Terra2": "0xa463ad028fb79679cfc8ce1efba35ac0e77b35080a1abe9bebe83461f176b0a3",
"Injective": "0x00000000000000000000000045dbea4617971d93188eda21530bc6503d153313",
"Osmosis": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Sui": "0xccceeb29348f71bdd22ffef43a2a19c1f5b5e17c5cca5411529120182672ade5",
"Aptos": "0x0000000000000000000000000000000000000000000000000000000000000001",
"Arbitrum": "0x0000000000000000000000000b2402144bb366a632d14b83f244d2e0e21bd39c",
"Optimism": "0x0000000000000000000000001d68124e65fafc907325e3edbf8c4d84499daa8b",
"Gnosis": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Pythnet": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Xpla": "0x8f9cf727175353b17a5f574270e370776123d90fd74956ae4277962b4fdee24c",
"Btc": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Base": "0x0000000000000000000000008d2de8d2f73f1f4cab472ac9a881c9b123c79627",
"Sei": "0x86c5fd957e2db8389553e1728f9c27964b22a8154091ccba54d75f4b10c61f5e",
"Rootstock": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Scroll": "0x00000000000000000000000024850c6f61c438823f01b7a3bf2b89b72174fa9d",
"Mantle": "0x00000000000000000000000024850c6f61c438823f01b7a3bf2b89b72174fa9d",
"Blast": "0x00000000000000000000000024850c6f61c438823f01b7a3bf2b89b72174fa9d",
"Xlayer": "0x0000000000000000000000005537857664b0f9efe38c9f320f75fef23234d904",
"Linea": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Berachain": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Seievm": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Snaxchain": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Wormchain": "0xaeb534c45c3049d380b9d9b966f9895f53abd4301bfaff407fa09dea8ae7a924",
"Cosmoshub": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Evmos": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Kujira": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Neutron": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Celestia": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Stargaze": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Seda": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Dymension": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Provenance": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Sepolia": "0x0000000000000000000000000000000000000000000000000000000000000000",
"ArbitrumSepolia": "0x0000000000000000000000000000000000000000000000000000000000000000",
"BaseSepolia": "0x0000000000000000000000000000000000000000000000000000000000000000",
"OptimismSepolia": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Holesky": "0x0000000000000000000000000000000000000000000000000000000000000000",
"PolygonSepolia": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
}
```
### Additional Info Examples
You can get the contract address for a module as follows:
```bash
worm info rpc INSERT_NETWORK INSERT_CHAIN INSERT_MODULE
```
To get the contract address for `NFTBridge` on BSC Mainnet, for example, you can provide the following command:
```bash
worm info contract mainnet bsc NFTBridge
```
You can get the RPC address for a chain as follows:
```bash
worm info rpc INSERT_NETWORK INSERT_CHAIN
```
To get the RPC address for BSC Mainnet, for example, you can provide the following command:
```bash
worm info rpc mainnet bsc
```
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/build/toolkit/dev-env/
--- BEGIN CONTENT ---
---
title: Local Dev Environment
description: Learn how to configure a development environment to build with Wormhole, including using the CLI, local validators, testing on public test networks, and more.
categories: Solidity-SDK, Typescript-SDK
---
# Development Environment
Developers building for smart contract integration will want to set up a development environment to allow testing the full integration, possibly including VAA generation and relaying.
## Tooling Installation
The [Wormhole CLI Tool](/docs/build/toolkit/cli/){target=\_blank} should be installed regardless of the environments chosen. Each environment has its own set of recommended tools. To begin working with a specific environment, see the recommended tools on the respective [environment page](/docs/build/start-building/supported-networks/){target=\_blank}.
## Development Stages
Different approaches to development and testing are recommended at various stages of application development.
### Initial Development
During the initial development of an on-chain application, the best option is to use the native tools available in the environment. You can visit the following resources for more information:
- **[Environment](https://github.com/wormhole-foundation/wormhole){target=\_blank}** - select the folder for the desired network to learn about the recommended native toolset
- **[Mock Guardian](https://github.com/wormhole-foundation/wormhole/blob/main/sdk/js/src/mock/wormhole.ts){target=\_blank}** - it's recommended to set up a mock Guardian or Emitter to provide signed VAAsFor any program methods that require some message be sent or received.
- **[Wormhole Scaffolding repository](https://github.com/wormhole-foundation/wormhole-scaffolding/blob/main/evm/ts-test/01_hello_world.ts){target=\_blank}** - example mock Guardian test
Relying on native tools when possible allows for more rapid prototyping and iteration.
### Integration
For integration to Wormhole and with multiple chains, the simplest option is to use the chains' Testnets. In choosing which chains to use for integration testing, consider which chains in a given environment provide easy access to Testnet tokens and where block times are fast. Find links for Testnet faucets in the [blockchain details section](/docs/build/start-building/supported-networks/){target=\_blank}. A developer may prefer standing up a set of local validators instead of using the Testnet. For this option, [Tilt](https://github.com/wormhole-foundation/wormhole/blob/main/DEVELOP.md){target=\_blank} is available to run local instances of all the chains Wormhole supports.
!!! note
Variation in host environments causes unique issues, and the computational intensity of multiple simultaneous local validators can make setting them up difficult or time-consuming. You may prefer Testnets for the simplest integration testing.
### Prepare for Deployment
Once you've finished the application's initial development and performed integration testing, you should set up a CI test environment. The best option for that is likely to be [Tilt](https://tilt.dev/){target=\_blank} since it allows you to spin up any chains supported by Wormhole in a consistent environment.
## Validator Setup with Tilt
### Tilt
If you'd like to set up a local validator environment, follow the setup guide for Tilt. Tilt is a full-fledged Kubernetes deployment of every chain connected to Wormhole, along with a Guardian node. It usually takes 30 minutes to spin up fully, but it comes with all chains running out of the box. Refer to the [Tilt](https://github.com/wormhole-foundation/wormhole/blob/main/DEVELOP.md){target=\_blank} page for a complete guide to setting up and configuring Tilt.
## Deploying to Public Networks
### Testnet
When doing integration testing on Testnets, remember that a single Guardian node is watching for transactions on various test networks. Because Testnets only have a single Guardian, there's a slight chance that your VAAs won't be processed. This rate doesn't indicate performance on Mainnet, where 19 Guardians are watching for transactions. The Testnet contract addresses are available on the page for each [environment](/docs/build/start-building/supported-networks/){target=\_blank}. The [Wormholescan API](https://docs.wormholescan.io){target=\_blank} offers the following Guardian equivalent Testnet endpoint:
```text
https://api.testnet.wormholescan.io
```
### Mainnet
The Mainnet contract addresses are available on the page for each [environment](/docs/build/start-building/supported-networks/){target=\_blank}. The [Wormholescan API](https://docs.wormholescan.io){target=\_blank} offers the following Guardian equivalent Mainnet endpoint:
```text
https://api.wormholescan.io
```
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/build/toolkit/faqs/
--- BEGIN CONTENT ---
---
title: Toolkit FAQs
description: FAQs on Wormhole Toolkit, covering Wormholescan, CLI, SDKs (TypeScript, Solidity), Tilt, error handling, transaction history, and manual VAA submission.
categories: Solidity-SDK, Typescript-SDK
---
# Toolkit FAQs
## Why does the `toNative` function in the TypeScript SDK return an error?
The `toNative` function may return an error if the platform-specific module (such as Solana or EVM) is not correctly imported or passed into the Wormhole constructor.
To fix this, ensure the relevant platform module is imported and included when initializing Wormhole. For example, if you're working with Solana, make sure to import the Solana module and pass it into the Wormhole constructor like this:
```typescript
import solana from '@wormhole-foundation/sdk/solana';
const wh = await wormhole('Testnet', [solana]);
```
## How can I retrieve the history of previously bridged transactions?
To retrieve the history of previously bridged transactions, you can use the Wormholescan API. Use the following endpoint to query the transaction history for a specific address:
```bash
https://api.wormholescan.io/api/v1/operations?address=INSERT_ADDRESS
```
Simply replace `INSERT_ADDRESS_HERE` with the address you want to query. The API will return a list of operations, including details about previously bridged transactions.
???- example "Fetch transaction history for a specific address"
```bash
curl -X GET "https://api.wormholescan.io/api/v1/operations?address=0x05c009C4C1F1983d4B915C145F4E782de23d3A38" -H "accept: application/json"
```
## How can I manually submit a VAA to a destination chain in the correct format?
To manually submit a VAA (Verifiable Action Approval) to a destination chain, follow these steps:
1. **Obtain the VAA in Base64 format** - navigate to the **Advanced** tab in [Wormholescan](https://wormholescan.io/){target=\_blank} to find the VAA associated with the transaction you want to submit and copy the VAA in base64 format
```bash
https://wormholescan.io/#/tx/INSERT_TX_HASH?view=advanced
```
2. **Convert the VAA to hex** - you must convert the base64 VAA into a hexadecimal (hex) format before submitting it to the destination chain. This can be done using various online tools or via command-line utilities like `xxd` or a script in a language like Python
3. **Submit the VAA through Etherscan (for EVM chains)** - once the VAA is in hex format, go to the [Etherscan UI](https://etherscan.io/){target=\_blank} and submit it through the [`TokenBridge`](https://github.com/wormhole-foundation/wormhole-solidity-sdk/blob/main/src/interfaces/ITokenBridge.sol){target=\_blank} contract’s method (such as the `CompleteTransfer` function or `CompleteTransferWithPayload`)
- The `TokenBridge` contract addresses for each chain are available in the [Wormhole contract addresses](/docs/build/reference/contract-addresses/){target=\_blank} section
- Interact with the smart contract through the Etherscan UI by pasting the hex-encoded VAA into the appropriate field
Following these steps, you can manually submit a VAA in the proper format to a destination chain.
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/build/toolkit/typescript-sdk/
--- BEGIN CONTENT ---
---
title: Wormhole SDK
description: The Wormhole SDK provides tools for cross-chain communication, token bridges, and more, enabling developers to integrate with multiple blockchain environments.
categories: Typescript-SDK
---
# Wormhole SDK
## Get Started
The Wormhole SDK provides developers with essential tools for cross-chain communication, token bridges, and more. This SDK enables seamless interaction between different blockchain environments with a focus on performance and usability.
- :octicons-book-16:{ .lg .middle } **Wormhole SDK**
---
Learn about the core functionalities of the Wormhole SDK, including how to use its features for building cross-chain applications.
[:custom-arrow: Explore the SDK](/docs/build/toolkit/typescript-sdk/wormhole-sdk/)
- :octicons-code-16:{ .lg .middle } **Layouts**
---
Discover how to define, serialize, and deserialize data structures using the Wormhole SDK's layout system, ensuring efficient cross-chain communication.
[:custom-arrow: Learn about layouts](/docs/build/toolkit/typescript-sdk/sdk-layout/)
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/build/toolkit/typescript-sdk/protocols-payloads/
--- BEGIN CONTENT ---
---
title: Building Protocols and Payloads
description: Learn how to build, register, and integrate protocols and payloads in the Wormhole TypeScript SDK with type-safe layouts.
categories: Typescript-SDK
---
# Building Protocols and Payloads
## Introduction
The [Wormhole TypeScript SDK](https://github.com/wormhole-foundation/wormhole-sdk-ts){target=\_blank} provides a flexible and powerful system for integrating cross-chain communication into your applications. A key feature of the SDK is its ability to define protocols—modular units representing distinct functionalities—and their associated payloads, which encapsulate the data required for specific operations within those protocols.
This guide will help you understand how to build protocols and payloads in the SDK, covering:
- The role of protocols and payloads in cross-chain communication
- The mechanics of registering protocols and payloads using the SDK
- Best practices for creating strongly typed layouts to ensure compatibility and reliability
- Real-world examples using the `TokenBridge` as a reference implementation
By the end of this guide, you’ll have a solid understanding of how to define, register, and use protocols and payloads in your projects.
## What is a Protocol?
In the Wormhole SDK, a protocol represents a significant feature or functionality that operates across multiple blockchains. Protocols provide the framework for handling specific types of messages, transactions, or operations consistently and standardized.
Examples of Protocols:
- **`TokenBridge`** - enables cross-chain token transfers, including operations like transferring tokens and relaying payloads
- **`NTT (Native Token Transfers)`** - manages native token movements across chains
Protocols are defined by:
- **A `name`** - a string identifier (e.g., `TokenBridge`, `Ntt`)
- **A set of `payloads`** - these represent the specific actions or messages supported by the protocol, such as `Transfer` or `TransferWithPayload`
Each protocol is registered in the Wormhole SDK, allowing developers to leverage its predefined features or extend it with custom payloads.
## What is a Payload?
A payload is a structured piece of data that encapsulates the details of a specific operation within a protocol. It defines the format, fields, and types of data used in a message or transaction. Payloads ensure consistency and type safety when handling complex cross-chain operations.
Each payload is defined as:
- **A `layout`** - describes the binary format of the payload fields
- **A `literal`** - combines the protocol name and payload name into a unique identifier (e.g., `TokenBridge:Transfer`)
By registering payloads, developers can enforce type safety and enable serialization and deserialization for specific protocol operations.
## Register Protocols and Payloads
Protocols and payloads work together to enable cross-chain communication with precise type safety. For instance, in the `TokenBridge` protocol:
- The protocol is registered under the `TokenBridge` namespace
- Payloads like `Transfer` or `AttestMeta` are linked to the protocol to handle specific operations
Understanding the connection between these components is important for customizing or extending the SDK to suit your needs.
### Register Protocols
Registering a protocol establishes its connection to Wormhole's infrastructure, ensuring it interacts seamlessly with payloads and platforms while maintaining type safety and consistency.
#### How Protocol Registration Works
Protocol registration involves two key tasks:
- **Mapping protocols to interfaces** - connect the protocol to its corresponding interface, defining its expected behavior across networks (`N`) and chains (`C`). This ensures type safety, similar to strong typing, by preventing runtime errors if protocol definitions are incorrect
- **Linking protocols to platforms** - specify platform-specific implementations if needed, or use default mappings for platform-agnostic protocols
For example, here's the `TokenBridge` protocol registration:
```typescript
declare module '../../registry.js' {
export namespace WormholeRegistry {
interface ProtocolToInterfaceMapping {
TokenBridge: TokenBridge;
}
interface ProtocolToPlatformMapping {
TokenBridge: EmptyPlatformMap<'TokenBridge'>;
}
}
}
```
This code snippet:
- Maps the `TokenBridge` protocol to its interface to define how it operates
- Links the protocol to a default platform mapping via `EmptyPlatformMap`
You can view the full implementation in the [`TokenBridge` protocol file](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/core/definitions/src/protocols/tokenBridge/tokenBridge.ts#L14-L70){target=\_blank}.
#### Platform-Specific Protocols
Some protocols require platform-specific behavior. For instance, the EVM-compatible Wormhole Registry maps native addresses for Ethereum-based chains:
```typescript
declare module '@wormhole-foundation/sdk-connect' {
export namespace WormholeRegistry {
interface PlatformToNativeAddressMapping {
Evm: EvmAddress;
}
}
}
registerNative(_platform, EvmAddress);
```
This ensures that `EvmAddress` is registered as the native address type for EVM-compatible platforms. See the [EVM platform address file](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/platforms/evm/src/address.ts#L98-L106){target=\_blank} for details.
### Register Payloads
[Payload registration](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/dbbbc7c365db602dd3b534f6d615ac80c3d2aaf1/core/definitions/src/vaa/registration.ts){target=\_blank} enables developers to define, serialize, and handle custom message types within their protocols. It establishes the connection between a protocol and its payloads, ensuring seamless integration, type enforcement, and runtime efficiency.
This process ties a protocol to its payloads using a combination of:
- **Payload literals** - unique identifiers in the format `:`. These literals map each payload to a layout
- **Payload layouts** - structures that define the binary representation of payload data
- **The payload factory** - a centralized runtime registry that maps payload literals to layouts for dynamic resolution and serialization
These components work together to streamline the definition and management of protocol payloads.
#### How Payload Registration Works
Payload registration involves:
1. **Define payload layouts** - create layouts to structure your payloads. For instance, a protocol might use a `TransferWithPayload` layout:
```typescript
export const transferWithPayloadLayout = <
const P extends CustomizableBytes = undefined
>(
customPayload?: P
) =>
[
payloadIdItem(3),
...transferCommonLayout,
{ name: 'from', ...universalAddressItem },
customizableBytes({ name: 'payload' }, customPayload),
] as const;
```
2. **Register payloads** - use `registerPayloadTypes` to map payload literals to their layouts:
```typescript
registerPayloadTypes('ProtocolName', protocolNamedPayloads);
```
3. **Access registered payloads** - use the [`getPayloadLayout`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/9105de290c91babbf8ad031bd89cc75ee38739c8/core/definitions/src/vaa/functions.ts#L19-L23){target=\_blank} function to fetch the layout for a specific payload literal. This method ensures that the correct layout is retrieved dynamically and safely:
```typescript
const layout = getPayloadLayout('ProtocolName:PayloadName');
```
These steps link payload literals and their layouts, enabling seamless runtime handling.
#### The Payload Factory
At the core of the payload registration process is the `payloadFactory`, a registry that manages the mapping between payload literals and layouts:
```typescript
export const payloadFactory = new Map();
export function registerPayloadType(
protocol: ProtocolName,
name: string,
layout: Layout
) {
const payloadLiteral = composeLiteral(protocol, name);
if (payloadFactory.has(payloadLiteral)) {
throw new Error(`Payload type ${payloadLiteral} already registered`);
}
payloadFactory.set(payloadLiteral, layout);
}
```
- The `payloadFactory` ensures each payload literal maps to its layout uniquely
- The [`registerPayloadType`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/dbbbc7c365db602dd3b534f6d615ac80c3d2aaf1/core/definitions/src/vaa/registration.ts#L46-L52){target=\_blank} function adds individual payloads, while [`registerPayloadTypes`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/dbbbc7c365db602dd3b534f6d615ac80c3d2aaf1/core/definitions/src/vaa/registration.ts#L62-L64){target=\_blank} supports bulk registration
This implementation ensures dynamic, efficient handling of payloads at runtime.
## Integrate Protocols with Payloads
Integrating payloads with protocols enables dynamic identification through payload literals, while serialization and deserialization ensure their binary representation is compatible across chains. For more details on these processes, refer to the [Layouts page](/docs/build/toolkit/typescript-sdk/sdk-layout/){target=\_blank}.
### Payload Discriminators
Payload discriminators are mechanisms in the Wormhole SDK that dynamically identify and map incoming payloads to their respective layouts at runtime. They are relevant for protocols like `TokenBridge`, enabling efficient handling of diverse payload types while ensuring type safety and consistent integration.
#### How Discriminators Work
Discriminators evaluate serialized binary data and determine the corresponding payload layout by inspecting fixed fields or patterns within the data. Each payload layout is associated with a payload literal (e.g., `TokenBridge:Transfer` or `TokenBridge:TransferWithPayload`).
This system ensures:
- **Dynamic runtime identification** - payloads are parsed based on their content, even if a single protocol handles multiple payload types
- **Strict type enforcement** - discriminators leverage layout mappings to prevent invalid payloads from being processed
Below is an example of how the Wormhole SDK builds a discriminator to distinguish between payload layouts:
```typescript
export function layoutDiscriminator(
layouts: readonly Layout[],
allowAmbiguous?: B
): Discriminator {
// Internal logic to determine distinguishable layouts
const [distinguishable, discriminator] = internalBuildDiscriminator(layouts);
if (!distinguishable && !allowAmbiguous) {
throw new Error('Cannot uniquely distinguish the given layouts');
}
return (
!allowAmbiguous
? (encoded: BytesType) => {
const layout = discriminator(encoded);
return layout.length === 0 ? null : layout[0];
}
: discriminator
) as Discriminator;
}
```
- [`layoutDiscriminator`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/9105de290c91babbf8ad031bd89cc75ee38739c8/core/base/src/utils/layout.ts#L16){target=\_blank} takes a list of layouts and generates a function that can identify the appropriate layout for a given serialized payload
- The `allowAmbiguous` parameter determines whether layouts with overlapping characteristics are permitted
### Real-World Example: Token Bridge Protocol
Integrating protocols with their respective payloads exemplifies how the Wormhole SDK leverages layouts and type-safe registration mechanisms to ensure efficient cross-chain communication. This section focuses on how protocols like `TokenBridge` use payloads to facilitate specific operations.
#### Token Bridge Protocol and Payloads
The `TokenBridge` protocol enables cross-chain token transfers through its payloads. Key payloads include:
- **`Transfer`** - handles basic token transfer operations
- **`TransferWithPayload`** - extends the `Transfer` payload to include custom data, enhancing functionality
Payloads are registered to the `TokenBridge` protocol via the `PayloadLiteralToLayoutMapping` interface, which links payload literals (e.g., `TokenBridge:Transfer`) to their layouts.
Additionally, the protocol uses reusable layouts like [`transferCommonLayout`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/76b20317b0f68e823d4e6c4a2e41bb2a7705c64f/core/definitions/src/protocols/tokenBridge/tokenBridgeLayout.ts#L29C7-L47){target=\_blank} and extends them in more specialized layouts such as [`transferWithPayloadLayout`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/76b20317b0f68e823d4e6c4a2e41bb2a7705c64f/core/definitions/src/protocols/tokenBridge/tokenBridgeLayout.ts#L49-L57){target=\_blank}:
```typescript
export const transferWithPayloadLayout = <
const P extends CustomizableBytes = undefined
>(
customPayload?: P
) =>
[
payloadIdItem(3),
...transferCommonLayout,
{ name: 'from', ...universalAddressItem },
customizableBytes({ name: 'payload' }, customPayload),
] as const;
```
This layout includes:
- A `payloadIdItem` to identify the payload type
- Common fields for token and recipient details
- A customizable `payload` field for additional data
#### Use the Discriminator
To manage multiple payloads, the `TokenBridge` protocol utilizes a discriminator to distinguish between payload types dynamically. For example:
```typescript
const tokenBridgePayloads = ['Transfer', 'TransferWithPayload'] as const;
export const getTransferDiscriminator = lazyInstantiate(() =>
payloadDiscriminator([_protocol, tokenBridgePayloads])
);
```
- The [`getTransferDiscriminator`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/dbbbc7c365db602dd3b534f6d615ac80c3d2aaf1/core/definitions/src/protocols/tokenBridge/tokenBridge.ts#L67-L70){target=\_blank} function dynamically evaluates payloads using predefined layouts
- This ensures that each payload type is processed according to its unique structure and type-safe layout
#### Register Payloads to Protocols
Here’s how the `TokenBridge` protocol connects its payloads to the Wormhole SDK:
```typescript
declare module '../../registry.js' {
export namespace WormholeRegistry {
interface PayloadLiteralToLayoutMapping
extends RegisterPayloadTypes<
'TokenBridge',
typeof tokenBridgeNamedPayloads
> {}
}
}
registerPayloadTypes('TokenBridge', tokenBridgeNamedPayloads);
```
This registration links the `TokenBridge` payload literals to their respective layouts, enabling serialization and deserialization at runtime.
You can explore the complete `TokenBridge` protocol and payload definitions in the [`TokenBridge` layout file](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/core/definitions/src/protocols/tokenBridge/tokenBridgeLayout.ts){target=\_blank}.
#### Token Bridge Payloads
The following payloads are registered for the `TokenBridge` protocol:
- **`AttestMeta`** - used for token metadata attestation
- **`Transfer`** - facilitates token transfers
- **`TransferWithPayload`** - adds a custom payload to token transfers
These payloads and their layouts are defined in the [`TokenBridge` layout file](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/core/definitions/src/protocols/tokenBridge/tokenBridgeLayout.ts){target=\_blank}.
### Other Protocols: Native Token Transfers (NTT)
While this guide focuses on the `TokenBridge` protocol, other protocols, like NTT, follow a similar structure.
- NTT manages the transfer of native tokens across chains
- Payloads such as `WormholeTransfer` and `WormholeTransferStandardRelayer` are registered to the protocol using the same patterns for payload literals and layouts
- The same mechanisms for type-safe registration and payload discriminators apply, ensuring reliability and extensibility
For more details, you can explore the [NTT implementation in the SDK](https://github.com/wormhole-foundation/example-native-token-transfers/blob/00f83aa215338b1b8fd66f522bd0f45be3e98a5a/sdk/definitions/src/ntt.ts){target=\_blank}.
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/build/toolkit/typescript-sdk/sdk-layout/
--- BEGIN CONTENT ---
---
title: Data Layouts
description: Learn how to efficiently define, serialize, and deserialize data structures using Wormhole SDK's layout system for cross-chain communication.
categories: Typescript-SDK
---
# Data Layouts
## Introduction
The [Wormhole SDK](https://github.com/wormhole-foundation/wormhole-sdk-ts){target=\_blank} uses the [layout package](https://www.npmjs.com/package/binary-layout){target=\_blank} to define, serialize, and deserialize data structures efficiently. This modular system ensures consistent data formatting and cross-environment compatibility, benefiting projects that require robust handling of structured data.
By understanding the layout mechanism, you’ll be able to:
- Define data structures (numbers, arrays, and custom types)
- Efficiently serialize and deserialize data using the SDK’s utilities
- Handle protocol-specific layouts with ease
This guide is beneficial for developers looking to integrate Wormhole into their applications or protocols, especially those dealing with complex payloads or cross-chain communication.
## Key Concepts
### Layout Items
A layout defines how data structures should be serialized (converted into binary format) and deserialized (converted back into their original structure). This ensures consistent data formatting when transmitting information across different blockchain environments.
Layouts are composed of [layout items](https://github.com/nonergodic/layout/blob/main/src/items.ts){target=\_blank}, which describe individual fields or sets of fields in your data. Each layout item specifies:
- **`name`** - name of the field
- **`binary`** - type of data (e.g., `uint`, `bytes`)
- **`size`** - byte length for fixed-size fields within uint and bytes items only
Layout items can represent:
- **Primitive types** - basic data types like unsigned integers (`uint`) or byte arrays (`bytes`)
- **Composite types** - more complex structures, such as arrays or nested objects
Below is an example of a layout that might be used to serialize a message across the Wormhole protocol:
```typescript
const exampleLayout = [
{ name: 'sourceChain', binary: 'uint', size: 2 },
{ name: 'orderSender', binary: 'bytes', size: 32 },
{ name: 'redeemer', binary: 'bytes', size: 32 },
{ name: 'redeemerMessage', binary: 'bytes', lengthSize: 4 },
] as const;
```
In this example:
- `sourceChain` is a 2-byte unsigned integer (`uint`) identifying the source blockchain
- `orderSender` is a fixed-length 32-byte array representing the sender's address
- `redeemer` is another 32-byte array used for the redeemer’s address
- `redeemerMessage` is a variable-length byte sequence, with its length specified by a 4-byte integer
This layout definition ensures that all necessary data fields are consistently encoded and can be correctly interpreted when they are deserialized.
### Serialization and Deserialization
Serialization converts structured data into binary format; deserialization reverses this, reconstructing the original objects.
You can serialize data using the `serializeLayout` function:
```typescript
const serialized = serializeLayout(fillLayout, exampleFill);
```
To deserialize the binary data back into a structured object, use the `deserializeLayout` function:
```typescript
const deserialized = deserializeLayout(fillLayout, serialized);
```
### Custom Conversions
Layouts also allow for custom conversions, which help map complex or custom types (like chain IDs or universal addresses) into a more usable format. This is useful when serializing or deserializing data that doesn’t fit neatly into simple types like integers or byte arrays.
For example, consider a custom conversion for a chain ID:
```typescript
const chainCustomConversion = {
to: (chainId: number) => toChain(chainId),
from: (chain: Chain) => chainToChainId(chain),
} satisfies CustomConversion;
```
This setup allows Wormhole to convert between human-readable formats and binary-encoded data used in payloads.
### Error Handling
The layout system performs error checks during serialization and deserialization. An error is thrown if data is incorrectly sized or in the wrong format. Refer to the below example:
```typescript
try {
deserializeLayout(fillLayout, corruptedData);
} catch (error) {
console.error('Error during deserialization:', error.message);
}
```
## Application of Layouts
This section will focus on applying the concepts explained earlier through examples. These will help developers better understand how to define layouts, serialize and deserialize data, and use custom conversions where needed.
### Defining Layouts
To get started with layouts in Wormhole, you need to define your structure. A layout is simply a list of fields (layout items) describing how each data piece will be serialized.
Consider the following layout for a payload:
```typescript
const exampleLayout = [
{ name: 'sourceChain', binary: 'uint', size: 2 },
{ name: 'orderSender', binary: 'bytes', size: 32 },
{ name: 'redeemer', binary: 'bytes', size: 32 },
{ name: 'redeemerMessage', binary: 'bytes', lengthSize: 4 },
] as const;
```
In this example:
- `sourceChain` is an unsigned integer (uint) of 2 bytes
- `orderSender` is a 32-byte fixed-length byte array
- `redeemer` is another 32-byte byte array
- `redeemerMessage` is a length-prefixed byte array, with the length specified by a 4-byte integer
### Serialize Data
Once a layout is defined, the next step is to serialize data according to that structure. You can accomplish this using the `serializeLayout` function from the Wormhole SDK.
```typescript
const examplePayload = {
sourceChain: 6,
orderSender: new Uint8Array(32),
redeemer: new Uint8Array(32),
redeemerMessage: new Uint8Array([0x01, 0x02, 0x03]),
};
const serializedData = serializeLayout(exampleLayout, examplePayload);
```
This takes the data structure (`examplePayload`) and serializes it according to the rules defined in the layout (`exampleLayout`). The result is a `Uint8Array` representing the serialized binary data.
### Deserialize Data
Deserialization is the reverse of serialization. Given a serialized `Uint8Array`, we can convert it back into its original structure using the `deserializeLayout` function.
```typescript
const deserializedPayload = deserializeLayout(exampleLayout, serializedData);
```
This will output the structured object, making it easy to work with data transmitted or received from another chain.
### Handling Variable-Length Fields
One relevant aspect of Wormhole SDK's layout system is the ability to handle variable-length fields, such as arrays and length-prefixed byte sequences.
For instance, if you want to serialize or deserialize a message where the length of the content isn't known beforehand, you can define a layout item with a `lengthSize` field.
```typescript
{ name: 'message', binary: 'bytes', lengthSize: 4 }
```
This tells the SDK to read or write the message's length (in 4 bytes) and then handle the content.
## Nested Layouts and Strong Typing
The Wormhole SDK simplifies handling complex structures with nested layouts and strong typing. Nested layouts clearly represent hierarchical data, while strong typing ensures data consistency and catches errors during development.
### Nested Layout
In complex protocols, layouts can contain nested structures. Nested layouts become relevant here, allowing you to represent hierarchical data (such as transactions or multi-part messages) in a structured format.
Refer to the following nested layout where a message contains nested fields:
```typescript
const nestedLayout = [
{
name: 'source',
binary: 'bytes',
layout: [
{ name: 'chainId', binary: 'uint', size: 2 },
{ name: 'sender', binary: 'bytes', size: 32 },
],
},
{
name: 'redeemer',
binary: 'bytes',
layout: [
{ name: 'address', binary: 'bytes', size: 32 },
{ name: 'message', binary: 'bytes', lengthSize: 4 },
],
},
] as const satisfies Layout;
```
In this layout:
- `source` is an object with two fields: `chainId` and `sender`
- `redeemer` is another object with two fields: `address` and a length-prefixed `message`
### Strong Typing
One of the benefits of using the Wormhole SDK in TypeScript is its support for strong typing. This ensures that serialized and deserialized data conform to expected structures, reducing errors during development by enforcing type checks at compile time.
Using TypeScript, the `LayoutToType` utility provided by the SDK automatically generates a strongly typed structure based on the layout:
```typescript
type NestedMessage = LayoutToType;
```
This ensures that when you serialize or deserialize data, it matches the expected structure.
```typescript
const message: NestedMessage = {
source: {
chainId: 6,
sender: new Uint8Array(32),
},
redeemer: {
address: new Uint8Array(32),
message: new Uint8Array([0x01, 0x02, 0x03]),
},
};
```
Attempting to assign data of incorrect types will result in a compile-time error. The Wormhole SDK's layout system enforces strong types, reducing runtime errors and improving code reliability.
### Serialization and Deserialization with Nested Layouts
You can serialize and deserialize nested structures in the same way as simpler layouts:
```typescript
const serializedNested = serializeLayout(nestedLayout, message);
const deserializedNested = deserializeLayout(nestedLayout, serializedNested);
```
Strong typing in TypeScript ensures that the message object conforms to the nested layout structure. This reduces the risk of data inconsistency during cross-chain communication.
## Commonly Used Layouts
The Wormhole SDK includes predefined layouts frequently used in cross-chain messaging. These layouts are optimized for standard fields such as chain IDs, addresses, and signatures. You can explore the complete set of predefined layouts in the [`layout-items` directory](https://github.com/wormhole-foundation/wormhole-sdk-ts/tree/main/core/definitions/src/layout-items){target=\_blank} of the Wormhole SDK.
### Chain ID Layouts
Chain ID layouts in the Wormhole SDK derive from a common foundation: `chainItemBase`. This structure defines the binary representation of a chain ID as a 2-byte unsigned integer, ensuring consistency across serialization and deserialization processes.
#### Base Structure
This simple structure is the blueprint for more specific layouts by standardizing the binary format and size.
```typescript
const chainItemBase = { binary: 'uint', size: 2 } as const;
```
#### Dynamic Chain ID Layout
The dynamic chain ID layout, [`chainItem`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/core/definitions/src/layout-items/chain.ts#L13-L40){target=\_blank}, extends `chainItemBase` by adding flexible custom conversion logic. It enables runtime validation of chain IDs, supports optional null values, and restricts chain IDs to a predefined set when needed.
```typescript
export const chainItem = <
const C extends readonly Chain[] = typeof chains,
const N extends boolean = false,
>(opts?: {
allowedChains?: C;
allowNull?: N;
}) =>
({
...chainItemBase, // Builds on the base structure
custom: {
to: (val: number): AllowNull => { ... },
from: (val: AllowNull): number => { ... },
},
});
```
This layout is versatile. It allows the serialization of human-readable chain names (e.g., `Ethereum`) to numeric IDs (e.g., `1`) and vice versa. This is particularly useful when working with dynamic configurations or protocols supporting multiple chains.
#### Fixed Chain ID Layout
The fixed chain ID layout, [`fixedChainItem`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/core/definitions/src/layout-items/chain.ts#L42-L49){target=\_blank}, is more rigid. It also extends `chainItemBase`, but the custom field is hardcoded for a single chain. This eliminates runtime validation and enforces strict adherence to a specific chain.
```typescript
export const fixedChainItem = (chain: C) => ({
...chainItemBase, // Builds on the base structure
custom: {
to: chain,
from: chainToChainId(chain),
},
});
```
This layout allows developers to efficiently serialize and deserialize messages involving a single, fixed chain ID.
### Address Layout
The Wormhole SDK uses a Universal Address Layout to serialize and deserialize blockchain addresses into a standardized format. This layout ensures that addresses are always represented as fixed 32-byte binary values, enabling seamless cross-chain communication.
#### Base Structure
The [`universalAddressItem`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/core/definitions/src/layout-items/universalAddress.ts#L7-L14){target=\_blank} defines the layout for addresses. It uses the binary type bytes and enforces a fixed size of 32 bytes for consistency.
```typescript
export const universalAddressItem = {
binary: 'bytes',
size: 32,
custom: {
to: (val: Uint8Array): UniversalAddress => new UniversalAddress(val),
from: (val: UniversalAddress): Uint8Array => val.toUint8Array(),
} satisfies CustomConversion,
} as const satisfies LayoutItem;
```
This layout ensures consistent address handling by defining the following:
- **Serialization** - converts a high-level `UniversalAddress` object into raw binary (32 bytes) for efficient storage or transmission
- **Deserialization** - converts raw binary back into a `UniversalAddress` object, enabling further interaction in a human-readable or programmatic format
### Signature Layout
In the Wormhole SDK, the Signature Layout defines how to serialize and deserialize cryptographic signatures. These signatures verify message authenticity and ensure data integrity, particularly in Guardian-signed VAAs.
#### Base Structure
The `signatureLayout` specifies the binary structure of a secp256k1 signature. It divides the signature into three components:
```typescript
const signatureLayout = [
{ name: 'r', binary: 'uint', size: 32 },
{ name: 's', binary: 'uint', size: 32 },
{ name: 'v', binary: 'uint', size: 1 },
] as const satisfies Layout;
```
This layout provides a clear binary format for the secp256k1 signature, making it efficient to process within the Wormhole protocol.
#### Layout with Custom Conversion
The [`signatureItem`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/core/definitions/src/layout-items/signature.ts#L15-L22){target=\_blank} builds upon the `signatureLayout` by adding custom conversion logic. This conversion transforms raw binary data into a high-level `Signature` object and vice versa.
```typescript
export const signatureItem = {
binary: 'bytes',
layout: signatureLayout,
custom: {
to: (val: LayoutToType) =>
new Signature(val.r, val.s, val.v),
from: (val: Signature) => ({ r: val.r, s: val.s, v: val.v }),
} satisfies CustomConversion, Signature>,
} as const satisfies BytesLayoutItem;
```
The `custom` field ensures seamless integration of raw binary data with the `Signature` class, encapsulating signature-specific logic.
## Advanced Use Cases
The Wormhole SDK’s layout system is designed to handle various data structures and serialization needs. This section will explore more advanced use cases, such as handling conditional data structures, fixed conversions, and optimizing serialization performance.
???- code "Switch Statements for Conditional Layouts"
In some cases, the structure of serialized data might change based on a specific field, such as a payload ID. The switch layout type conditionally defines layouts based on a value.
For example, different message types can be identified using a payload ID, and the layout for each message can be determined at runtime:
```typescript
const switchLayout = {
binary: 'switch',
idSize: 1, // size of the payload ID
idTag: 'messageType', // tag to identify the type of message
layouts: [
[[1, 'messageType1'], fillLayout], // layout for type 1
[[2, 'messageType2'], fastFillLayout], // layout for type 2
],
} as const satisfies Layout;
```
The switch statement helps developers parse multiple payload types using the same structure, depending on a control field like an ID.
???- code "Fixed Conversions and Omitted Fields"
Fixed conversions and omitted fields allow developers to handle known, static data without including it in every serialization or deserialization operation. For instance, when specific fields in a layout always hold a constant value, they can be omitted from the deserialized object.
**Example: Fixed Conversion**
In some cases, a field may always contain a predefined value. The layout system supports fixed conversions, allowing developers to “hard-code” these values:
```typescript
const fixedConversionLayout = {
binary: 'uint',
size: 2,
custom: {
to: 'Ethereum',
from: chainToChainId('Ethereum'),
},
} as const satisfies Layout;
```
**Example: Omitted Fields**
Omitted fields are useful for handling padding or reserved fields that do not carry meaningful information and can safely be excluded from the deserialized output:
```typescript
const omittedFieldLayout = [
{ name: 'reserved', binary: 'uint', size: 2, omit: true },
] as const satisfies Layout;
```
In this example, `reserved` is a padding field with a fixed, non-dynamic value that serves no functional purpose. It is omitted from the deserialized result but still considered during serialization to maintain the correct binary format.
Only fields with a fixed, known value, such as padding or reserved fields, should be marked as `omit: true`. Fields with meaningful or dynamic information, such as `sourceChain` or `version`, must remain in the deserialized structure to ensure data integrity and allow seamless round-trip conversions between serialized and deserialized representations.
## Integration with Wormhole Protocol
The layout system facilitates seamless interaction with the Wormhole protocol, mainly when dealing with VAAs. These cross-chain messages must be serialized and deserialized to ensure they can be transmitted and processed accurately across different chains.
### VAAs and Layouts
VAAs are the backbone of Wormhole’s cross-chain communication. Each VAA is a signed message encapsulating important information such as the originating chain, the emitter address, a sequence number, and Guardian signatures. The Wormhole SDK leverages its layout system to define, serialize, and deserialize VAAs, ensuring data integrity and chain compatibility.
#### Base VAA Structure
The Wormhole SDK organizes the VAA structure into three key components:
- [**Header**](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/core/definitions/src/vaa/vaa.ts#L37-L41){target=\_blank} - contains metadata such as the Guardian set index and an array of Guardian signatures
- [**Envelope**](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/core/definitions/src/vaa/vaa.ts#L44-L51){target=\_blank} - includes chain-specific details such as the emitter chain, address, sequence, and [consistency (finality) level](/docs/build/reference/consistency-levels/){target=\_blank}
- **Payload** - provides application-specific data, such as the actual message or operation being performed
**Header layout:**
```typescript
const guardianSignatureLayout = [
{ name: 'guardianIndex', binary: 'uint', size: 1 },
{ name: 'signature', ...signatureItem },
] as const satisfies Layout;
export const headerLayout = [
{ name: 'version', binary: 'uint', size: 1, custom: 1, omit: true },
{ name: 'guardianSet', ...guardianSetItem },
{
name: 'signatures',
binary: 'array',
lengthSize: 1,
layout: guardianSignatureLayout,
},
] as const satisfies Layout;
```
The header defines metadata for validating and processing the VAA, such as the Guardian set index and signatures. Each signature is represented using the `signatureItem` layout, ensuring consistency and compatibility across different platforms.
!!! note "Signature Standard Compliance"
The signature field uses the `signatureItem` layout, which is explicitly defined as 65 bytes. This layout is aligned with widely used standards such as EIP-2612 and Uniswap's Permit2, ensuring compatibility with cryptographic protocols and applications.
**Envelope layout:**
```typescript
export const envelopeLayout = [
{ name: 'timestamp', binary: 'uint', size: 4 },
{ name: 'nonce', binary: 'uint', size: 4 },
{ name: 'emitterChain', ...chainItem() },
{ name: 'emitterAddress', ...universalAddressItem },
{ name: 'sequence', ...sequenceItem },
{ name: 'consistencyLevel', binary: 'uint', size: 1 },
] as const satisfies Layout;
```
The envelope encapsulates the VAA's core message data, including chain-specific information like the emitter address and sequence number. This structured layout ensures that the VAA can be securely transmitted across chains.
**Payload Layout:**
The Payload contains the user-defined data specific to the application or protocol, such as a token transfer message, governance action, or other cross-chain operation. The layout of the payload is dynamic and depends on the payload type, identified by the `payloadLiteral` field.
```typescript
const examplePayloadLayout = [
{ name: 'type', binary: 'uint', size: 1 },
{ name: 'data', binary: 'bytes', lengthSize: 2 },
] as const satisfies Layout;
```
This example demonstrates a payload containing:
- A type field specifying the operation type (e.g., transfer or governance action)
- A data field that is length-prefixed and can store operation-specific information
Dynamic payload layouts are selected at runtime using the `payloadLiteral` field, which maps to a predefined layout in the Wormhole SDK.
**Combined Base Layout:**
The base VAA layout combines the header, envelope, and dynamically selected payload layout:
```typescript
export const baseLayout = [...headerLayout, ...envelopeLayout] as const;
```
At runtime, the payload layout is appended to the `baseLayout` to form the complete structure.
#### Serializing VAA Data
The Wormhole SDK provides the [`serialize`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/core/definitions/src/vaa/functions.ts#L48-L54){target=\_blank} function to serialize a VAA message. This function combines the base layout (header and envelope) with the appropriate payload layout, ensuring the message’s format is correct for transmission across chains.
```typescript
import { serialize } from '@wormhole-foundation/sdk-core/vaa/functions';
const vaaData = {
guardianSet: 1,
signatures: [{ guardianIndex: 0, signature: new Uint8Array(65).fill(0) }],
timestamp: 1633000000,
nonce: 42,
emitterChain: 2, // Ethereum
emitterAddress: new Uint8Array(32).fill(0),
sequence: BigInt(1),
consistencyLevel: 1,
payloadLiteral: 'SomePayloadType',
payload: { key: 'value' },
};
const serializedVAA = serialize(vaaData);
```
???- note "How does it work?"
Internally, the serialize function dynamically combines the `baseLayout` (header and envelope) with the payload layout defined by the `payloadLiteral`. The complete layout is then passed to the `serializeLayout` function, which converts the data into binary format.
```typescript
const layout = [
...baseLayout, // Header and envelope layout
payloadLiteralToPayloadItemLayout(vaa.payloadLiteral), // Payload layout
] as const;
return serializeLayout(layout, vaa as LayoutToType);
```
#### Deserializing VAA Data
The Wormhole SDK provides the [`deserialize`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/core/definitions/src/vaa/functions.ts#L162-L200){target=\_blank} function to parse a VAA from its binary format back into a structured object. This function uses the `baseLayout` and payload discriminator logic to ensure the VAA is correctly interpreted.
```typescript
import { deserialize } from '@wormhole-foundation/sdk-core/vaa/functions';
const serializedVAA = new Uint8Array([
/* Serialized VAA binary data */
]);
const vaaPayloadType = 'SomePayloadType'; // The payload type expected for this VAA
const deserializedVAA = deserialize(vaaPayloadType, serializedVAA);
```
???- note "How does it work?"
Internally, the `deserialize` function uses the `baseLayout` (header and envelope) to parse the main VAA structure. It then identifies the appropriate payload layout using the provided payload type or discriminator.
```typescript
const [header, envelopeOffset] = deserializeLayout(headerLayout, data, {
consumeAll: false,
});
const [envelope, payloadOffset] = deserializeLayout(envelopeLayout, data, {
offset: envelopeOffset,
consumeAll: false,
});
const [payloadLiteral, payload] =
typeof payloadDet === 'string'
? [
payloadDet as PayloadLiteral,
deserializePayload(payloadDet as PayloadLiteral, data, payloadOffset),
]
: deserializePayload(
payloadDet as PayloadDiscriminator,
data,
payloadOffset
);
return {
...header,
...envelope,
payloadLiteral,
payload,
} satisfies VAA;
```
### Registering Custom Payloads
In the Wormhole SDK, payloads rely on layouts to define their binary structure, ensuring consistency and type safety across protocols. Custom payloads extend this functionality, allowing developers to handle protocol-specific features or unique use cases.
To learn how to define and register payloads using layouts, refer to the [Building Protocols and Payloads](/docs/build/toolkit/typescript-sdk/protocols-payloads/){target=\_blank} page for a detailed guide.
## Common Pitfalls & Best Practices
When working with the Wormhole SDK layout system, it's important to be aware of a few common issues that can arise. Below are some pitfalls to avoid and best practices to ensure smooth integration.
### Pitfalls to Avoid
#### Defining Sizes for Data Types
When defining sizes for each data type, make sure to match the actual data length to the specified size to prevent serialization and deserialization errors:
- **`uint` and `int`** - the specified size must be large enough to accommodate the data value. For instance, storing a value greater than 255 in a single byte (`uint8`) will fail since it exceeds the byte’s capacity. Similarly, an undersized integer (e.g., specifying 2 bytes for a 4-byte integer) can lead to data loss or deserialization failure
- **`bytes`** - the data must match the specified byte length in the layout. For example, defining a field as 32 bytes (`size: 32`) requires the provided data to be exactly 32 bytes long; otherwise, serialization will fail
```typescript
// Pitfall: Mismatch between the size of data and the defined size in the layout
{ name: 'orderSender', binary: 'bytes', size: 32 }
// If the provided data is not exactly 32 bytes, this will fail
```
#### Incorrectly Defined Arrays
Arrays can be fixed-length or length-prefixed, so it’s important to define them correctly. Fixed-length arrays must match the specified length, while length-prefixed arrays need a `lengthSize` field.
```typescript
// Pitfall: Array length does not match the expected size
{ name: 'redeemerMessage', binary: 'bytes', lengthSize: 4 }
```
### Best Practices
These best practices and common pitfalls can help prevent bugs and improve the reliability of your implementation when working with layouts in the Wormhole SDK.
#### Reuse Predefined Layout Items
Rather than defining sizes or types manually, reuse the predefined layout items provided by the Wormhole SDK. These items ensure consistent formatting and enforce strong typing.
For instance, use the `chainItem` layout for chain IDs or `universalAddressItem` for blockchain addresses:
```typescript
import {
chainItem,
universalAddressItem,
} from '@wormhole-foundation/sdk-core/layout-items';
const exampleLayout = [
{ name: 'sourceChain', ...chainItem() }, // Use predefined chain ID layout
{ name: 'senderAddress', ...universalAddressItem }, // Use universal address layout
] as const;
```
By leveraging predefined layout items, you reduce redundancy, maintain consistency, and ensure compatibility with Wormhole’s standards.
#### Use Class Instances
Whenever possible, convert deserialized data into higher-level class instances. This makes it easier to validate, manipulate, and interact with structured data. For example, the [`UniversalAddress`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/core/definitions/src/universalAddress.ts#L17-L59){target=\_blank} class ensures consistent address handling:
```typescript
import { UniversalAddress } from '@wormhole-foundation/sdk-core';
const deserializedAddress = new UniversalAddress(someBinaryData);
```
Focusing on reusing predefined layout items and converting deserialized data into higher-level abstractions can ensure a more robust and maintainable implementation.
#### Consistent Error Handling
Always handle errors during both serialization and deserialization. Catching exceptions allows you to log or resolve issues gracefully when working with potentially corrupted or invalid data.
```typescript
try {
const deserialized = deserializeLayout(fillLayout, data);
} catch (error) {
console.error('Deserialization failed:', error);
}
```
#### Leverage Reusable Layouts
Creating reusable layouts for commonly repeated structures improves code maintainability and reduces duplication. These layouts can represent fields or combinations of fields frequently encountered in cross-chain communication, such as chain IDs, addresses, and signatures.
For example, define a reusable layout for chain IDs and addresses:
```typescript
const commonLayout = [
{ name: 'chainId', binary: 'uint', size: 2 },
{ name: 'address', binary: 'bytes', size: 32 },
] as const satisfies Layout;
// Reuse the common layout in different contexts
const exampleLayout = [
...commonLayout,
{ name: 'sequence', binary: 'uint', size: 8 },
];
```
By abstracting common elements into a single layout, you ensure consistency across different parts of your application and simplify future updates.
## Performance Considerations
Efficient serialization and deserialization are crucial when handling large amounts of cross-chain data. Below are some strategies and best practices to ensure optimal performance when using Wormhole SDK layouts.
### Lazy Instantiation
Building a discriminator can be resource-intensive for complex or large datasets. The layout structures do not incur significant upfront costs, but deferring the creation of discriminators until needed can improve efficiency.
```typescript
const lazyDiscriminator = lazyInstantiate(() => layoutDiscriminator(layouts));
```
This approach ensures that discriminators are only built when required, helping to optimize performance, especially for complex or conditional layouts.
## Resources
For further learning and practical experience, explore the following resources:
- **Wormhole TypeScript SDK** - the [Wormhole SDK repository](https://github.com/wormhole-foundation/wormhole-sdk-ts){target=\_blank} contains the core implementation of layouts, including predefined layout items and utilities like `serializeLayout` and `deserializeLayout`
- **Layout tests repository** - for hands-on experimentation, check out this [layout package repository](https://github.com/nonergodic/layout){target=\_blank}, which provides examples and unit tests to help you better understand serialization, deserialization, and the strong typing mechanism. Running these tests locally is a great way to deepen your understanding of how layouts function in real-world scenarios
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/build/toolkit/typescript-sdk/vaas-protocols/
--- BEGIN CONTENT ---
---
title: VAAs and Protocols
description: Understand how VAAs enable cross-chain messaging and how to handle them using Wormhole's TypeScript and Solidity SDKs.
categories: Typescript-SDK
---
# VAAs and Protocols
## Introduction
Wormhole's core functionality revolves around [Verifiable Action Approvals](/docs/learn/infrastructure/vaas/){target=\_blank} (VAAs), which are signed messages enabling secure and decentralized communication across chains. This guide focuses on their practical usage within the Wormhole ecosystem, specifically when working with protocol-specific messages in the [TypeScript](https://github.com/wormhole-foundation/wormhole-sdk-ts){target=\_blank} and [Solidity](https://github.com/wormhole-foundation/wormhole-solidity-sdk){target=\_blank} SDKs.
For deeper insights into serialization, deserialization, and protocol design, refer to:
- [Data Layouts](/docs/build/toolkit/typescript-sdk/sdk-layout/){target=\_blank} for serialization concepts
- [Building Protocols and Payloads](/docs/build/toolkit/typescript-sdk/protocols-payloads/){target=\_blank} for designing custom protocol messages
This guide will help you understand how to handle VAAs and protocol messages in off-chain and on-chain scenarios.
## VAA Structure
Understanding the structure of VAAs is fundamental to working with Wormhole's SDKs. Each section of the VAA—Header, Envelope, and Payload—serves a specific role:
| Section | Description |
|----------|----------------------------------------------------------------------------------------------------------|
| Header | Includes the version and guardian signature information required to verify the VAA |
| Envelope | Contains metadata about the emitted message, such as the emitter chain, emitter address, and timestamp |
| Payload | Represents the actual message, in raw bytes, without a length prefix |
The VAA's body combines the Envelope and Payload. The Wormhole Guardians signed the core data and hashed (using `keccak256`) to generate the VAA's unique identifier.
When integrating protocols like Token Bridge or Wormhole Relayer:
- The TypeScript SDK handles VAAs off-chain, focusing on deserialization, validation, and payload extraction before submission
- The Solidity SDK processes VAAs on-chain, using libraries like `VaaLib` to decode and execute protocol actions
## VAAs in Protocol Contexts
### How VAAs Enable Protocol-Specific Messaging
VAAs are the backbone of Wormhole's cross-chain communication, encapsulating critical protocol payloads that drive actions on different blockchains. Each protocol—such as [Token Bridge](https://github.com/wormhole-foundation/wormhole-sdk-ts/tree/main/core/definitions/src/protocols/tokenBridge){target=\_blank}, [Wormhole Relayer](https://github.com/wormhole-foundation/wormhole-sdk-ts/tree/main/core/definitions/src/protocols/relayer){target=\_blank}, or [Circle CCTP](https://github.com/wormhole-foundation/wormhole-sdk-ts/tree/main/core/definitions/src/protocols/circleBridge){target=\_blank}—uses VAAs to securely transmit its messages across chains.
Examples of mapping protocols to VAAs:
| Protocol | Payload Purpose | Example |
|-----------------|-----------------------------------------------------------|------------------------------------|
| Token Bridge | Transfers token data and metadata | Token transfer or redemption |
| Wormhole Relayer| Manages delivery instructions for messages across chains | Delivery fee or refund handling |
| Circle CCTP | Facilitates stablecoin mint-and-burn operations | Circle-issued stablecoin transfer |
Each protocol integrates its payload format into the VAA structure, ensuring consistent message validation and execution across the ecosystem.
### TypeScript SDK: Off-Chain Handling of VAAs
The TypeScript SDK is designed for off-chain operations like reading, validating, and manipulating VAAs before submitting them to a chain. Developers can easily deserialize VAAs to extract protocol payloads and prepare actions such as initiating token transfers or constructing delivery instructions.
In the example below, we use the real [`envelopeLayout`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/dd6bd2463264680597519285ff559f9e92e85ca7/core/definitions/src/vaa/vaa.ts#L44-L51){target=\_blank} from Wormhole's TS SDK to deserialize and extract essential information like the emitter chain, sequence, and [consistency (finality) level](/docs/build/reference/consistency-levels/){target=\_blank}:
```typescript
import { deserializeLayout } from '@wormhole-foundation/sdk-base';
import {
universalAddressItem,
sequenceItem,
} from '@wormhole-foundation/core/layout-items/index.js';
export const envelopeLayout = [
{ name: 'timestamp', binary: 'uint', size: 4 },
{ name: 'nonce', binary: 'uint', size: 4 },
{ name: 'emitterChain', binary: 'uint', size: 2 },
{ name: 'emitterAddress', ...universalAddressItem },
{ name: 'sequence', ...sequenceItem },
{ name: 'consistencyLevel', binary: 'uint', size: 1 },
] as const satisfies Layout;
const encodedEnvelope = new Uint8Array([
/* binary envelope data */
]);
const deserializedEnvelope = deserializeLayout(envelopeLayout, encodedEnvelope);
```
For more details, you can refer to the [parseVAA example](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/examples/src/parseVaa.ts){target=\_blank} in the Wormhole SDK repository.
### Solidity SDK: On-Chain Handling of VAAs
The Solidity SDK enables on-chain processing of VAAs directly within smart contracts. This is essential for real-time validation, decoding, and execution of protocol-specific payloads. Developers can use libraries like [`VaaLib`](https://github.com/wormhole-foundation/wormhole-solidity-sdk/blob/e19013d08d1fdf5af9e6344c637e36a270422dd9/src/libraries/VaaLib.sol){target=\_blank} to parse the VAA header and payload, ensuring the message is authentic and consistent with Wormhole's validation.
Below is an example of parsing an envelope on-chain using the Solidity SDK:
```solidity
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.19;
import {VaaLib} from "wormhole-sdk/libraries/VaaLib.sol";
contract EnvelopeParser {
using VaaLib for bytes;
function parseEnvelope(
bytes memory encodedVaa
)
public
pure
returns (
uint32 timestamp,
uint32 nonce,
uint16 emitterChainId,
bytes32 emitterAddress,
uint64 sequence,
uint8 consistencyLevel
)
{
// Skip the header and decode the envelope
uint offset = VaaLib.skipVaaHeaderMemUnchecked(encodedVaa, 0);
return VaaLib.decodeVaaEnvelopeMemUnchecked(encodedVaa, offset);
}
}
```
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/build/toolkit/typescript-sdk/wormhole-sdk/
--- BEGIN CONTENT ---
---
title: Wormhole TS SDK
description: Explore Wormhole's TypeScript SDK and learn how to perform different types of transfers, including native, token, and USDC.
categories: Typescript-SDK
---
# Wormhole TypeScript SDK
## Introduction
The Wormhole TypeScript SDK is useful for interacting with the chains Wormhole supports and the [protocols](#protocols) built on top of Wormhole. This package bundles together functions, definitions, and constants that streamline the process of connecting chains and completing transfers using Wormhole. The SDK also offers targeted sub-packages for Wormhole-connected platforms, which allow you to add multichain support without creating outsized dependencies.
This section covers all you need to know about the functionality and ease of development offered through the Wormhole TypeScript SDK. Take a tour of the package to discover how it helps make integration easier. Learn more about how the SDK abstracts away complexities around concepts like platforms, contexts, and signers. Finally, you'll find guidance on usage, along with code examples, to show you how to use the tools of the SDK.
- :octicons-download-16:{ .lg .middle } **Installation**
---
Find installation instructions for both the meta package and installing specific, individual packages
[:custom-arrow: Install the SDK](#installation)
- :octicons-book-16:{ .lg .middle } **Concepts**
---
Understand key concepts and how the SDK abstracts them away. Learn more about platforms, chain context, addresses, and signers
[:custom-arrow: Explore concepts](#concepts)
- :octicons-file-code-16:{ .lg .middle } **Usage**
---
Guidance on using the SDK to add seamless interchain messaging to your application, including code examples
[:custom-arrow: Use the SDK](#usage)
- :octicons-code-square-16:{ .lg .middle } **TSdoc for SDK**
---
Review the TSdoc for the Wormhole TypeScript SDK for a detailed look at availabel methods, classes, interfaces, and definitions
[:custom-arrow: View the TSdoc on GitHub](https://wormhole-foundation.github.io/wormhole-sdk-ts/){target=\_blank}
!!! warning
This package is a work in progress. The interface may change, and there are likely bugs. Please [report](https://github.com/wormhole-foundation/connect-sdk/issues){target=\_blank} any issues you find.
## Installation
### Basic
To install the meta package using npm, run the following command in the root directory of your project:
```bash
npm install @wormhole-foundation/sdk
```
This package combines all the individual packages to make setup easier while allowing for tree shaking.
### Advanced
Alternatively, you can install a specific set of published packages individually:
??? interface "`sdk-base` - exposes constants"
```sh
npm install @wormhole-foundation/sdk-base
```
??? interface "`sdk-definitions` - exposes contract interfaces, basic types, and VAA payload definitions"
```sh
npm install @wormhole-foundation/sdk-definitions
```
??? interface "`sdk-evm` - exposes EVM-specific utilities"
```sh
npm install @wormhole-foundation/sdk-evm
```
??? interface "`sdk-evm-tokenbridge` - exposes the EVM Token Bridge protocol client"
```sh
npm install @wormhole-foundation/sdk-evm-tokenbridge
```
## Usage
Getting your integration started is simple. First, import Wormhole:
```ts
import { wormhole } from '@wormhole-foundation/sdk';
import { Wormhole, amount, signSendWait } from '@wormhole-foundation/sdk';
import algorand from '@wormhole-foundation/sdk/algorand';
import aptos from '@wormhole-foundation/sdk/aptos';
import cosmwasm from '@wormhole-foundation/sdk/cosmwasm';
import evm from '@wormhole-foundation/sdk/evm';
import solana from '@wormhole-foundation/sdk/solana';
import sui from '@wormhole-foundation/sdk/sui';
import { getSigner } from './helpers/index.js';
(async function () {
const wh = await wormhole('Testnet', [
evm,
solana,
aptos,
algorand,
cosmwasm,
sui,
]);
const ctx = wh.getChain('Solana');
const rcv = wh.getChain('Algorand');
const sender = await getSigner(ctx);
const receiver = await getSigner(rcv);
// Get a Token Bridge contract client on the source
const sndTb = await ctx.getTokenBridge();
// Send the native token of the source chain
const tokenId = Wormhole.tokenId(ctx.chain, 'native');
// Bigint amount using `amount` module
const amt = amount.units(amount.parse('0.1', ctx.config.nativeTokenDecimals));
// Create a transaction stream for transfers
const transfer = sndTb.transfer(
sender.address.address,
receiver.address,
tokenId.address,
amt
);
// Sign and send the transaction
const txids = await signSendWait(ctx, transfer, sender.signer);
console.log('Sent: ', txids);
// Get the Wormhole message ID from the transaction
const [whm] = await ctx.parseTransaction(txids[txids.length - 1]!.txid);
console.log('Wormhole Messages: ', whm);
const vaa = await wh.getVaa(
// Wormhole Message ID
whm!,
// Protocol:Payload name to use for decoding the VAA payload
'TokenBridge:Transfer',
// Timeout in milliseconds, depending on the chain and network, the VAA may take some time to be available
60_000
);
// Now get the token bridge on the redeem side
const rcvTb = await rcv.getTokenBridge();
// Create a transaction stream for redeeming
const redeem = rcvTb.redeem(receiver.address.address, vaa!);
// Sign and send the transaction
const rcvTxids = await signSendWait(rcv, redeem, receiver.signer);
console.log('Sent: ', rcvTxids);
// Now check if the transfer is completed according to
// the destination token bridge
const finished = await rcvTb.isTransferCompleted(vaa!);
console.log('Transfer completed: ', finished);
})();
```
Then, import each of the ecosystem [platforms](#platforms) that you wish to support:
```ts
import aptos from '@wormhole-foundation/sdk/aptos';
import cosmwasm from '@wormhole-foundation/sdk/cosmwasm';
import evm from '@wormhole-foundation/sdk/evm';
import solana from '@wormhole-foundation/sdk/solana';
import sui from '@wormhole-foundation/sdk/sui';
```
To make the [platform](#platforms) modules available for use, pass them to the Wormhole constructor:
```ts
evm,
solana,
aptos,
algorand,
cosmwasm,
sui,
]);
```
With a configured Wormhole object, you can do things like parse addresses for the provided platforms, get a [`ChainContext`](#chain-context) object, or fetch VAAs.
```ts
```
You can retrieve a VAA as follows. In this example, a timeout of `60,000` milliseconds is used. The amount of time required for the VAA to become available will vary by network.
```ts
// Wormhole Message ID
whm!,
// Protocol:Payload name to use for decoding the VAA payload
'TokenBridge:Transfer',
// Timeout in milliseconds, depending on the chain and network, the VAA may take some time to be available
60_000
);
```
??? code "View the complete script"
```ts
import { wormhole } from '@wormhole-foundation/sdk';
import { Wormhole, amount, signSendWait } from '@wormhole-foundation/sdk';
import algorand from '@wormhole-foundation/sdk/algorand';
import aptos from '@wormhole-foundation/sdk/aptos';
import cosmwasm from '@wormhole-foundation/sdk/cosmwasm';
import evm from '@wormhole-foundation/sdk/evm';
import solana from '@wormhole-foundation/sdk/solana';
import sui from '@wormhole-foundation/sdk/sui';
import { getSigner } from './helpers/index.js';
(async function () {
const wh = await wormhole('Testnet', [
evm,
solana,
aptos,
algorand,
cosmwasm,
sui,
]);
const ctx = wh.getChain('Solana');
const rcv = wh.getChain('Algorand');
const sender = await getSigner(ctx);
const receiver = await getSigner(rcv);
// Get a Token Bridge contract client on the source
const sndTb = await ctx.getTokenBridge();
// Send the native token of the source chain
const tokenId = Wormhole.tokenId(ctx.chain, 'native');
// Bigint amount using `amount` module
const amt = amount.units(amount.parse('0.1', ctx.config.nativeTokenDecimals));
// Create a transaction stream for transfers
const transfer = sndTb.transfer(
sender.address.address,
receiver.address,
tokenId.address,
amt
);
// Sign and send the transaction
const txids = await signSendWait(ctx, transfer, sender.signer);
console.log('Sent: ', txids);
// Get the Wormhole message ID from the transaction
const [whm] = await ctx.parseTransaction(txids[txids.length - 1]!.txid);
console.log('Wormhole Messages: ', whm);
const vaa = await wh.getVaa(
// Wormhole Message ID
whm!,
// Protocol:Payload name to use for decoding the VAA payload
'TokenBridge:Transfer',
// Timeout in milliseconds, depending on the chain and network, the VAA may take some time to be available
60_000
);
// Now get the token bridge on the redeem side
const rcvTb = await rcv.getTokenBridge();
// Create a transaction stream for redeeming
const redeem = rcvTb.redeem(receiver.address.address, vaa!);
// Sign and send the transaction
const rcvTxids = await signSendWait(rcv, redeem, receiver.signer);
console.log('Sent: ', rcvTxids);
// Now check if the transfer is completed according to
// the destination token bridge
const finished = await rcvTb.isTransferCompleted(vaa!);
console.log('Transfer completed: ', finished);
})();
```
Optionally, you can override the default configuration with a partial `WormholeConfig` object to specify particular fields, such as a different RPC endpoint.
```ts
const wh = await wormhole('Testnet', [solana], {
chains: {
Solana: {
contracts: {
coreBridge: '11111111111111111111111111111',
},
rpc: 'https://api.devnet.solana.com',
},
},
});
```
??? code "View the complete script"
```ts
import { wormhole } from '@wormhole-foundation/sdk';
import solana from '@wormhole-foundation/sdk/solana';
(async function () {
const wh = await wormhole('Testnet', [solana], {
chains: {
Solana: {
contracts: {
coreBridge: '11111111111111111111111111111',
},
rpc: 'https://api.devnet.solana.com',
},
},
});
console.log(wh.config.chains.Solana);
})();
```
## Concepts
Understanding several higher-level Wormhole concepts and how the SDK abstracts them away will help you use the tools most effectively. The following sections will introduce and discuss the concepts of platforms, chain contexts, addresses, signers, and protocols, how they are used in the Wormhole context, and how the SDK helps ease development in each conceptual area.
### Platforms
While every chain has unique attributes, chains from the same platform typically have standard functionalities they share. The SDK includes `Platform` modules, which create a standardized interface for interacting with the chains of a supported platform. The contents of a module vary by platform but can include:
- Protocols, such as [Wormhole core](#wormhole-core), preconfigured to suit the selected platform
- Definitions and configurations for types, signers, addresses, and chains
- Helpers configured for dealing with unsigned transactions on the selected platform
These modules also import and expose essential functions and define types or constants from the chain's native ecosystem to reduce the dependencies needed to interact with a chain using Wormhole. Rather than installing the entire native package for each desired platform, you can install a targeted package of standardized functions and definitions essential to connecting with Wormhole, keeping project dependencies as slim as possible.
Wormhole currently supports the following platforms:
- EVM
- Solana
- Cosmos
- Sui
- Aptos
- Algorand
See the [Platforms folder of the TypeScript SDK](https://github.com/wormhole-foundation/wormhole-sdk-ts/tree/main/platforms){target=\_blank} for an up-to-date list of the platforms supported by the Wormhole TypeScript SDK.
### Chain Context
The `definitions` package of the SDK includes the `ChainContext` class, which creates an interface for working with connected chains in a standardized way. This class contains the network, chain, and platform configurations for connected chains and cached RPC and protocol clients. The `ChainContext` class also exposes chain-specific methods and utilities. Much of the functionality comes from the `Platform` methods but some specific chains may have overridden methods via the context. This is also where the `Network`, `Chain`, and `Platform` type parameters which are used throughout the package are defined.
```ts
const srcChain = wh.getChain(senderAddress.chain);
const dstChain = wh.getChain(receiverAddress.chain);
const tb = await srcChain.getTokenBridge(); // => TokenBridge<'Evm'>
srcChain.getRpcClient(); // => RpcClient<'Evm'>
```
### Addresses
The SDK uses the `UniversalAddress` class to implement the `Address` interface, which all address types must implement. Addresses from various networks are parsed into their byte representation and modified as needed to ensure they are exactly 32 bytes long. Each platform also has an address type that understands the native address formats, referred to as `NativeAddress.` These abstractions allow you to work with addresses consistently regardless of the underlying chain.
```ts
// It's possible to convert a string address to its Native address
const ethAddr: NativeAddress<'Evm'> = toNative('Ethereum', '0xbeef...');
// A common type in the SDK is the `ChainAddress` which provides
// the additional context of the `Chain` this address is relevant for
const senderAddress: ChainAddress = Wormhole.chainAddress(
'Ethereum',
'0xbeef...'
);
const receiverAddress: ChainAddress = Wormhole.chainAddress(
'Solana',
'Sol1111...'
);
// Convert the ChainAddress back to its canonical string address format
const strAddress = Wormhole.canonicalAddress(senderAddress); // => '0xbeef...'
// Or if the ethAddr above is for an emitter and you need the UniversalAddress
const emitterAddr = ethAddr.toUniversalAddress().toString();
```
### Tokens
Similar to the `ChainAddress` type, the `TokenId` type provides the chain and address of a given token. The following snippet introduces `TokenId`, a way to uniquely identify any token, whether it's a standard token or a blockchain's native currency (like ETH for Ethereum).
Wormhole uses their contract address to create a `TokenId` for standard tokens. For native currencies, Wormhole uses the keyword `native` instead of an address. This makes it easy to work with any type of token consistently.
Finally, the snippet demonstrates how to convert a `TokenId` back into a regular address format when needed.
```ts
const sourceToken: TokenId = Wormhole.tokenId('Ethereum', '0xbeef...');
const gasToken: TokenId = Wormhole.tokenId('Ethereum', 'native');
const strAddress = Wormhole.canonicalAddress(senderAddress); // => '0xbeef...'
```
### Signers
Certain methods of signing transactions require a `Signer` interface in the SDK. Depending on the specific requirements, this interface can be fulfilled by either a `SignOnlySigner` or a `SignAndSendSigner`. A signer can be created by wrapping an offline or web wallet.
A `SignOnlySigner` is used when the signer isn't connected to the network or prefers not to broadcast transactions themselves. It accepts an array of unsigned transactions and returns an array of signed and serialized transactions. Before signing, the transactions may be inspected or altered. It's important to note that the serialization process is chain-specific. Refer to the testing signers (e.g., [EVM](https://github.com/wormhole-foundation/connect-sdk/blob/main/platforms/evm/src/signer.ts){target=\_blank} or [Solana](https://github.com/wormhole-foundation/connect-sdk/blob/main/platforms/solana/src/signer.ts){target=\_blank}) for an example of how to implement a signer for a specific chain or platform.
Conversely, a `SignAndSendSigner` is appropriate when the signer is connected to the network and intends to broadcast the transactions. This type of signer also accepts an array of unsigned transactions but returns an array of transaction IDs corresponding to the order of the unsigned transactions.
```ts
export type Signer = SignOnlySigner | SignAndSendSigner;
export interface SignOnlySigner {
chain(): ChainName;
address(): string;
// Accept an array of unsigned transactions and return
// an array of signed and serialized transactions.
// The transactions may be inspected or altered before
// signing.
sign(tx: UnsignedTransaction[]): Promise;
}
export interface SignAndSendSigner {
chain(): ChainName;
address(): string;
// Accept an array of unsigned transactions and return
// an array of transaction ids in the same order as the
// unsignedTransactions array.
signAndSend(tx: UnsignedTransaction[]): Promise;
}
```
#### Set Up a Signer with Ethers.js
To sign transactions programmatically with the Wormhole SDK, you can use Ethers.js to manage private keys and handle signing. Here's an example of setting up a signer using Ethers.js:
```javascript
import { ethers } from 'ethers';
// Update the following variables
const rpcUrl = 'INSERT_RPC_URL';
const privateKey = 'INSERT_PRIVATE_KEY';
const toAddress = 'INSERT_RECIPIENT_ADDRESS';
// Set up a provider and signer
const provider = new ethers.JsonRpcProvider(rpcUrl);
const signer = new ethers.Wallet(privateKey, provider);
// Example: Signing and sending a transaction
async function sendTransaction() {
const tx = {
to: toAddress,
value: ethers.parseUnits('0.1'), // Sending 0.1 ETH
gasPrice: await provider.getGasPrice(),
gasLimit: ethers.toBeHex(21000),
};
const transaction = await signer.sendTransaction(tx);
console.log('Transaction hash:', transaction.hash);
}
sendTransaction();
```
- **`provider`** - responsible for connecting to the Ethereum network (or any EVM-compatible network). It acts as a bridge between your application and the blockchain, allowing you to fetch data, check the state of the blockchain, and submit transactions
- **`signer`** - represents the account that will sign the transaction. In this case, you’re creating a signer using the private key associated with the account. The signer is responsible for authorizing transactions by digitally signing them with the private key
- **`Wallet`** - combines both the provider (for blockchain interaction) and the signer (for transaction authorization), allowing you to sign and send transactions programmatically
These components work together to create, sign, and submit a transaction to the blockchain.
???- tip "Managing Private Keys Securely"
Handling private keys is unavoidable, so it’s crucial to manage them securely. Here are some best practices:
- **Use environment variables** - avoid hardcoding private keys in your code. Use environment variables or secret management tools to inject private keys securely
- **Hardware wallets** - for production environments, consider integrating hardware wallets to keep private keys secure while allowing programmatic access through the SDK
### Protocols
While Wormhole is a Generic Message Passing (GMP) protocol, several protocols have been built to provide specific functionality. If available, each protocol will have a platform-specific implementation. These implementations provide methods to generate transactions or read state from the contract on-chain.
#### Wormhole Core
The core protocol underlies all Wormhole activity. This protocol is responsible for emitting the message containing the information necessary to perform bridging, including the [emitter address](https://docs.wormhole.com/wormhole/reference/glossary#emitter){target=\_blank}, the [sequence number](https://docs.wormhole.com/wormhole/reference/glossary#sequence){target=\_blank} for the message, and the payload of the message itself.
The following example demonstrates sending and verifying a message using the Wormhole Core protocol on Solana.
First, initialize a Wormhole instance for the Testnet environment, specifically for the Solana chain. Then, obtain a signer and its associated address, which will be used to sign transactions.
Next, get a reference to the core messaging bridge, which is the main interface for interacting with Wormhole's cross-chain messaging capabilities.
The code then prepares a message for publication. This message includes:
- The sender's address
- The message payload (in this case, the encoded string `lol`)
- A nonce (set to `0` here, but can be any user-defined value to uniquely identify the message)
- A [consistency (finality) level](/docs/build/reference/consistency-levels/){target=\_blank} (set to `0`, which determines the finality requirements for the message)
After preparing the message, the next steps are to generate, sign, and send the transaction or transactions required to publish the message on the Solana blockchain. Once the transaction is confirmed, the Wormhole message ID is extracted from the transaction logs. This ID is crucial for tracking the message across chains.
The code then waits for the Wormhole network to process and sign the message, turning it into a Verified Action Approval (VAA). This VAA is retrieved in a `Uint8Array` format, with a timeout of 60 seconds.
Lastly, the code will demonstrate how to verify the message on the receiving end. A verification transaction is prepared using the original sender's address and the VAA, and finally, this transaction is signed and sent.
???+ code "View the complete script"
```ts
import { encoding, signSendWait, wormhole } from '@wormhole-foundation/sdk';
import { getSigner } from './helpers/index.js';
import solana from '@wormhole-foundation/sdk/solana';
import evm from '@wormhole-foundation/sdk/evm';
(async function () {
const wh = await wormhole('Testnet', [solana, evm]);
const chain = wh.getChain('Avalanche');
const { signer, address } = await getSigner(chain);
// Get a reference to the core messaging bridge
const coreBridge = await chain.getWormholeCore();
// Generate transactions, sign and send them
const publishTxs = coreBridge.publishMessage(
// Address of sender (emitter in VAA)
address.address,
// Message to send (payload in VAA)
encoding.bytes.encode('lol'),
// Nonce (user defined, no requirement for a specific value, useful to provide a unique identifier for the message)
0,
// ConsistencyLevel (ie finality of the message, see wormhole docs for more)
0
);
// Send the transaction(s) to publish the message
const txids = await signSendWait(chain, publishTxs, signer);
// Take the last txid in case multiple were sent
// The last one should be the one containing the relevant
// event or log info
const txid = txids[txids.length - 1];
// Grab the wormhole message id from the transaction logs or storage
const [whm] = await chain.parseTransaction(txid!.txid);
// Wait for the vaa to be signed and available with a timeout
const vaa = await wh.getVaa(whm!, 'Uint8Array', 60_000);
console.log(vaa);
// Note: calling verifyMessage manually is typically not a useful thing to do
// As the VAA is typically submitted to the counterpart contract for
// A given protocol and the counterpart contract will verify the VAA
// This is simply for demo purposes
const verifyTxs = coreBridge.verifyMessage(address.address, vaa!);
console.log(await signSendWait(chain, verifyTxs, signer));
})();
```
The payload contains the information necessary to perform whatever action is required based on the protocol that uses it.
#### Token Bridge
The most familiar protocol built on Wormhole is the Token Bridge. Every chain has a `TokenBridge` protocol client that provides a consistent interface for interacting with the Token Bridge, which includes methods to generate the transactions required to transfer tokens and methods to generate and redeem attestations. `WormholeTransfer` abstractions are the recommended way to interact with these protocols, but it is possible to use them directly.
```ts
import { signSendWait } from '@wormhole-foundation/sdk';
const tb = await srcChain.getTokenBridge();
const token = '0xdeadbeef...';
const txGenerator = tb.createAttestation(token);
const txids = await signSendWait(srcChain, txGenerator, src.signer);
```
Supported protocols are defined in the [definitions module](https://github.com/wormhole-foundation/connect-sdk/tree/main/core/definitions/src/protocols){target=\_blank}.
## Transfers
While using the [`ChainContext`](#chain-context) and [`Protocol`](#protocols) clients directly is possible, the SDK provides some helpful abstractions for transferring tokens.
The `WormholeTransfer` interface provides a convenient abstraction to encapsulate the steps involved in a cross-chain transfer.
### Token Transfers
Performing a token transfer is trivial for any source and destination chains. You can create a new `Wormhole` object to make objects like `TokenTransfer` and `CircleTransfer`, to transfer tokens between chains.
The following example demonstrates the process of initiating and completing a token transfer. It starts by creating a `TokenTransfer` object, which tracks the transfer's state throughout its lifecycle. The code then obtains a quote for the transfer, ensuring the amount is sufficient to cover fees and any requested native gas.
The transfer process is divided into three main steps:
1. Initiating the transfer on the source chain
2. Waiting for the transfer to be attested (if not automatic)
3. Completing the transfer on the destination chain
For automatic transfers, the process ends after initiation. The code waits for the transfer to be attested for manual transfers and then completes it on the destination chain.
```ts
const xfer = await wh.tokenTransfer(
route.token,
route.amount,
route.source.address,
route.destination.address,
route.delivery?.automatic ?? false,
route.payload,
route.delivery?.nativeGas
);
const quote = await TokenTransfer.quoteTransfer(
wh,
route.source.chain,
route.destination.chain,
xfer.transfer
);
console.log(quote);
if (xfer.transfer.automatic && quote.destinationToken.amount < 0)
throw 'The amount requested is too low to cover the fee and any native gas requested.';
// 1) Submit the transactions to the source chain, passing a signer to sign any txns
console.log('Starting transfer');
const srcTxids = await xfer.initiateTransfer(route.source.signer);
console.log(`Started transfer: `, srcTxids);
// If automatic, we're done
if (route.delivery?.automatic) return xfer;
// 2) Wait for the VAA to be signed and ready (not required for auto transfer)
console.log('Getting Attestation');
const attestIds = await xfer.fetchAttestation(60_000);
console.log(`Got Attestation: `, attestIds);
// 3) Redeem the VAA on the dest chain
console.log('Completing Transfer');
const destTxids = await xfer.completeTransfer(route.destination.signer);
console.log(`Completed Transfer: `, destTxids);
```
??? code "View the complete script"
```ts hl_lines="122"
import {
Chain,
Network,
TokenId,
TokenTransfer,
Wormhole,
amount,
isTokenId,
wormhole,
} from '@wormhole-foundation/sdk';
import evm from '@wormhole-foundation/sdk/evm';
import solana from '@wormhole-foundation/sdk/solana';
import { SignerStuff, getSigner, waitLog } from './helpers/index.js';
(async function () {
// Init Wormhole object, passing config for which network
// to use (e.g. Mainnet/Testnet) and what Platforms to support
const wh = await wormhole('Testnet', [evm, solana]);
// Grab chain Contexts -- these hold a reference to a cached rpc client
const sendChain = wh.getChain('Avalanche');
const rcvChain = wh.getChain('Solana');
// Shortcut to allow transferring native gas token
const token = Wormhole.tokenId(sendChain.chain, 'native');
// A TokenId is just a `{chain, address}` pair and an alias for ChainAddress
// The `address` field must be a parsed address.
// You can get a TokenId (or ChainAddress) prepared for you
// by calling the static `chainAddress` method on the Wormhole class.
// e.g.
// wAvax on Solana
// const token = Wormhole.tokenId("Solana", "3Ftc5hTz9sG4huk79onufGiebJNDMZNL8HYgdMJ9E7JR");
// wSol on Avax
// const token = Wormhole.tokenId("Avalanche", "0xb10563644a6AB8948ee6d7f5b0a1fb15AaEa1E03");
// Normalized given token decimals later but can just pass bigints as base units
// Note: The Token bridge will dedust past 8 decimals
// This means any amount specified past that point will be returned
// To the caller
const amt = '0.05';
// With automatic set to true, perform an automatic transfer. This will invoke a relayer
// Contract intermediary that knows to pick up the transfers
// With automatic set to false, perform a manual transfer from source to destination
// Of the token
// On the destination side, a wrapped version of the token will be minted
// To the address specified in the transfer VAA
const automatic = false;
// The Wormhole relayer has the ability to deliver some native gas funds to the destination account
// The amount specified for native gas will be swapped for the native gas token according
// To the swap rate provided by the contract, denominated in native gas tokens
const nativeGas = automatic ? '0.01' : undefined;
// Get signer from local key but anything that implements
// Signer interface (e.g. wrapper around web wallet) should work
const source = await getSigner(sendChain);
const destination = await getSigner(rcvChain);
// Used to normalize the amount to account for the tokens decimals
const decimals = isTokenId(token)
? Number(await wh.getDecimals(token.chain, token.address))
: sendChain.config.nativeTokenDecimals;
// Set this to true if you want to perform a round trip transfer
const roundTrip: boolean = false;
// Set this to the transfer txid of the initiating transaction to recover a token transfer
// And attempt to fetch details about its progress.
let recoverTxid = undefined;
// Finally create and perform the transfer given the parameters set above
const xfer = !recoverTxid
? // Perform the token transfer
await tokenTransfer(
wh,
{
token,
amount: amount.units(amount.parse(amt, decimals)),
source,
destination,
delivery: {
automatic,
nativeGas: nativeGas
? amount.units(amount.parse(nativeGas, decimals))
: undefined,
},
},
roundTrip
)
: // Recover the transfer from the originating txid
await TokenTransfer.from(wh, {
chain: source.chain.chain,
txid: recoverTxid,
});
const receipt = await waitLog(wh, xfer);
// Log out the results
console.log(receipt);
})();
async function tokenTransfer(
wh: Wormhole,
route: {
token: TokenId;
amount: bigint;
source: SignerStuff;
destination: SignerStuff;
delivery?: {
automatic: boolean;
nativeGas?: bigint;
};
payload?: Uint8Array;
},
roundTrip?: boolean
): Promise> {
// Create a TokenTransfer object to track the state of the transfer over time
const xfer = await wh.tokenTransfer(
route.token,
route.amount,
route.source.address,
route.destination.address,
route.delivery?.automatic ?? false,
route.payload,
route.delivery?.nativeGas
);
const quote = await TokenTransfer.quoteTransfer(
wh,
route.source.chain,
route.destination.chain,
xfer.transfer
);
console.log(quote);
if (xfer.transfer.automatic && quote.destinationToken.amount < 0)
throw 'The amount requested is too low to cover the fee and any native gas requested.';
// 1) Submit the transactions to the source chain, passing a signer to sign any txns
console.log('Starting transfer');
const srcTxids = await xfer.initiateTransfer(route.source.signer);
console.log(`Started transfer: `, srcTxids);
// If automatic, we're done
if (route.delivery?.automatic) return xfer;
// 2) Wait for the VAA to be signed and ready (not required for auto transfer)
console.log('Getting Attestation');
const attestIds = await xfer.fetchAttestation(60_000);
console.log(`Got Attestation: `, attestIds);
// 3) Redeem the VAA on the dest chain
console.log('Completing Transfer');
const destTxids = await xfer.completeTransfer(route.destination.signer);
console.log(`Completed Transfer: `, destTxids);
// If no need to send back, dip
if (!roundTrip) return xfer;
const { destinationToken: token } = quote;
return await tokenTransfer(wh, {
...route,
token: token.token,
amount: token.amount,
source: route.destination,
destination: route.source,
});
}
```
Internally, this uses the [TokenBridge](#token-bridge) protocol client to transfer tokens. Like other Protocols, the `TokenBridge` protocol provides a consistent set of methods across all chains to generate a set of transactions for that specific chain.
### Native USDC Transfers
You can also transfer native USDC using [Circle's CCTP](https://www.circle.com/en/cross-chain-transfer-protocol){target=\_blank}. Please note that if the transfer is set to `Automatic` mode, a fee for performing the relay will be included in the quote. This fee is deducted from the total amount requested to be sent. For example, if the user wishes to receive `1.0` on the destination, the amount sent should be adjusted to `1.0` plus the relay fee. The same principle applies to native gas drop offs.
In the following example, the `wh.circleTransfer` function is called with several parameters to set up the transfer. It takes the amount to be transferred (in the token's base units), the sender's chain and address, and the receiver's chain and address. The function also allows specifying whether the transfer should be automatic, meaning it will be completed without further user intervention.
An optional payload can be included with the transfer, though it's set to undefined in this case. Finally, if the transfer is automatic, you can request that native gas (the blockchain's native currency used for transaction fees) be sent to the receiver along with the transferred tokens.
When waiting for the `VAA`, a timeout of `60,000` milliseconds is used. The amount of time required for the VAA to become available will [vary by network](https://developers.circle.com/stablecoins/docs/required-block-confirmations#mainnet){target=\_blank}.
```ts
// Amount as bigint (base units)
req.amount,
// Sender chain/address
src.address,
// Receiver chain/address
dst.address,
// Automatic delivery boolean
req.automatic,
// Payload to be sent with the transfer
undefined,
// If automatic, native gas can be requested to be sent to the receiver
req.nativeGas
);
// Note, if the transfer is requested to be Automatic, a fee for performing the relay
// will be present in the quote. The fee comes out of the amount requested to be sent.
// If the user wants to receive 1.0 on the destination, the amount to send should be 1.0 + fee.
// The same applies for native gas dropoff
const quote = await CircleTransfer.quoteTransfer(
src.chain,
dst.chain,
xfer.transfer
);
console.log('Quote', quote);
console.log('Starting Transfer');
const srcTxids = await xfer.initiateTransfer(src.signer);
console.log(`Started Transfer: `, srcTxids);
if (req.automatic) {
const relayStatus = await waitForRelay(srcTxids[srcTxids.length - 1]!);
console.log(`Finished relay: `, relayStatus);
return;
}
console.log('Waiting for Attestation');
const attestIds = await xfer.fetchAttestation(60_000);
console.log(`Got Attestation: `, attestIds);
console.log('Completing Transfer');
const dstTxids = await xfer.completeTransfer(dst.signer);
console.log(`Completed Transfer: `, dstTxids);
}
```
??? code "View the complete script"
```ts
import {
Chain,
CircleTransfer,
Network,
Signer,
TransactionId,
TransferState,
Wormhole,
amount,
wormhole,
} from '@wormhole-foundation/sdk';
import evm from '@wormhole-foundation/sdk/evm';
import solana from '@wormhole-foundation/sdk/solana';
import { SignerStuff, getSigner, waitForRelay } from './helpers/index.js';
/*
Notes:
Only a subset of chains are supported by Circle for CCTP, see core/base/src/constants/circle.ts for currently supported chains
AutoRelayer takes a 0.1 USDC fee when transferring to any chain beside Goerli, which is 1 USDC
*/
//
(async function () {
// Init the Wormhole object, passing in the config for which network
// to use (e.g. Mainnet/Testnet) and what Platforms to support
const wh = await wormhole('Testnet', [evm, solana]);
// Grab chain Contexts
const sendChain = wh.getChain('Avalanche');
const rcvChain = wh.getChain('Solana');
// Get signer from local key but anything that implements
// Signer interface (e.g. wrapper around web wallet) should work
const source = await getSigner(sendChain);
const destination = await getSigner(rcvChain);
// 6 decimals for USDC (except for BSC, so check decimals before using this)
const amt = amount.units(amount.parse('0.2', 6));
// Choose whether or not to have the attestation delivered for you
const automatic = false;
// If the transfer is requested to be automatic, you can also request that
// during redemption, the receiver gets some amount of native gas transferred to them
// so that they may pay for subsequent transactions
// The amount specified here is denominated in the token being transferred (USDC here)
const nativeGas = automatic ? amount.units(amount.parse('0.0', 6)) : 0n;
await cctpTransfer(wh, source, destination, {
amount: amt,
automatic,
nativeGas,
});
})();
async function cctpTransfer(
wh: Wormhole,
src: SignerStuff,
dst: SignerStuff,
req: {
amount: bigint;
automatic: boolean;
nativeGas?: bigint;
}
) {
const xfer = await wh.circleTransfer(
// Amount as bigint (base units)
req.amount,
// Sender chain/address
src.address,
// Receiver chain/address
dst.address,
// Automatic delivery boolean
req.automatic,
// Payload to be sent with the transfer
undefined,
// If automatic, native gas can be requested to be sent to the receiver
req.nativeGas
);
// Note, if the transfer is requested to be Automatic, a fee for performing the relay
// will be present in the quote. The fee comes out of the amount requested to be sent.
// If the user wants to receive 1.0 on the destination, the amount to send should be 1.0 + fee.
// The same applies for native gas dropoff
const quote = await CircleTransfer.quoteTransfer(
src.chain,
dst.chain,
xfer.transfer
);
console.log('Quote', quote);
console.log('Starting Transfer');
const srcTxids = await xfer.initiateTransfer(src.signer);
console.log(`Started Transfer: `, srcTxids);
if (req.automatic) {
const relayStatus = await waitForRelay(srcTxids[srcTxids.length - 1]!);
console.log(`Finished relay: `, relayStatus);
return;
}
console.log('Waiting for Attestation');
const attestIds = await xfer.fetchAttestation(60_000);
console.log(`Got Attestation: `, attestIds);
console.log('Completing Transfer');
const dstTxids = await xfer.completeTransfer(dst.signer);
console.log(`Completed Transfer: `, dstTxids);
}
export async function completeTransfer(
wh: Wormhole,
txid: TransactionId,
signer: Signer
): Promise {
const xfer = await CircleTransfer.from(wh, txid);
const attestIds = await xfer.fetchAttestation(60 * 60 * 1000);
console.log('Got attestation: ', attestIds);
const dstTxIds = await xfer.completeTransfer(signer);
console.log('Completed transfer: ', dstTxIds);
}
```
### Recovering Transfers
It may be necessary to recover an abandoned transfer before it is completed. To do this, instantiate the `Transfer` class with the `from` static method and pass one of several types of identifiers. A `TransactionId` or `WormholeMessageId` may be used to recover the transfer.
```ts
const attestIds = await xfer.fetchAttestation(60 * 60 * 1000);
console.log('Got attestation: ', attestIds);
const dstTxIds = await xfer.completeTransfer(signer);
console.log('Completed transfer: ', dstTxIds);
```
??? code "View the complete script"
```ts hl_lines="130"
import {
Chain,
CircleTransfer,
Network,
Signer,
TransactionId,
TransferState,
Wormhole,
amount,
wormhole,
} from '@wormhole-foundation/sdk';
import evm from '@wormhole-foundation/sdk/evm';
import solana from '@wormhole-foundation/sdk/solana';
import { SignerStuff, getSigner, waitForRelay } from './helpers/index.js';
/*
Notes:
Only a subset of chains are supported by Circle for CCTP, see core/base/src/constants/circle.ts for currently supported chains
AutoRelayer takes a 0.1 USDC fee when transferring to any chain beside Goerli, which is 1 USDC
*/
//
(async function () {
// Init the Wormhole object, passing in the config for which network
// to use (e.g. Mainnet/Testnet) and what Platforms to support
const wh = await wormhole('Testnet', [evm, solana]);
// Grab chain Contexts
const sendChain = wh.getChain('Avalanche');
const rcvChain = wh.getChain('Solana');
// Get signer from local key but anything that implements
// Signer interface (e.g. wrapper around web wallet) should work
const source = await getSigner(sendChain);
const destination = await getSigner(rcvChain);
// 6 decimals for USDC (except for BSC, so check decimals before using this)
const amt = amount.units(amount.parse('0.2', 6));
// Choose whether or not to have the attestation delivered for you
const automatic = false;
// If the transfer is requested to be automatic, you can also request that
// during redemption, the receiver gets some amount of native gas transferred to them
// so that they may pay for subsequent transactions
// The amount specified here is denominated in the token being transferred (USDC here)
const nativeGas = automatic ? amount.units(amount.parse('0.0', 6)) : 0n;
await cctpTransfer(wh, source, destination, {
amount: amt,
automatic,
nativeGas,
});
})();
async function cctpTransfer(
wh: Wormhole,
src: SignerStuff,
dst: SignerStuff,
req: {
amount: bigint;
automatic: boolean;
nativeGas?: bigint;
}
) {
const xfer = await wh.circleTransfer(
// Amount as bigint (base units)
req.amount,
// Sender chain/address
src.address,
// Receiver chain/address
dst.address,
// Automatic delivery boolean
req.automatic,
// Payload to be sent with the transfer
undefined,
// If automatic, native gas can be requested to be sent to the receiver
req.nativeGas
);
// Note, if the transfer is requested to be Automatic, a fee for performing the relay
// will be present in the quote. The fee comes out of the amount requested to be sent.
// If the user wants to receive 1.0 on the destination, the amount to send should be 1.0 + fee.
// The same applies for native gas dropoff
const quote = await CircleTransfer.quoteTransfer(
src.chain,
dst.chain,
xfer.transfer
);
console.log('Quote', quote);
console.log('Starting Transfer');
const srcTxids = await xfer.initiateTransfer(src.signer);
console.log(`Started Transfer: `, srcTxids);
if (req.automatic) {
const relayStatus = await waitForRelay(srcTxids[srcTxids.length - 1]!);
console.log(`Finished relay: `, relayStatus);
return;
}
console.log('Waiting for Attestation');
const attestIds = await xfer.fetchAttestation(60_000);
console.log(`Got Attestation: `, attestIds);
console.log('Completing Transfer');
const dstTxids = await xfer.completeTransfer(dst.signer);
console.log(`Completed Transfer: `, dstTxids);
}
export async function completeTransfer(
wh: Wormhole,
txid: TransactionId,
signer: Signer
): Promise {
const xfer = await CircleTransfer.from(wh, txid);
const attestIds = await xfer.fetchAttestation(60 * 60 * 1000);
console.log('Got attestation: ', attestIds);
const dstTxIds = await xfer.completeTransfer(signer);
console.log('Completed transfer: ', dstTxIds);
}
```
## Routes
While a specific `WormholeTransfer`, such as `TokenTransfer` or `CCTPTransfer`, may be used, the developer must know exactly which transfer type to use for a given request.
To provide a more flexible and generic interface, the `Wormhole` class provides a method to produce a `RouteResolver` that can be configured with a set of possible routes to be supported.
The following section demonstrates setting up and validating a token transfer using Wormhole's routing system.
```ts
const resolver = wh.resolver([
routes.TokenBridgeRoute, // manual token bridge
routes.AutomaticTokenBridgeRoute, // automatic token bridge
routes.CCTPRoute, // manual CCTP
routes.AutomaticCCTPRoute, // automatic CCTP
routes.AutomaticPorticoRoute, // Native eth transfers
]);
```
Once created, the resolver can be used to provide a list of input and possible output tokens.
```ts
const srcTokens = await resolver.supportedSourceTokens(sendChain);
console.log(
'Allowed source tokens: ',
srcTokens.map((t) => canonicalAddress(t))
);
const sendToken = Wormhole.tokenId(sendChain.chain, 'native');
// Given the send token, what can we possibly get on the destination chain?
const destTokens = await resolver.supportedDestinationTokens(
sendToken,
sendChain,
destChain
);
console.log(
'For the given source token and routes configured, the following tokens may be receivable: ',
destTokens.map((t) => canonicalAddress(t))
);
// Grab the first one for the example
const destinationToken = destTokens[0]!;
```
Once the tokens are selected, a `RouteTransferRequest` may be created to provide a list of routes that can fulfill the request. Creating a transfer request fetches the token details since all routes will need to know about the tokens.
```ts
// Since all routes will need to know about the tokens
const tr = await routes.RouteTransferRequest.create(wh, {
source: sendToken,
destination: destinationToken,
});
// Resolve the transfer request to a set of routes that can perform it
const foundRoutes = await resolver.findRoutes(tr);
console.log(
'For the transfer parameters, we found these routes: ',
foundRoutes
);
```
Choosing the best route is currently left to the developer, but strategies might include sorting by output amount or expected time to complete the transfer (no estimate is currently provided).
After choosing the best route, extra parameters like `amount`, `nativeGasDropoff`, and `slippage` can be passed, depending on the specific route selected. A quote can be retrieved with the validated request.
After successful validation, the code requests a transfer quote. This quote likely includes important details such as fees, estimated time, and the final amount to be received. If the quote is generated successfully, it's displayed for the user to review and decide whether to proceed with the transfer. This process ensures that all transfer details are properly set up and verified before any actual transfer occurs.
```ts
'This route offers the following default options',
bestRoute.getDefaultOptions()
);
// Specify the amount as a decimal string
const amt = '0.001';
// Create the transfer params for this request
const transferParams = { amount: amt, options: { nativeGas: 0 } };
// Validate the transfer params passed, this returns a new type of ValidatedTransferParams
// which (believe it or not) is a validated version of the input params
// This new var must be passed to the next step, quote
const validated = await bestRoute.validate(tr, transferParams);
if (!validated.valid) throw validated.error;
console.log('Validated parameters: ', validated.params);
// Get a quote for the transfer, this too returns a new type that must
// be passed to the next step, execute (if you like the quote)
const quote = await bestRoute.quote(tr, validated.params);
if (!quote.success) throw quote.error;
console.log('Best route quote: ', quote);
```
Finally, assuming the quote looks good, the route can initiate the request with the quote and the `signer`.
```ts
tr,
sender.signer,
quote,
receiver.address
);
console.log('Initiated transfer with receipt: ', receipt);
```
??? code "View the complete script"
```ts
import {
Wormhole,
canonicalAddress,
routes,
wormhole,
} from '@wormhole-foundation/sdk';
import evm from '@wormhole-foundation/sdk/evm';
import solana from '@wormhole-foundation/sdk/solana';
import { getSigner } from './helpers/index.js';
(async function () {
// Setup
const wh = await wormhole('Testnet', [evm, solana]);
// Get chain contexts
const sendChain = wh.getChain('Avalanche');
const destChain = wh.getChain('Solana');
// Get signers from local config
const sender = await getSigner(sendChain);
const receiver = await getSigner(destChain);
// Create new resolver, passing the set of routes to consider
const resolver = wh.resolver([
routes.TokenBridgeRoute, // manual token bridge
routes.AutomaticTokenBridgeRoute, // automatic token bridge
routes.CCTPRoute, // manual CCTP
routes.AutomaticCCTPRoute, // automatic CCTP
routes.AutomaticPorticoRoute, // Native eth transfers
]);
// What tokens are available on the source chain?
const srcTokens = await resolver.supportedSourceTokens(sendChain);
console.log(
'Allowed source tokens: ',
srcTokens.map((t) => canonicalAddress(t))
);
const sendToken = Wormhole.tokenId(sendChain.chain, 'native');
// Given the send token, what can we possibly get on the destination chain?
const destTokens = await resolver.supportedDestinationTokens(
sendToken,
sendChain,
destChain
);
console.log(
'For the given source token and routes configured, the following tokens may be receivable: ',
destTokens.map((t) => canonicalAddress(t))
);
// Grab the first one for the example
const destinationToken = destTokens[0]!;
// 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: sendToken,
destination: destinationToken,
});
// Resolve the transfer request to a set of routes that can perform it
const foundRoutes = await resolver.findRoutes(tr);
console.log(
'For the transfer parameters, we found these routes: ',
foundRoutes
);
const bestRoute = foundRoutes[0]!;
console.log('Selected: ', bestRoute);
console.log(
'This route offers the following default options',
bestRoute.getDefaultOptions()
);
// Specify the amount as a decimal string
const amt = '0.001';
// Create the transfer params for this request
const transferParams = { amount: amt, options: { nativeGas: 0 } };
// Validate the transfer params passed, this returns a new type of ValidatedTransferParams
// which (believe it or not) is a validated version of the input params
// This new var must be passed to the next step, quote
const validated = await bestRoute.validate(tr, transferParams);
if (!validated.valid) throw validated.error;
console.log('Validated parameters: ', validated.params);
// Get a quote for the transfer, this too returns a new type that must
// be passed to the next step, execute (if you like the quote)
const quote = await bestRoute.quote(tr, validated.params);
if (!quote.success) throw quote.error;
console.log('Best route quote: ', quote);
// If you're sure you want to do this, set this to true
const imSure = false;
if (imSure) {
// Now the transfer may be initiated
// A receipt will be returned, guess what you gotta do with that?
const receipt = await bestRoute.initiate(
tr,
sender.signer,
quote,
receiver.address
);
console.log('Initiated transfer with receipt: ', receipt);
// Kick off a wait log, if there is an opportunity to complete, this function will do it
// See the implementation for how this works
await routes.checkAndCompleteTransfer(bestRoute, receipt, receiver.signer);
} else {
console.log('Not initiating transfer (set `imSure` to true to do so)');
}
})();
```
See the `router.ts` example in the [examples directory](https://github.com/wormhole-foundation/wormhole-sdk-ts/tree/main/examples){target=\_blank} for a full working example.
### Routes as Plugins
Routes can be imported from any npm package that exports them and configured with the resolver. Custom routes must extend [`Route`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/0c57292368146c460abc9ce9e7f6a42be8e0b903/connect/src/routes/route.ts#L21-L64){target=\_blank} and implement [`StaticRouteMethods`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/0c57292368146c460abc9ce9e7f6a42be8e0b903/connect/src/routes/route.ts#L101){target=\_blank}.
```ts
import { Network, routes } from '@wormhole-foundation/sdk-connect';
export class CustomRoute
extends routes.Route
implements routes.StaticRouteMethods
{
static meta = {
name: 'CustomRoute',
};
// implementation...
}
```
A noteworthy example of a route exported from a separate npm package is Wormhole Native Token Transfers (NTT). See the [`NttAutomaticRoute`](https://github.com/wormhole-foundation/native-token-transfers/blob/66f8e414223a77f5c736541db0a7a85396cab71c/sdk/route/src/automatic.ts#L48){target=\_blank} route implementation.
## See Also
The TSdoc is available [on GitHub](https://wormhole-foundation.github.io/wormhole-sdk-ts/){target=\_blank}.
--- END CONTENT ---
## Basics Concepts [shared: true]
The following section contains foundational documentation shared across all Wormhole products.
It describes the architecture and messaging infrastructure that serve as the backbone for all integrations built with Wormhole.
This includes the core contracts, VAA (Verifiable Action Approval) structure, guardian set functionality, and message flow mechanisms.
This context is provided to help understand how the system works under the hood, but responses should stay focused on the specific product unless the user explicitly asks about the general architecture.
---
## List of shared concept pages:
## Full content for shared concepts:
Doc-Content: https://wormhole.com/docs/learn/glossary/
--- BEGIN CONTENT ---
---
title: Glossary
description: Explore a comprehensive glossary of technical terms and key concepts used in the Wormhole network, covering Chain ID, Guardian, VAA, and more.
categories: Basics
---
# Glossary
This glossary is an index of technical term definitions for words commonly used in Wormhole documentation.
## Chain ID
Wormhole assigns a unique `u16` integer chain ID to each supported blockchain. These chain IDs are specific to Wormhole and may differ from those used by blockchains to identify their networks.
You can find each chain ID documented on the [Wormhole Chain IDs](/docs/build/reference/chain-ids/){target=\_blank} page.
## Consistency Level
The level of finality (consistency) a transaction should meet before being signed by a Guardian. See the [Wormhole Finality](/docs/build/reference/consistency-levels/){target=\_blank} reference page for details.
## Delivery Provider
A Delivery Provider monitors for Wormhole Relayer delivery requests and delivers those requests to the intended target chain as instructed.
## Emitter
The emitter contract makes the call to the Wormhole Core Contract. The published message includes the emitter contract address and, a sequence number for the message is tracked to provide a unique ID.
## Finality
The finality of a transaction depends on its blockchain properties. Once a transaction is considered final, you can assume the resulting state changes it caused won't be reverted.
## Guardian
A [Guardian](/docs/learn/infrastructure/guardians/){target=\_blank} is one of the 19 parties running validators in the Guardian Network contributing to the VAA multisig.
## Guardian Network
Validators in their own P2P network who serve as Wormhole's oracle by observing activity on-chain and generating signed messages attesting to that activity.
## Guardian Set
The Guardian Set is a set of guardians responsible for validating a message emitted from the core contracts. Occasionally, the members of the set will change through a governance action.
## Heartbeat
Each Guardian will issue a `heartbeat` on a 15-second interval to signal that it is still running and convey details about its identity, uptime, version, and the status of the connected nodes.
You can view the heartbeats on the [Wormhole dashboard](https://wormhole-foundation.github.io/wormhole-dashboard/#/?endpoint=Mainnet){target=\_blank}.
## Observation
An Observation is a data structure describing a message emitted by the Core Contract and noticed by the Guardian node.
## Relayer
A relayer is any process that delivers VAAs to a destination.
## Sequence
A nonce, strictly increasing, which is tracked by the Wormhole Core Contract and unique to the emitter chain and address.
## Spy
A Spy is a daemon that eavesdrops on the messages passed between Guardians, typically to track VAAs as they get signed.
## VAA
[Verifiable Action Approvals](/docs/learn/infrastructure/vaas/){target=\_blank} (VAAs) are the base data structure in the Wormhole ecosystem. They contain emitted messages along with information such as what contract emitted the message.
## Validator
A daemon configured to monitor a blockchain node and observe messages emitted by the Wormhole contracts.
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/learn/infrastructure/
--- BEGIN CONTENT ---
---
title: Infrastructure Components
description: Explore Wormhole's infrastructure, including the key components that enable secure multichain communication and asset transfers across blockchain networks.
categories: Basics
---
# Infrastructure Components
This section examines the core components that power Wormhole's infrastructure, including Guardians, relayers, VAAs, and the Spy.
## Get Started
Start here for an overview of Wormhole architecture components and security mechanisms:
- :octicons-book-16:{ .lg .middle } **Architecture Overview**
---
Overview of Wormhole's architecture, detailing key on-chain and off-chain components like the Core Contract, Guardian Network, and relayers.
[:custom-arrow: Learn About Architecture](/docs/learn/infrastructure/architecture/)
- :octicons-book-16:{ .lg .middle } **Security**
---
Explore Wormhole's security features, including the Guardian network, governance, and monitoring.
[:custom-arrow: Learn About Security](/docs/learn/security/)
## Explore Components
The relationship between individual components can be demonstrated through the simplified flow of a multichain message from a source-chain contract to a target-chain contract. Select the title of each step to learn more about that component:
[timeline left(wormhole-docs/.snippets/text/learn/infrastructure/infrastructure-index-timeline.json)]
The [Spy](/docs/learn/infrastructure/spy/) continuously runs in the background to subscribe to gossiped messages across the Guardian Network and enable real-time network activity monitoring.
## Next Steps
- :octicons-book-16:{ .lg .middle } **Messaging Components**
---
Learn more about individual messaging components such as Core Contracts, VAAs, Guardians, and relayers
[:custom-arrow: Explore Core Contracts](/docs/learn/infrastructure/core-contracts/)
- :octicons-people-16:{ .lg .middle } **Core Messaging Guides**
---
Explore this section for guides to using Wormhole Relayer and Core Contracts in your project.
[:custom-arrow: Build with Core Messaging](/docs/build/core-messaging/)
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/learn/infrastructure/architecture/
--- BEGIN CONTENT ---
---
title: Architecture
description: Overview of Wormhole's architecture, detailing key on-chain and off-chain components like the Core Contract, Guardian Network, and relayers.
categories: Basics
---
# Architecture
## Overview
Wormhole has several noteworthy components. Before discussing each component in depth, this page will provide an overview of how the major pieces fit together.

The preceding diagram outlines the end-to-end flow of multichain communication through Wormhole's architecture, which is described as follows:
1. **Source chain** - a source contract emits a message by interacting with the [Wormhole Core Contract](/docs/learn/infrastructure/core-contracts/){target=\_blank} on the source chain, which publishes the message in the blockchain's transaction logs
2. **Guardian Network** - [Guardians](/docs/learn/infrastructure/guardians/){target=\_blank} validate these messages and sign them to produce [Verifiable Action Approvals (VAAs)](/docs/learn/infrastructure/vaas/){target=\_blank}
3. **Relayers** - off-chain relayers or applications fetch the VAA and relay it to the target chain
4. **Target chain** - on the target chain, the message is consumed by the appropriate contract. This contract interacts with the Wormhole Core Contract to verify the VAA and execute the intended multichain operation.
The flow from the relayer to the target chain involves an entry point contract, which could vary based on the use case:
- In some applications, the target contract acts as the entry point and performs verification via the Core Contract
- In products like the Token Bridge, the Token Bridge contract itself interacts with the Core Contract
## On-Chain Components
- **Emitter** - a contract that calls the publish message method on the Core Contract. To identify the message, the Core Contract will write an event to the transaction logs with details about the emitter and sequence number. This may be your [xDapp](/docs/learn/glossary/#xdapp){target=\_blank} or an existing ecosystem protocol
- **[Wormhole Core Contract](/docs/learn/infrastructure/core-contracts/){target=\_blank}** - primary contract, this is the contract which the Guardians observe and which fundamentally allows for multichain communication
- **Transaction logs** - blockchain-specific logs that allow the Guardians to observe messages emitted by the Core Contract
## Off-Chain Components
- **Guardian Network** - validators that exist in their own P2P network. Guardians observe and validate the messages emitted by the Core Contract on each supported chain to produce VAAs (signed messages)
- **[Guardian](/docs/learn/infrastructure/guardians/){target=\_blank}** - one of 19 validators in the Guardian Network that contributes to the VAA multisig
- **[Spy](/docs/learn/infrastructure/spy/){target=\_blank}** - a daemon that subscribes to messages published within the Guardian Network. A Spy can observe and forward network traffic, which helps scale up VAA distribution
- **[API](https://docs.wormholescan.io/){target=\_blank}** - a REST server to retrieve details for a VAA or the Guardian Network
- **[VAAs](/docs/learn/infrastructure/vaas/){target=\_blank}** - Verifiable Action Approvals (VAAs) are the signed attestation of an observed message from the Wormhole Core Contract
- **[Relayer](/docs/learn/infrastructure/relayer/){target=\_blank}** - any off-chain process that relays a VAA to the target chain
- **Wormhole relayers** - a decentralized relayer network that delivers messages that are requested on-chain via the Wormhole relayer contract
- **Custom relayers** - relayers that only handle VAAs for a specific protocol or multichain application. They can execute custom logic off-chain, reducing gas costs and increasing multichain compatibility. Currently, multichain application developers are responsible for developing and hosting custom relayers
## Next Steps
- :octicons-book-16:{ .lg .middle } **Core Contracts**
---
Discover Wormhole's Core Contracts, enabling multichain communication with message sending, receiving, and multicast features for efficient synchronization.
[:custom-arrow: Explore Core Contracts](/docs/learn/infrastructure/core-contracts/)
- :octicons-tools-16:{ .lg .middle } **Core Messaging**
---
Follow the guides in this section to work directly with the building blocks of Wormhole messaging, Wormhole-deployed relayers and Core Contracts, to send, receive, validate, and track multichain messages.
[:custom-arrow: Build with Core Messaging](/docs/build/core-messaging/)
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/learn/infrastructure/core-contracts/
--- BEGIN CONTENT ---
---
title: Core Contracts
description: Discover Wormhole's Core Contracts, which enable multichain communication with message sending, receiving, and multicast features for efficient synchronization.
categories: Basics
---
# Core Contracts
## Introduction
The Wormhole Core Contract is deployed across each supported blockchain network. This contract is a fundamental component of the Wormhole interoperability protocol and acts as the foundational layer enabling secure and efficient multichain messaging. All multichain applications either interact directly with the Core Contract or with another contract that does.
This page summarizes the key functions of the Core Contract and outlines how the Core Contract works.
## Key Functions
Key functions of the Wormhole Core Contract include the following:
- **Multichain messaging** - standardizes and secures the format of messages to facilitate consistent communication for message transfer between Wormhole-connected blockchain networks, allowing developers to leverage the unique features of each network
- **Verification and validation** - verifies and validates all VAAs received on the target chain by confirming the Guardian signature to ensure the message is legitimate and has not been manipulated or altered
- **Guardian Network coordination** - coordinates with Wormhole's Guardian Network to facilitate secure, trustless communication across chains and ensure that only validated interactions are processed to enhance the protocol's overall security and reliability
- **Event emission for monitoring** - emits events for every multichain message processed, allowing for network activity monitoring like tracking message statuses, debugging, and applications that can react to multichain events in real time
## How the Core Contract Works
The Wormhole Core Contract is central in facilitating secure and efficient multichain transactions. It enables communication between different blockchain networks by packaging transaction data into standardized messages, verifying their authenticity, and ensuring they are executed correctly on the destination chain.
The following describes the role of the Wormhole Core Contract in message transfers:
1. **Message submission** - when a user initiates a multichain transaction, the Wormhole Core Contract on the source chain packages the transaction data into a standardized message payload and submits it to the Guardian Network for verification
2. **Guardian verification** - the Guardians independently observe and sign the message. Once enough Guardians have signed the message, the collection of signatures is combined with the message and metadata to produce a VAA
3. **Message reception and execution** - on the target chain, the Wormhole Core Contract receives the verified message, checks the Guardians' signatures, and executes the corresponding actions like minting tokens, updating states, or calling specific smart contract functions
For a closer look at how messages flow between chains and all of the components involved, you can refer to the [Architecture Overview](/docs/learn/infrastructure/architecture/) page.
### Message Submission
You can send multichain messages by calling a function against the source chain Core Contract, which then publishes the message. Message publishing strategies can differ by chain; however, generally, the Core Contract posts the following items to the blockchain logs:
- `emitterAddress` - the contract which made the call to publish the message
- `sequenceNumber` - a unique number that increments for every message for a given emitter (and implicitly chain)
- `consistencyLevel`- the level of finality to reach before the Guardians will observe and attest the emitted event. This is a defense against reorgs and rollbacks since a transaction, once considered "final," is guaranteed not to have the state changes it caused rolled back. Since different chains use different consensus mechanisms, each one has different finality assumptions, so this value is treated differently on a chain-by-chain basis. See the options for finality for each chain in the [Wormhole Finality](/docs/build/reference/consistency-levels/){target=\_blank} reference page
There are no fees to publish a message except when publishing on Solana, but this is subject to change in the future.
### Message Reception
When you receive a multichain message on the target chain Core Contract, you generally must parse and verify the [components of a VAA](/docs/learn/infrastructure/vaas#vaa-format){target=\_blank}. Receiving and verifying a VAA ensures that the Guardian Network properly attests to the message and maintains the integrity and authenticity of the data transmitted between chains.
## Multicast
Multicast refers to simultaneously broadcasting a single message or transaction across different blockchains with no destination address or chain for the sending and receiving functions. VAAs attest that "this contract on this chain said this thing." Therefore, VAAs are multicast by default and will be verified as authentic on any chain where they are used.
This multicast-by-default model makes it easy to synchronize state across the entire ecosystem. A blockchain can make its data available to every chain in a single action with low latency, which reduces the complexity of the n^2 problems encountered by routing data to many blockchains.
This doesn't mean an application _cannot_ specify a destination address or chain. For example, the [Token Bridge](/docs/learn/transfers/token-bridge/){target=\_blank} and [Wormhole relayer](/docs/learn/infrastructure/relayer/){target=\_blank} contracts require that some destination details be passed and verified on the destination chain.
Because the VAA creation is separate from relaying, the multicast model does not incur an additional cost when a single chain is targeted. If the data isn't needed on a certain blockchain, don't relay it there, and it won't cost anything.
## Next Steps
- :octicons-book-16:{ .lg .middle } **Verified Action Approvals (VAA)**
---
Learn about Verified Action Approvals (VAAs) in Wormhole, their structure, validation, and their role in multichain communication.
[:custom-arrow: Learn About VAAs](/docs/learn/infrastructure/vaas/)
- :octicons-tools-16:{ .lg .middle } **Get Started with Core Contracts**
---
This guide walks through the key methods of the Core Contracts, providing you with the knowledge needed to integrate them into your multichain contracts.
[:custom-arrow: Build with Core Contracts](/docs/build/core-messaging/core-contracts/)
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/learn/infrastructure/guardians/
--- BEGIN CONTENT ---
---
title: Guardians
description: Explore Wormhole's Guardian Network, a decentralized system for secure, scalable cross-chain communication across various blockchain ecosystems.
categories: Basics
---
## Guardian
Wormhole relies on a set of 19 distributed nodes that monitor the state on several blockchains. In Wormhole, these nodes are referred to as Guardians. The current Guardian set can be seen in the [Dashboard](https://wormhole-foundation.github.io/wormhole-dashboard/#/?endpoint=Mainnet){target=\_blank}.
Guardians fulfill their role in the messaging protocol as follows:
1. Each Guardian observes messages and signs the corresponding payloads in isolation from the other Guardians
2. Guardians combine their indpendent signatures to form a multisig
3. This multisig represents proof that a majority of the Wormhole network has observed and agreed upon a state
Wormhole refers to these multisigs as [Verifiable Action Approvals](/docs/learn/infrastructure/vaas/){target=\_blank} (VAAs).
## Guardian Network
The Guardian Network functions as Wormhole's decentralized oracle, ensuring secure, cross-chain interoperability. Learning about this critical element of the Wormhole ecosystem will help you better understand the protocol.
The Guardian Network is designed to help Wormhole deliver on five key principles:
- **Decentralization** - control of the network is distributed across many parties
- **Modularity** - independent components (e.g., oracle, relayer, applications) ensure flexibility and upgradeability
- **Chain agnosticism** - supports EVM, Solana, and other blockchains without relying on a single network
- **Scalability** - can handle large transaction volumes and high-value transfers
- **Upgradeable** - can change the implementation of its existing modules without breaking integrators to adapt to changes in decentralized computing
The following sections explore each principle in detail.
### Decentralization
Decentralization remains the core concern for interoperability protocols. Earlier solutions were fully centralized, and even newer models often rely on a single entity or just one or two actors, creating low thresholds for collusion or failure.
Two common approaches to decentralization have notable limitations:
- **Proof-of-Stake (PoS)** - while PoS is often seen as a go-to model for decentralization, it's not well-suited for a network that verifies many blockchains and doesn't run its own smart contracts. Its security in this context is unproven, and it introduces complexities that make other design goals harder to achieve
- **Zero-Knowledge Proofs (ZKPs)** - ZKPs offer a trustless and decentralized approach, but the technology is still early-stage. On-chain verification is often too computationally expensive—especially on less capable chains—so a multisig-based fallback is still required for practical deployment
In the current De-Fi landscape, most major blockchains are secured by a small group of validator companies. Only a limited number of companies worldwide have the expertise and capital to run high-performance validators.
If a protocol could unite many of these top validator companies into a purpose-built consensus mechanism designed for interoperability, it would likely offer better performance and security than a token-incentivized network. The key question is: how many of them could Wormhole realistically involve?
To answer that, consider these key constraints and design decisions:
- **Threshold signatures allow flexibility, but** - with threshold signatures, in theory, any number of validators could participate. However, threshold signatures are not yet widely supported across blockchains. Verifying them is expensive and complex, especially in a chain-agnostic system
- **t-Schnorr multisig is more practical** - Wormhole uses [t-Schnorr multisig](https://en.wikipedia.org/wiki/Schnorr_signature){target=\_blank}, which is broadly supported and relatively inexpensive to verify. However, verification costs scale linearly with the number of signers, so the size of the validator set needs to be carefully chosen
- **19 validators is the optimal tradeoff** - a set of 19 participants presents a practical compromise between decentralization and efficiency. With a two-thirds consensus threshold, only 13 signatures must be verified on-chain—keeping gas costs reasonable while ensuring strong security
- **Security through reputation, not tokens** - Wormhole relies on a network of established validator companies instead of token-based incentives. These 19 Guardians are among the most trusted operators in the industry—real entities with a track record, not anonymous participants
This forms the foundation for a purpose-built Proof-of-Authority (PoA) consensus model, where each Guardian has an equal stake. As threshold signatures gain broader support, the set can expand. Once ZKPs become widely viable, the network can evolve into a fully trustless system.
### Modularity
Wormhole is designed with simple components that are very good at a single function. Separating security and consensus (Guardians) from message delivery ([relayers](/docs/learn/infrastructure/relayer/){target=\_blank}) allows for the flexibility to change or upgrade one component without disrupting the others.
### Chain Agnosticism
Today, Wormhole supports a broader range of ecosystems than any other interoperability protocol because it uses simple tech (t-schnorr signatures), an adaptable, heterogeneous relayer model, and a robust validator network. Wormhole can expand to new ecosystems as quickly as a [Core Contract](/docs/learn/infrastructure/core-contracts/){target=\_blank} can be developed for the smart contract runtime.
### Scalability
Wormhole scales well, as demonstrated by its ability to handle substantial total value locked (TVL) and transaction volume even during tumultuous events.
Every Guardian must run a full node for every blockchain in the ecosystem. This requirement can be computationally heavy to set up; however, once all the full nodes are running, the Guardian Network's actual computation needs become lightweight.
Performance is generally limited by the speed of the underlying blockchains, not the Guardian Network itself.
### Upgradeable
Wormhole is designed to adapt and evolve in the following ways:
- **Guardian Set expansion** – future updates may introduce threshold signatures to allow for more Guardians in the set
- **ZKP integration** - as Zero-Knowledge Proofs become more widely supported, the network can transition to a fully trustless model
These principles combine to create a clear pathway towards a fully trustless interoperability layer that spans decentralized computing.
## Next Steps
- :octicons-book-16:{ .lg .middle } **Relayers**
---
Discover the role of relayers in the Wormhole network, including client-side, custom, and Wormhole-deployed types, for secure cross-chain communication.
[:custom-arrow: Learn About Relayers](/docs/learn/infrastructure/relayer/)
- :octicons-tools-16:{ .lg .middle } **Query Guardian Data**
---
Learn how to use Wormhole Queries to add real-time access to Guardian-attested on-chain data via a REST endpoint to your dApp, enabling secure cross-chain interactions and verifications.
[:custom-arrow: Build with Queries](/docs/build/queries/overview/)
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/learn/infrastructure/relayer/
--- BEGIN CONTENT ---
---
title: Relayers
description: Discover the role of relayers in the Wormhole network, including client-side, custom, and Wormhole-deployed types, for secure cross-chain communication.
categories: Basics
---
# Relayers
This page provides a comprehensive guide to relayers within the Wormhole network, describing their role, types, and benefits in facilitating cross-chain processes.
Relayers in the Wormhole context are processes that deliver [Verified Action Approvals (VAAs)](/docs/learn/infrastructure/vaas/){target=\_blank} to their destination, playing a crucial role in Wormhole's security model. They can't compromise security, only availability, and act as delivery mechanisms for VAAs without the capacity to tamper with the outcome.
There are three primary types of relayers discussed:
- **Client-side relaying** - a cost-efficient, no-backend-infrastructure approach relying on user-facing front ends. It provides a simple solution, although it can complicate the user experience due to the manual steps involved
- **Custom relayers** - backend components that handle parts of the cross-chain process, offering a smoother user experience and allowing off-chain calculations to reduce gas costs. These relayers could operate through direct listening to the Guardian Network (Spy relaying)
- **Wormhole-deployed relayers** - a decentralized relayer network that can deliver arbitrary VAAs, reducing the developer's need to develop, host, or maintain relayers. However, they require all calculations to be done on-chain and might be less gas-efficient
## Fundamentals
This section highlights the crucial principles underpinning the operation and handling of relayers within the Wormhole network.
Relayers are fundamentally trustless entities within the network, meaning while they don't require your trust to operate, you also shouldn't trust them implicitly. Relayers function as delivery mechanisms, transporting VAAs from their source to their destination.
Key characteristics of VAAs include:
- Public emission from the Guardian Network
- Authentication through signatures from the Guardian Network
- Verifiability by any entity or any Wormhole Core Contract
These characteristics mean anyone can pick up a VAA and deliver it anywhere, but no one can alter the VAA content without invalidating the signatures.
Keep in mind the following security considerations around relayers:
- **Trusting information** - it is crucial not to trust information outside your contract or a VAA. Relying on information from a relayer could expose you to input attacks
- **Gas optimization** - using relayers to perform trustless off-chain computation to pass into the destination contract can optimize gas costs but also risk creating attack vectors if not used correctly
- **Deterministic by design** - the design of a relayer should ensure a single, deterministic way to process messages in your protocol. Relayers should have a "correct" implementation, mirroring "crank turner" processes used elsewhere in blockchain
## Client-Side Relaying
Client-side relaying relies on user-facing front ends, such as a webpage or a wallet, to complete the cross-chain process.
### Key Features
- **Cost-efficiency** - users only pay the transaction fee for the second transaction, eliminating any additional costs
- **No backend infrastructure** - the process is wholly client-based, eliminating the need for a backend relaying infrastructure
### Implementation
Users themselves carry out the three steps of the cross-chain process:
1. Perform an action on chain A
2. Retrieve the resulting VAA from the Guardian Network
3. Perform an action on chain B using the VAA
### Considerations
Though simple, this type of relaying is generally not recommended if your aim is a highly polished user experience. It can, however, be useful for getting a Minimum Viable Product (MVP) up and running.
- Users must sign all required transactions with their own wallet
- Users must have funds to pay the transaction fees on every chain involved
- The user experience may be cumbersome due to the manual steps involved
## Custom Relayers
Custom relayers are purpose-built components within the Wormhole protocol, designed to relay messages for specific applications. They can perform off-chain computations and can be customized to suit a variety of use cases.
The main method of setting up a custom relayer is by listening directly to the Guardian Network via a [Spy](/docs/learn/infrastructure/spy/).
### Key Features
- **Optimization** - capable of performing trustless off-chain computations which can optimize gas costs
- **Customizability** - allows for specific strategies like batching, conditional delivery, multi-chain deliveries, and more
- **Incentive structure** - developers have the freedom to design an incentive structure suitable for their application
- **Enhanced UX** - the ability to retrieve a VAA from the Guardian Network and perform an action on the target chain using the VAA on behalf of the user can simplify the user experience
### Implementation
A plugin relayer to make the development of custom relayers easier is available in the [main Wormhole repository](https://github.com/wormhole-foundation/wormhole/tree/main/relayer){target=\_blank}. This plugin sets up the basic infrastructure for relaying, allowing developers to focus on implementing the specific logic for their application.
### Considerations
Remember, despite their name, custom relayers still need to be considered trustless. VAAs are public and can be submitted by anyone, so developers shouldn't rely on off-chain relayers to perform any computation considered "trusted."
- Development work and hosting of relayers are required
- The fee-modeling can become complex, as relayers are responsible for paying target chain fees
- Relayers are responsible for availability, and adding dependencies for the cross-chain application
## Wormhole Relayers
Wormhole relayers are a component of a decentralized network in the Wormhole protocol. They facilitate the delivery of VAAs to recipient contracts compatible with the standard relayer API.
### Key Features
- **Lower operational costs** - no need to develop, host, or maintain individual relayers
- **Simplified integration** - because there is no need to run a relayer, integration is as simple as calling a function and implementing an interface
### Implementation
The Wormhole relayer integration involves two key steps:
- **Delivery request** - request delivery from the ecosystem Wormhole relayer contract
- **Relay reception** - implement a [`receiveWormholeMessages`](https://github.com/wormhole-foundation/wormhole-solidity-sdk/blob/bacbe82e6ae3f7f5ec7cdcd7d480f1e528471bbb/src/interfaces/IWormholeReceiver.sol#L44-L50){target=\_blank} function within their contracts. This function is invoked upon successful relay of the VAA
### Considerations
Developers should note that the choice of relayers depends on their project's specific requirements and constraints. Wormhole relayers offer simplicity and convenience but limit customization and optimization opportunities compared to custom relayers.
- All computations are performed on-chain
- Potentially less gas-efficient compared to custom relayers
- Optimization features like conditional delivery, batching, and off-chain calculations might be restricted
- Support may not be available for all chains
## Next Steps
- :octicons-book-16:{ .lg .middle } **Spy**
---
Discover Wormhole's Spy daemon, which subscribes to gossiped messages in the Guardian Network, including VAAs and Observations, with setup instructions.
[:custom-arrow: Learn More About the Spy](/docs/learn/infrastructure/spy/)
- :octicons-book-16:{ .lg .middle } **Build with Wormhole Relayers**
---
Learn how to use Wormhole-deployed relayer configurations for seamless cross-chain messaging between contracts on different EVM blockchains without off-chain deployments.
[:custom-arrow: Get Started with Wormhole Relayers](/docs/build/core-messaging/wormhole-relayers/)
- :octicons-book-16:{ .lg .middle } **Run a Custom Relayer**
---
Learn how to build and configure your own off-chain custom relaying solution to relay Wormhole messages for your applications using the Relayer Engine.
[:custom-arrow: Get Started with Custom Relayers](/docs/infrastructure/relayers/run-relayer/)
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/learn/infrastructure/spy/
--- BEGIN CONTENT ---
---
title: Spy
description: Discover Wormhole's Spy daemon, which subscribes to gossiped messages in the Guardian Network, including VAAs and Observations, with setup instructions.
categories: Basics
---
# Spy
In Wormhole's ecosystem, the _Spy_ is a daemon, a continuously running background process that monitors messages within the Guardian Network. Unlike Guardians, a Spy doesn't perform validation; instead, it serves as an interface for observing the network's message traffic, enabling applications and users to access live data transmitted over Wormhole.
The primary purpose of a Spy is to subscribe to the gossiped messages across the Guardian Network, tracking key message types that allow integrators and applications to monitor real-time network activity without directly engaging in consensus operations.
This page provides a comprehensive guide to where the Spy fits within the Wormhole network, describing the key features and role in facilitating multichain processes.
## Key Features
- **Real-time monitoring of Wormhole messages** - the Spy allows users to observe Wormhole messages as they are published across supported chains in near real-time
- **Filterable and observable message streams** - users can filter message streams by chain, emitter, and other criteria, making it easier to track specific contracts or categories of interest
- **Integration-friendly event streaming** - the Spy exposes gRPC and WebSocket interfaces, making it easy to integrate message observation into custom tooling, dashboards, or indexing services
- **Support for multiple message protocols** - it can observe messages from different Wormhole messaging protocols (Token Bridge, CCTP, NTT, etc.), providing broad coverage of cross-chain activity
- **Lightweight and infrastructure-ready** - the Spy is designed to run as part of indexing or backend services, not requiring validator-level infrastructure
## Integrator Use Case
The Spy provides a valuable mechanism for integrators to observe real-time network activity in the Guardian Network without directly engaging in validation or consensus. By running a Spy, integrators can track multichain events and message flows — such as VAAs, observations, and Guardian heartbeats — to monitor network activity essential to their applications.
This monitoring capability is especially beneficial for applications that need immediate insights into multichain data events. Integrators can run a Spy to ensure their applications are promptly informed of message approvals, observations, or Guardian liveness signals, supporting timely and responsive app behavior without additional overhead on network resources.
## Observable Message Categories
A Spy can access the following categories of messages shared over the gossip protocol:
- [Verifiable Action Approvals (VAAs)](/docs/learn/infrastructure/vaas/){target=\_blank} - packets of multichain data
- The Spy can detect whether a VAA has been approved by the Guardian Network, making it a valuable tool for applications needing real-time multichain verification
- [Observations](/docs/learn/glossary/#observation){target=\_blank} - emitted by Wormhole's core contracts, observations are picked up by the Guardians and relayed across the network
- A Spy allow users to monitor these messages, adding transparency and insight into blockchain events
- [Guardian heartbeats](/docs/learn/glossary/#heartbeat){target=\_blank} - heartbeat messages represent Guardian node status
- By monitoring heartbeats, a Spy can signal the liveness and connectivity of Guardians in the network
## Additional Resources
- :octicons-code-16:{ .lg .middle } **Spy Source Code**
---
To see the source code for the Go implementation of the Spy, visit the `wormhole` repository on GitHub.
[:custom-arrow: View the Source Code](https://github.com/wormhole-foundation/wormhole/blob/main/node/cmd/spy/spy.go){target=\_blank}
- :octicons-code-16:{ .lg .middle } **Alternative Implementation**
---
Visit the `beacon` repository on GitHub to learn more about Beacon, an alternative highly available, reduced-latency version of the Wormhole Spy.
[:custom-arrow: Get Started with Pyth Beacon](https://github.com/pyth-network/beacon)
- :octicons-book-16:{ .lg .middle } **Discover Wormhole Queries**
---
For an alternative option to on-demand access to Guardian-attested multichain data, see the Wormhole Queries page. Queries provide a simple, REST endpoint style developer experience.
[:custom-arrow: Explore Queries](/docs/build/queries/overview/)
## Next Steps
- :octicons-code-16:{ .lg .middle } **Run a Spy**
---
Learn how to run the needed infrastructure to spin up a Spy daemon locally and subscribe to a stream of Verifiable Action Approvals (VAAs).
[:custom-arrow: Spin Up a Spy](/docs/infrastructure/spy/run-spy/){target=\_blank}
- :octicons-code-16:{ .lg .middle } **Use Queries**
---
For access to real-time network data without infrastructure overhead, follow this guide and use Wormhole Query to construct a query, make a request, and verify the response.
[:custom-arrow: Get Started with Queries](/docs/build/queries/use-queries/)
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/learn/infrastructure/vaas/
--- BEGIN CONTENT ---
---
title: VAAs
description: Learn about Verified Action Approvals (VAAs) in Wormhole, their structure, validation, and role in cross-chain communication.
categories: Basics
---
# Verified Action Approvals
Verified Action Approvals (VAAs) are Wormhole's core messaging primitive. They are packets of cross-chain data emitted whenever a cross-chain application contract interacts with the Core Contract.
[Guardians](/docs/learn/infrastructure/guardians/){target=\_blank} validate messages emitted by contracts before sending them to the target chain. Once a majority of Guardians agree the message is valid, they sign a keccak256 hash of the message body.
The message is wrapped up in a structure called a VAA, which combines the message with the Guardian signatures to form a proof.
VAAs are uniquely indexed by the (`emitter_chain`, `emitter_address`, `sequence`) tuple. To obtain a VAA, one can query the [Wormholescan API](https://docs.wormholescan.io/){target=\_blank} with this information.
The `sequence` field depends on the final ordering of blocks on the emitter chain. When a lower consistency level is chosen (i.e., not waiting for finality), there is a chance that chain reorganizations could lead to multiple, different VAAs appearing for what looks like the “same” message on the user side.
The tuple (`emitter_chain`, `emitter_address`, `sequence`) can only be considered unique if the chain does not undergo a reorg and the block containing the message has effectively reached finality. However, there is always a small chance of an extended reorg that could invalidate or alter a previously emitted sequence number.
## VAA Format
The basic VAA consists of header and body components described as follows:
- **Header** - holds metadata about the current VAA, the Guardian set that is currently active, and the list of signatures gathered so far
- `version` ++"byte"++ - the VAA Version
- `guardian_set_index` ++"u32"++ - indicates which Guardian set is signing
- `len_signatures` ++"u8"++ - the number of signatures stored
- `signatures` ++"[]signature"++ - the collection of Guardian signatures
Where each `signature` is:
- `index` ++"u8"++ - the index of this Guardian in the Guardian set
- `signature` ++"[65]byte"++ - the ECDSA signature
- **Body** - _deterministically_ derived from an on-chain message. Any two Guardians processing the same message must derive the same resulting body to maintain a one-to-one relationship between VAAs and messages to avoid double-processing messages
- `timestamp` ++"u32"++ - the timestamp of the block this message was published in
- `nonce` ++"u32"++
- `emitter_chain` ++"u16"++ - the id of the chain that emitted the message
- `emitter_address` ++"[32]byte"++ - the contract address (Wormhole formatted) that called the Core Contract
- `sequence` ++"u64"++ - the auto-incrementing integer that represents the number of messages published by this emitter
- `consistency_level` ++"u8"++ - the consistency level (finality) required by this emitter
- `payload` ++"[]byte"++ - arbitrary bytes containing the data to be acted on
The deterministic nature of the body is only strictly true once the chain's state is finalized. If a reorg occurs, and a transaction that previously appeared in block X is replaced by block Y, Guardians observing different forks may generate different VAAs for what the emitter contract believes is the same message. This scenario is less likely once a block is sufficiently buried, but it can still happen if you choose a faster (less finalized) consistency level
The body contains relevant information for entities, such as contracts or other systems, that process or utilize VAAs. When a function like `parseAndVerifyVAA` is called, the body is returned, allowing verification of the `emitterAddress` to determine if the VAA originated from a trusted contract.
Because VAAs have no destination, they are effectively multicast. Any Core Contract on any chain in the network will verify VAAs as authentic. If a VAA has a specific destination, relayers are responsible for appropriately completing that delivery.
## Consistency and Finality
The consistency level determines whether Guardians wait for a chain's final commitment state or issue a VAA sooner under less-final conditions. This choice is especially relevant for blockchains without instant finality, where the risk of reorganization remains until a block is deeply confirmed.
Guardian watchers are specialized processes that monitor each blockchain in real-time. They enforce the selected consistency level by deciding whether enough commitment has been reached before signing and emitting a VAA. Some chains allow only one commitment level (effectively final), while others let integrators pick between near-final or fully finalized states. Choosing a faster option speeds up VAA production but increases reorg risk. A more conservative option takes longer but reduces the likelihood of rollback.
## Signatures
The body of the VAA is hashed twice with `keccak256` to produce the signed digest message.
```js
// hash the bytes of the body twice
digest = keccak256(keccak256(body))
// sign the result
signature = ecdsa_sign(digest, key)
```
!!!tip "Hash vs. double hash"
Different implementations of the ECDSA signature validation may apply a keccak256 hash to the message passed, so care must be taken to pass the correct arguments.
For example, the [Solana secp256k1 program](https://docs.solanalabs.com/runtime/programs#secp256k1-program){target=\_blank} will hash the message passed. In this case, the argument for the message should be a single hash of the body, not the twice-hashed body.
## Payload Types
Different applications built on Wormhole may specify a format for the payloads attached to a VAA. This payload provides information on the target chain and contract so it can take action (e.g., minting tokens to a receiver address).
### Token Transfer
Many bridges use a lockup/mint and burn/unlock mechanism to transfer tokens between chains. Wormhole's generic message-passing protocol handles the routing of lock and burn events across chains to ensure Wormhole's Token Bridge is chain-agnostic and can be rapidly integrated into any network with a Wormhole contract.
Transferring tokens from the sending chain to the destination chain requires the following steps:
1. Lock the token on the sending chain
2. The sending chain emits a message as proof the token lockup is complete
3. The destination chain receives the message confirming the lockup event on the sending chain
4. The token is minted on the destination chain
The message the sending chain emits to verify the lockup is referred to as a transfer message and has the following structure:
- `payload_id` ++"u8"++ - the ID of the payload. This should be set to `1` for a token transfer
- `amount` ++"u256"++ - amount of tokens being transferred
- `token_address` ++"u8[32]"++ - address on the source chain
- `token_chain` ++"u16"++ - numeric ID for the source chain
- `to` ++"u8[32]"++ - address on the destination chain
- `to_chain` ++"u16"++ - numeric ID for the destination chain
- `fee` ++"u256"++ - portion of amount paid to a relayer
This structure contains everything the destination chain needs to learn about a lockup event. Once the destination chain receives this payload, it can mint the corresponding asset.
Note that the destination chain is agnostic regarding how the tokens on the sending side were locked. They could have been burned by a mint or locked in a custody account. The protocol relays the event once enough Guardians have attested to its existence.
### Attestation
While the destination chain can trust the message from the sending chain to inform it of token lockup events, it has no way of verifying the correct token is locked up. To solve this, the Token Bridge supports token attestation.
To create a token attestation, the sending chain emits a message containing metadata about a token, which the destination chain may use to preserve the name, symbol, and decimal precision of a token address.
The message format for token attestation is as follows:
- `payload_id` ++"u8"++ - the ID of the payload. This should be set to `2` for an attestation
- `token_address` ++"[32]byte"++ - address of the originating token contract
- `token_chain` ++"u16"++ - chain ID of the originating token
- `decimals` ++"u8"++ - number of decimals this token should have
- `symbol` ++"[32]byte"++ - short name of asset
- `name` ++"[32]byte"++ - full name of asset
#### Attestation Tips
Be aware of the following considerations when working with attestations:
- Attestations use a fixed-length byte array to encode UTF8 token name and symbol data. Because the byte array is fixed length, the data contained may truncate multibyte Unicode characters
- When sending an attestation VAA, it is recommended to send the longest UTF8 prefix that doesn't truncate a character and then right-pad it with zero bytes
- When parsing an attestation VAA, it is recommended to trim all trailing zero bytes and convert the remainder to UTF-8 via any lossy algorithm
- Be mindful that different on-chain systems may have different VAA parsers, resulting in different names/symbols on different chains if the string is long or contains invalid UTF8
- Without knowing a token's decimal precision, the destination chain cannot correctly mint the number of tokens when processing a transfer. For this reason, the Token Bridge requires an attestation for each token transfer
### Token Transfer with Message
The Token Transfer with Message data structure is identical to the token-only data structure, except for the following:
- **`fee` field** - replaced with the `from_address` field
- **`payload` field** - is added containing arbitrary bytes. A dApp may include additional data in this arbitrary byte field to inform some application-specific behavior
This VAA type was previously known as Contract Controlled Transfer and is also sometimes referred to as a `payload3` message. The Token Transfer with Message data sructure is as follows:
- `payload_id` ++"u8"++ - the ID of the payload. This should be set to `3` for a token transfer with message
- `amount` ++"u256"++ - amount of tokens being transferred
- `token_address` ++"u8[32]"++ - address on the source chain
- `token_chain` ++"u16"++ - numeric ID for the source chain
- `to` ++"u8[32]"++ - address on the destination chain
- `to_chain` ++"u16"++ - numeric ID for the destination chain
- `from_address` ++"u8[32]"++ - address that called the Token Bridge on the source chain
- `payload` ++"[]byte"++ - message, arbitrary bytes, app-specific
### Governance
Governance VAAs don't have a `payload_id` field like the preceding formats. Instead, they trigger an action in the deployed contracts (for example, an upgrade).
#### Action Structure
Governance messages contain pre-defined actions, which can target the various Wormhole modules currently deployed on-chain. The structure includes the following fields:
- `module` ++"u8[32]"++ - contains a right-aligned module identifier
- `action` ++"u8"++ - predefined governance action to execute
- `chain` ++"u16"++ - chain the action is targeting. This should be set to `0` for all chains
- `args` ++"any"++ - arguments to the action
Below is an example message containing a governance action triggering a code upgrade to the Solana Core Contract. The module field here is a right-aligned encoding of the ASCII Core, represented as a 32-byte hex string.
```js
module: 0x0000000000000000000000000000000000000000000000000000436f7265
action: 1
chain: 1
new_contract: 0x348567293758957162374959376192374884562522281937446234828323
```
#### Actions
The meaning of each numeric action is pre-defined and documented in the Wormhole design documents. For each application, the relevant definitions can be found via these links:
- [Core governance actions](https://github.com/wormhole-foundation/wormhole/blob/main/whitepapers/0002_governance_messaging.md){target=\_blank}
- [Token Bridge governance actions](https://github.com/wormhole-foundation/wormhole/blob/main/whitepapers/0003_token_bridge.md){target=\_blank}
## Lifetime of a Message
Anyone can submit a VAA to the target chain. Guardians typically don't perform this step to avoid transaction fees. Instead, applications built on top of Wormhole can acquire a VAA via the Guardian RPC and submit it in a separate flow.
With the concepts now defined, it is possible to illustrate a full flow for message passing between two chains. The following stages demonstrate each step of processing that the Wormhole network performs to route a message.
1. **A message is emitted by a contract running on Chain A** - any contract can emit messages, and the Guardians are programmed to observe all chains for these events. Here, the Guardians are represented as a single entity to simplify the graphics, but the observation of the message must be performed individually by each of the 19 Guardians
2. **Signatures are aggregated** - Guardians independently observe and sign the message. Once enough Guardians have signed the message, the collection of signatures is combined with the message and metadata to produce a VAA
3. **VAA submitted to target chain** - the VAA acts as proof that the Guardians have collectively attested the existence of the message payload. The VAA is submitted (or relayed) to the target chain to be processed by a receiving contract and complete the final step

## Next Steps
- :octicons-book-16:{ .lg .middle } **Guardians**
---
Explore Wormhole's Guardian Network, a decentralized system for secure, scalable cross-chain communication across various blockchain ecosystems.
[:custom-arrow: Learn About Guardians](/docs/learn/infrastructure/guardians/)
- :octicons-tools-16:{ .lg .middle } **Wormhole Relayer**
---
Explore this guide to using Wormhole-deployed relayers to send and receive messages using VAAs.
[:custom-arrow: Build with Wormhole Relayer](/docs/build/core-messaging/wormhole-relayers/)
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/learn/introduction/
--- BEGIN CONTENT ---
---
title: Introduction to Wormhole
description: Wormhole is a protocol for seamless communication between blockchains, enabling cross-chain applications and integrations.
categories: Basics
---
# Introduction to Wormhole
In the rapidly evolving landscape of blockchain technology, interoperability between different blockchains remains a significant challenge. Developers often face hurdles in creating applications that can seamlessly operate across multiple blockchains, limiting innovation and the potential of decentralized ecosystems.
Wormhole addresses this problem by providing a _generic message-passing_ protocol that enables secure and efficient communication between blockchains. By allowing data and asset transfers across various blockchain networks, Wormhole breaks down the walls that traditionally separate these ecosystems.
Wormhole is distinguished by its focus on robust security, scalability, and transparency. The protocol is supported by a decentralized network of validators that ensure the integrity of every cross-chain transaction. This, combined with Wormhole’s proven performance in real-world applications, gives developers a dependable platform to create and scale multichain applications confidently.

!!! note
The above is an oversimplified illustration of the protocol; details about the architecture and components are available on the [architecture page](/docs/learn/infrastructure/architecture/){target=\_blank}.
Wormhole allows developers to leverage the strengths of multiple blockchain ecosystems without being confined to one. This means applications can benefit from the unique features of various networks—such as Solana's high throughput, Ethereum's security, and Cosmos's interoperability while maintaining a unified, efficient user experience.
This page introduces the key concepts and components necessary to understand how Wormhole enables fast, secure, and scalable cross-chain communication.
## What Problems Does Wormhole Solve?
Interoperability is a critical challenge in the rapidly evolving blockchain landscape. Individual blockchains are often isolated, limiting the potential for integrated applications operating across multiple ecosystems. Wormhole solves this problem by enabling seamless communication between blockchains, allowing developers to create multichain applications that can leverage the unique features of each network.
Critical problems Wormhole addresses include:
- **Blockchain isolation** - Wormhole connects disparate blockchains, enabling the transfer of assets, data, and governance actions across networks
- **Cross-chain complexity** - by abstracting the complexities of cross-chain communication, Wormhole makes it easier for developers to build and deploy cross-chain applications
- **Security and decentralization** - Wormhole prioritizes security through a decentralized Guardian network that validates and signs messages, ensuring the integrity of cross-chain interactions
## What Does Wormhole Offer?
Wormhole provides a suite of tools and protocols that support a wide range of use cases:
- **Cross-chain messaging** - securely transfer arbitrary data between blockchains, enabling the development of cross-chain decentralized applications (xDapps)
- **Asset transfers** - facilitate the movement of tokens and NFTs across supported chains with ease, powered by protocols built on Wormhole like [Portal](https://portalbridge.com/){target=\_blank}
- **Developer tools** - leverage [Wormhole’s SDKs](/docs/build/toolkit/typescript-sdk/){target=\_blank}, [APIs](/docs/build/toolkit/#wormhole-api-docs){target=\_blank}, [Wormhole Scan](https://wormholescan.io/){target=\_blank}, and documentation to build and deploy cross-chain applications quickly and efficiently
## What Isn't Wormhole?
- **Wormhole is _not_ a blockchain** - it acts as a communication layer that connects different blockchains, enabling them to interact without being a blockchain itself
- **Wormhole is _not_ a token bridge** - while it facilitates token transfers, Wormhole also supports a wide range of cross-chain applications, making it much more versatile than a typical bridge
## Use Cases of Wormhole
Consider the following examples of potential applications enabled by Wormhole:
- **Cross-chain exchange** - using [Wormhole Connect](/docs/build/transfers/connect/overview/){target=\_blank}, developers can build exchanges that allow deposits from any Wormhole-connected chain, significantly increasing liquidity access
- **[Cross-chain governance](https://wormhole.com/blog/stake-for-governance-is-now-live-for-w-token-holders){target=\_blank}** - NFT collections on different networks can use Wormhole to communicate votes cast on their respective chains to a designated "voting" chain for combined proposals
- **Cross-chain game** - games can be developed on a performant network like Solana, with rewards issued as NFTs on another network, such as Ethereum
## Explore
Discover more about the Wormhole ecosystem, components, and protocols:
- **[Architecture](/docs/learn/infrastructure/architecture/){target=\_blank}** - explore the components of the protocol
- **[Protocol Specifications](https://github.com/wormhole-foundation/wormhole/tree/main/whitepapers){target=\_blank}** - learn about the protocols built on top of Wormhole
## Demos
Demos offer more realistic implementations than tutorials:
- **[Wormhole Scaffolding](https://github.com/wormhole-foundation/wormhole-scaffolding){target=\_blank}** - quickly set up a project with the Scaffolding repository
- **[xDapp Book Projects](https://github.com/wormhole-foundation/xdapp-book/tree/main/projects){target=\_blank}** - run and learn from example programs
!!! note
Wormhole Integration Complete?
Let us know so we can list your project in our ecosystem directory and introduce you to our global, multichain community!
**[Reach out now!](https://forms.clickup.com/45049775/f/1aytxf-10244/JKYWRUQ70AUI99F32Q){target=\_blank}**
## Supported Blockchains
Wormhole supports a growing number of blockchains.
### EVM
| Ethereum | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Acala | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Arbitrum | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Avalanche | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Base | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Berachain | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Blast | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| BNB Smart Chain | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Celo | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Fantom | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Gnosis | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| HyperEVM | EVM | :x: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs |
| Ink | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Kaia | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Karura | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs |
| Linea | EVM | :x: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Mantle | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Mezo | EVM | :x: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Monad | EVM | :x: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Moonbeam | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Neon | EVM | :x: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Oasis | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Optimism | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Polygon | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Scroll | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Seievm | EVM | :x: | :white_check_mark: | |
| SNAXchain | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Unichain | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| World Chain | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| X Layer | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
### SVM
| Solana | SVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Pythnet | SVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
### AVM
| Algorand | AVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
### CosmWasm
| Injective | CosmWasm | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Neutron | CosmWasm | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Osmosis | CosmWasm | :x: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Sei | CosmWasm | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Terra | CosmWasm | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Terra 2.0 | CosmWasm | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| XPLA | CosmWasm | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
### Move VM
| Aptos | Move VM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
### NEAR VM
| NEAR | NEAR VM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
### Sui Move VM
| Sui | Sui Move VM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/learn/security/
--- BEGIN CONTENT ---
---
title: Security
description: Explore Wormhole's security features, including the Guardian network, governance, monitoring, open-source development, and bug bounty programs.
categories: Basics
---
# Security
## Core Security Assumptions
At its core, Wormhole is secured by a network of [Guardian](/docs/learn/infrastructure/guardians/){target=\_blank} nodes that validate and sign messages. If a super majority (e.g., 13 out of 19) of Guardians sign the same message, it can be considered valid. A smart contract on the target chain will verify the signatures and format of the message before approving any transaction.
- Wormhole's core security primitive is its signed messages (signed [VAAs](/docs/learn/glossary/#vaa){target=\_blank})
- The Guardian network is currently secured by a collection of 19 of the world's top [validator companies](https://wormhole-foundation.github.io/wormhole-dashboard/#/?endpoint=Mainnet){target=\_blank}
- Guardians produce signed state attestations (signed VAAs) when requested by a Core Contract integrator
- Every Guardian runs full nodes (rather than light nodes) of every blockchain in the Wormhole network, so if a blockchain suffers a consensus attack or hard fork, the blockchain will disconnect from the network rather than potentially produce invalid signed VAAs
- Any Signed VAA can be verified as authentic by the Core Contract of any other chain
- [Relayers](/docs/learn/glossary/#relayer){target=\_blank} are considered untrusted in the Wormhole ecosystem
In summary:
- **Core integrators aren't exposed to risk from chains and contracts they don't integrate with**
- By default, you only trust Wormhole's signing process and the core contracts of the chains you're on
- You can expand your contract and chain dependencies as you see fit
Core assumptions aside, many other factors impact the real-world security of decentralized platforms. Here is more information on additional measures that have been put in place to ensure the security of Wormhole.
## Guardian Network
Wormhole is an evolving platform. While the Guardian set currently comprises 19 validators, this is a limitation of current blockchain technology.
### Governance
Governance is the process through which contract upgrades happen. Guardians manually vote on governance proposals that originate inside the Guardian Network and are then submitted to ecosystem contracts.
This means that governance actions are held to the same security standard as the rest of the system. A two-thirds supermajority of the Guardians is required to pass any governance action.
Governance messages can target any of the various wormhole modules, including the core contracts and all currently deployed token bridge contracts. When a Guardian signs such a message, its signature implies a vote on the action in question. Once more than two-thirds of the Guardians have signed, the message and governance action are considered valid.
All governance actions and contract upgrades have been managed via Wormhole's on-chain governance system.
Via governance, the Guardians can:
- Change the current Guardian set
- Expand the Guardian set
- Upgrade ecosystem contract implementations
The governance system is fully open source in the core repository. See the [Open Source section](#open-source){target=\_blank} for contract source.
## Monitoring
A key element of Wormhole's defense-in-depth strategy is that each Guardian is a highly competent validator company with its own in-house processes for running, monitoring, and securing blockchain operations. This heterogeneous approach to monitoring increases the likelihood that fraudulent activity is detected and reduces the number of single failure points in the system.
Guardians are not just running Wormhole validators; they're running validators for every blockchain inside of Wormhole as well, which allows them to perform monitoring holistically across decentralized computing rather than just at a few single points.
Guardians monitor:
- Block production and consensus of each blockchain - if a blockchain's consensus is violated, it will be disconnected from the network until the Guardians resolve the issue
- Smart contract level data - via processes like the Governor, Guardians constantly monitor the circulating supply and token movements across all supported blockchains
- Guardian level activity - the Guardian Network functions as an autonomous decentralized computing network, ensuring independent security measures across its validators
## Asset Layer Protections
One key strength of the Wormhole ecosystem is the Guardians’ ability to validate and protect the integrity of assets across multiple blockchains.
To enforce the Wormhole Asset Layer’s core protections, the Global Accountant tracks the total circulating supply of all Wormhole assets across all chains, preventing any blockchain from bridging assets that could violate the supply invariant.
In addition to the Global Accountant, Guardians may only sign transfers that do not violate the requirements of the Governor. The [Governor](https://github.com/wormhole-foundation/wormhole/blob/main/whitepapers/0007_governor.md){target=\_blank} tracks inflows and outflows of all blockchains and delays suspicious transfers that may indicate an exploit.
## Open Source
Wormhole builds in the open and is always open source.
- **[Wormhole core repository](https://github.com/wormhole-foundation/wormhole){target=\_blank}**
- **[Wormhole Foundation GitHub organization](https://github.com/wormhole-foundation){target=\_blank}**
- **[Wormhole contract deployments](/docs/learn/infrastructure/core-contracts/){target=\_blank}**
## Audits
Wormhole has been heavily audited, with _29 third-party audits completed_ and more started. Audits have been performed by the following firms:
- [Trail of Bits](https://www.trailofbits.com/){target=\_blank}
- [Neodyme](https://neodyme.io/en/){target=\_blank}
- [Kudelski](https://kudelskisecurity.com/){target=\_blank}
- [OtterSec](https://osec.io/){target=\_blank}
- [Certik](https://www.certik.com/){target=\_blank}
- [Hacken](https://hacken.io/){target=\_blank}
- [Zellic](https://www.zellic.io/){target=\_blank}
- [Coinspect](https://www.coinspect.com/){target=\_blank}
- [Halborn](https://www.halborn.com/){target=\_blank}
- [Cantina](https://cantina.xyz/welcome){target=\_blank}
All audits and final reports can be found in [security page of the GitHub Repo](https://github.com/wormhole-foundation/wormhole/blob/main/SECURITY.md#3rd-party-security-audits){target=\blank}.
## Bug Bounties
Wormhole has one of the largest bug bounty programs in software development and has repeatedly shown commitment to engaging with the white hat community.
Wormhole runs a bug bounty program through [Immunefi](https://immunefi.com/bug-bounty/wormhole/){target=\blank} program, with a top payout of **5 million dollars**.
If you are interested in contributing to Wormhole security, please look at this section for [Getting Started as a White Hat](https://github.com/wormhole-foundation/wormhole/blob/main/SECURITY.md#white-hat-hacking){target=\blank}, and follow the [Wormhole Contributor Guidelines](https://github.com/wormhole-foundation/wormhole/blob/main/CONTRIBUTING.md){target=\blank}.
For more information about submitting to the bug bounty programs, refer to the [Wormhole Immunefi page](https://immunefi.com/bug-bounty/wormhole/){target=\blank}.
## Learn More
The [SECURITY.md](https://github.com/wormhole-foundation/wormhole/blob/main/SECURITY.md){target=\blank} from the official repository has the latest security policies and updates.
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/build/core-messaging/core-contracts/
--- BEGIN CONTENT ---
---
title: Get Started with Core Contracts
description: This guide walks through the key methods of the Core Contracts, providing you with the knowledge needed to integrate them into your cross-chain contracts
categories: Basics
---
# Get Started with Core Contracts
## Introduction
Wormhole's Core Contracts, deployed on each supported blockchain network, enable the fundamental operations of sending and receiving cross-chain messages.
While the implementation details of the Core Contracts varies by network, the core functionality remains consistent across chains. Each version of the Core Contract facilitates secure and reliable cross-chain communication, ensuring that developers can effectively publish and verify messages.
This guide will walk you through the variations and key methods of the Core Contracts, providing you with the knowledge needed to integrate them into your cross-chain contracts. To learn more about Core Contracts' features and how it works, please refer to the [Core Contracts](/docs/learn/infrastructure/core-contracts/){target=\_blank} page in the Learn section.
## Prerequisites
To interact with the Wormhole Core Contract, you'll need the following:
- The [address of the Core Contract](/docs/build/reference/contract-addresses/#core-contracts){target=\_blank} on the chains you're deploying your contract on
- The [Wormhole chain ID](/docs/build/reference/chain-ids/){target=\_blank} of the chains you're deploying your contract on
- The [Wormhole Finality](/docs/build/reference/consistency-levels/){target=\_blank} (consistency) levels (required finality) for the chains you're deploying your contract on
## How to Interact with Core Contracts
Before writing your own contracts, it's essential to understand the key functions and events of the Wormhole Core Contracts. The primary functionality revolves around:
- **Sending messages** - submitting messages to the Wormhole network for cross-chain communication
- **Receiving and verifying messages** - validating messages received from other chains via the Wormhole network
While the implementation details of the Core Contracts vary by network, the core functionality remains consistent across chains.
### Sending Messages
To send a message, regardless of the environment or chain, the Core Contract is invoked with a message argument from an [emitter](/docs/learn/glossary/#emitter){target=\_blank}. This emitter might be your contract or an existing application such as the [Token Bridge](/docs/learn/transfers/token-bridge/#token-bridge){target=\_blank}.
=== "EVM"
The `IWormhole.sol` interface provides the `publishMessage` function, which can be used to publish a message directly to the Core Contract:
```solidity
function publishMessage(
uint32 nonce,
bytes memory payload,
uint8 consistencyLevel
) external payable returns (uint64 sequence);
```
??? interface "Parameters"
`nonce` ++"uint32"++
A free integer field that can be used however you like. Note that changing the `nonce` will result in a different digest.
---
`payload` ++"bytes memory"++
The content of the emitted message. Due to the constraints of individual blockchains, it may be capped to a certain maximum length.
---
`consistencyLevel` ++"uint8"++
A value that defines the required level of finality that must be reached before the Guardians will observe and attest to emitted events.
??? interface "Returns"
`sequence` ++"uint64"++
A unique number that increments for every message for a given emitter (and implicitly chain). This, combined with the emitter address and emitter chain ID, allows the VAA for this message to be queried from the [Wormholescan API](https://docs.wormholescan.io/){target=\_blank}.
??? interface "Example"
```solidity
IWormhole wormhole = IWormhole(wormholeAddr);
// Get the fee for publishing a message
uint256 wormholeFee = wormhole.messageFee();
// Check fee and send parameters
// Create the HelloWorldMessage struct
HelloWorldMessage memory parsedMessage = HelloWorldMessage({
payloadID: uint8(1),
message: helloWorldMessage
});
// Encode the HelloWorldMessage struct into bytes
bytes memory encodedMessage = encodeMessage(parsedMessage);
// Send the HelloWorld message by calling publishMessage on the
// wormhole core contract and paying the Wormhole protocol fee.
messageSequence = wormhole.publishMessage{value: wormholeFee}(
0, // batchID
encodedMessage,
wormholeFinality()
);
```
View the complete Hello World example in the [Wormhole Scaffolding](https://github.com/wormhole-foundation/wormhole-scaffolding/tree/main/evm/src/01_hello_world){target=\_blank} repository on GitHub.
=== "Solana"
The `wormhole_anchor_sdk::wormhole` module and the Wormhole program account can be used to pass a message directly to the Core Contract via the `wormhole::post_message` function:
```rs
pub fn post_message<'info>(
ctx: CpiContext<'_, '_, '_, 'info, PostMessage<'info>>,
batch_id: u32,
payload: Vec,
finality: Finality
) -> Result<()>
```
??? interface "Parameters"
`ctx` ++"CpiContext<'_, '_, '_, 'info, PostMessage<'info>>"++
Provides the necessary context for executing the function, including the accounts and program information required for the Cross-Program Invocation (CPI).
??? child "Type `pub struct CpiContext<'a, 'b, 'c, 'info, T>`"
```rs
pub struct CpiContext<'a, 'b, 'c, 'info, T>
where
T: ToAccountMetas + ToAccountInfos<'info>,
{
pub accounts: T,
pub remaining_accounts: Vec>,
pub program: AccountInfo<'info>,
pub signer_seeds: &'a [&'b [&'c [u8]]],
}
```
For more information, please refer to the [`wormhole_anchor_sdk` Rust docs](https://docs.rs/anchor-lang/0.29.0/anchor_lang/context/struct.CpiContext.html){target=\_blank}.
??? child "Type `PostMessage<'info>`"
```rs
pub struct PostMessage<'info> {
pub config: AccountInfo<'info>,
pub message: AccountInfo<'info>,
pub emitter: AccountInfo<'info>,
pub sequence: AccountInfo<'info>,
pub payer: AccountInfo<'info>,
pub fee_collector: AccountInfo<'info>,
pub clock: AccountInfo<'info>,
pub rent: AccountInfo<'info>,
pub system_program: AccountInfo<'info>,
}
```
For more information, please refer to the [`wormhole_anchor_sdk` Rust docs](https://docs.rs/wormhole-anchor-sdk/latest/wormhole_anchor_sdk/wormhole/instructions/struct.PostMessage.html){target=\_blank}.
---
`batch_id` ++"u32"++
An identifier for the message batch.
---
`payload` ++"Vec"++
The data being sent in the message. This is a variable-length byte array that contains the actual content or information being transmitted. To learn about the different types of payloads, check out the [VAAs](/docs/learn/infrastructure/vaas#payload-types){target=\_blank} page.
---
`finality` ++"Finality"++
Specifies the level of finality or confirmation required for the message.
??? child "Type `Finality`"
```rs
pub enum Finality {
Confirmed,
Finalized,
}
```
??? interface "Returns"
++"Result<()>"++
The result of the function’s execution. If the function completes successfully, it returns `Ok(())`, otherwise it returns `Err(E)`, indicating that an error occurred along with the details about the error
??? interface "Example"
```rust
let fee = ctx.accounts.wormhole_bridge.fee();
// ... Check fee and send parameters
let config = &ctx.accounts.config
let payload: Vec = HelloWorldMessage::Hello { message }.try_to_vec()?;
// Invoke `wormhole::post_message`.
wormhole::post_message(
CpiContext::new_with_signer(
ctx.accounts.wormhole_program.to_account_info(),
wormhole::PostMessage {
// ... Set fields
},
&[
// ... Set seeds
],
),
config.batch_id,
payload,
config.finality.into(),
)?;
```
View the complete Hello World example in the [Wormhole Scaffolding](https://github.com/wormhole-foundation/wormhole-scaffolding/tree/main/solana/programs/01_hello_world){target=\_blank} repository on GitHub.
Once the message is emitted from the Core Contract, the [Guardian Network](/docs/learn/infrastructure/guardians/){target=\_blank} will observe the message and sign the digest of an Attestation [VAA](/docs/learn/infrastructure/vaas/){target=\_blank}. On EVM chains, the body of the VAA is hashed twice with keccak256 to produce the signed digest message. On Solana, the [Solana secp256k1 program](https://docs.solana.com/developing/runtime-facilities/programs#secp256k1-program){target=\_blank} will hash the message passed. In this case, the argument for the message should be a single hash of the body, not the twice-hashed body.
VAAs are [multicast](/docs/learn/infrastructure/core-contracts/#multicast){target=\_blank} by default. This means there is no default target chain for a given message. The application developer decides on the format of the message and its treatment upon receipt.
### Receiving Messages
The way a message is received and handled depends on the environment.
=== "EVM"
On EVM chains, the message passed is the raw VAA encoded as binary. The `IWormhole.sol` interface provides the `parseAndVerifyVM` function, which can be used to parse and verify the received message.
```solidity
function parseAndVerifyVM(
bytes calldata encodedVM
) external view returns (VM memory vm, bool valid, string memory reason);
```
??? interface "Parameters"
`encodedVM` ++"bytes calldata"++
The encoded message as a Verified Action Approval (VAA), which contains all necessary information for verification and processing.
??? interface "Returns"
`vm` ++"VM memory"++
The valid parsed VAA, which will include the original `emitterAddress`, `sequenceNumber`, and `consistencyLevel`, among other fields outlined on the [VAAs](/docs/learn/infrastructure/vaas/) page.
??? child "Struct `VM`"
```solidity
struct VM {
uint8 version;
uint32 timestamp;
uint32 nonce;
uint16 emitterChainId;
bytes32 emitterAddress;
uint64 sequence;
uint8 consistencyLevel;
bytes payload;
uint32 guardianSetIndex;
Signature[] signatures;
bytes32 hash;
}
```
For more information, refer to the [`IWormhole.sol` interface](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/interfaces/IWormhole.sol){target=\_blank}.
---
`valid` ++"bool"++
A boolean indicating whether the VAA is valid or not.
---
`reason` ++"string"++
If the VAA is not valid, a reason will be provided
??? interface "Example"
```solidity
function receiveMessage(bytes memory encodedMessage) public {
// Call the Wormhole core contract to parse and verify the encodedMessage
(
IWormhole.VM memory wormholeMessage,
bool valid,
string memory reason
) = wormhole().parseAndVerifyVM(encodedMessage);
// Perform safety checks here
// Decode the message payload into the HelloWorldMessage struct
HelloWorldMessage memory parsedMessage = decodeMessage(
wormholeMessage.payload
);
// Your custom application logic here
}
```
View the complete Hello World example in the [Wormhole Scaffolding](https://github.com/wormhole-foundation/wormhole-scaffolding/tree/main/evm/src/01_hello_world){target=\_blank} repository on GitHub.
=== "Solana"
On Solana, the VAA is first posted and verified by the Core Contract, after which it can be read by the receiving contract and action taken.
Retrieve the raw message data:
```rs
let posted_message = &ctx.accounts.posted;
posted_message.data()
```
??? interface "Example"
```rust
pub fn receive_message(ctx: Context, vaa_hash: [u8; 32]) -> Result<()> {
let posted_message = &ctx.accounts.posted
if let HelloWorldMessage::Hello { message } = posted_message.data() {
// Check message
// Your custom application logic here
Ok(())
} else {
Err(HelloWorldError::InvalidMessage.into())
}
}
```
View the complete Hello World example in the [Wormhole Scaffolding](https://github.com/wormhole-foundation/wormhole-scaffolding/tree/main/solana/programs/01_hello_world){target=\_blank} repository on GitHub.
#### Validating the Emitter
When processing cross-chain messages, it's critical to ensure that the message originates from a trusted sender (emitter). This can be done by verifying the emitter address and chain ID in the parsed VAA.
Typically, contracts should provide a method to register trusted emitters and check incoming messages against this list before processing them. For example, the following check ensures that the emitter is registered and authorized:
```solidity
require(isRegisteredSender(emitterChainId, emitterAddress), "Invalid emitter");
```
This check can be applied after the VAA is parsed, ensuring only authorized senders can interact with the receiving contract. Trusted emitters can be registered using a method like `setRegisteredSender` during contract deployment or initialization.
```typescript
const tx = await receiverContract.setRegisteredSender(
sourceChain.chainId,
ethers.zeroPadValue(senderAddress as BytesLike, 32)
);
await tx.wait();
```
#### Additional Checks
In addition to environment-specific checks that should be performed, a contract should take care to check other [fields in the body](/docs/learn/infrastructure/vaas/){target=\_blank}, including:
- **Sequence** - is this the expected sequence number? How should out-of-order deliveries be handled?
- **Consistency level** - for the chain this message came from, is the [Wormhole Finality](/docs/build/reference/consistency-levels/){target=\_blank} level enough to guarantee the transaction won't be reverted after taking some action?
The VAA digest is separate from the VAA body but is also relevant. It can be used for replay protection by checking if the digest has already been seen. Since the payload itself is application-specific, there may be other elements to check to ensure safety.
## Source Code References
For a deeper understanding of the Core Contract implementation for a specific blockchain environment and to review the actual source code, please refer to the following links:
- [Algorand Core Contract source code](https://github.com/wormhole-foundation/wormhole/blob/main/algorand/wormhole_core.py){target=\_blank}
- [Aptos Core Contract source code](https://github.com/wormhole-foundation/wormhole/tree/main/aptos/wormhole){target=\_blank}
- [EVM Core Contract source code](https://github.com/wormhole-foundation/wormhole/tree/main/ethereum/contracts){target=\_blank} ([`IWormhole.sol` interface](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/interfaces/IWormhole.sol){target=\_blank})
- [NEAR Core Contract source code](https://github.com/wormhole-foundation/wormhole/tree/main/near/contracts/wormhole){target=\_blank}
- [Solana Core Contract source code](https://github.com/wormhole-foundation/wormhole/tree/main/solana/bridge/program){target=\_blank}
- [Sui Core Contract source code](https://github.com/wormhole-foundation/wormhole/tree/main/sui/wormhole){target=\_blank}
- [Terra Core Contract source code](https://github.com/wormhole-foundation/wormhole/tree/main/terra/contracts/wormhole){target=\_blank}
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/build/core-messaging/wormhole-relayers/
--- BEGIN CONTENT ---
---
title: Wormhole-Deployed Relayers
description: Learn about the Wormhole-deployed relayer configuration for seamless cross-chain messaging between contracts on different EVM blockchains without off-chain deployments.
categories: Relayers, Basics
---
# Wormhole Relayer
## Introduction
The Wormhole-deployed relayers provide a mechanism for contracts on one blockchain to send messages to contracts on another without requiring off-chain infrastructure. Through the Wormhole relayer module, developers can use an untrusted delivery provider to transport VAAs, saving the need to build and maintain custom relaying solutions. The option to [run a custom relayer](/docs/infrastructure/relayers/run-relayer/) is available for more complex needs.
This section covers the components and interfaces involved in using the Wormhole relayer module, such as message sending and receiving, delivery guarantees, and considerations for building reliable and efficient cross-chain applications. Additionally, you'll find details on how to handle specific implementation scenarios and track message delivery progress using the Wormhole CLI tool.
## Get Started with the Wormhole Relayer
Before getting started, it's important to note that the Wormhole-deployed relayer configuration is currently **limited to EVM environments**. The complete list of EVM environment blockchains is on the [Supported Networks](/docs/build/start-building/supported-networks/) page.
To interact with the Wormhole relayer, you'll need to create contracts on the source and target chains to handle the sending and receiving of messages. No off-chain logic needs to be implemented to take advantage of Wormhole-powered relaying.

The components outlined in blue must be implemented.
### Wormhole Relayer Interfaces
There are three relevant interfaces to discuss when utilizing the Wormhole relayer module:
- [**`IWormholeRelayer`**](https://github.com/wormhole-foundation/wormhole/blob/main/relayer/ethereum/contracts/interfaces/relayer/IWormholeRelayer.sol){target=\_blank} - the primary interface by which you send and receive messages. It allows you to request the sending of messages and VAAs
- [**`IWormholeReceiver`**](https://github.com/wormhole-foundation/wormhole/blob/main/relayer/ethereum/contracts/interfaces/relayer/IWormholeReceiver.sol){target=\_blank} - this is the interface you are responsible for implementing. It allows the selected delivery provider to deliver messages/VAAs to your contract
- [**`IDeliveryProvider`**](https://github.com/wormhole-foundation/wormhole/blob/main/relayer/ethereum/contracts/interfaces/relayer/IDeliveryProvider.sol){target=\_blank} - this interface represents the delivery pricing information for a given relayer network. Each delivery provider implements this on every blockchain they support delivering from
## Interact with the Wormhole Relayer
To start interacting with the Wormhole relayer in your contracts, you'll need to import the `IWormholeRelayer` interface and set up a reference using the contract address to the Wormhole-deployed relayer on the supported network of your choice.
To easily integrate with the Wormhole relayer interface, you can use the [Wormhole Solidity SDK](https://github.com/wormhole-foundation/wormhole-solidity-sdk){target=\_blank}.
To retrieve the contract address of the Wormhole relayer, refer to the Wormhole relayer section on the [Contract Addresses](/docs/build/reference/contract-addresses/#wormhole-relayer) reference page.
Your initial set up should resemble the following:
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import "wormhole-solidity-sdk/interfaces/IWormholeRelayer.sol";
contract Example {
IWormholeRelayer public wormholeRelayer;
constructor(address _wormholeRelayer) {
wormholeRelayer = IWormholeRelayer(_wormholeRelayer);
}
}
```
The code provided sets up the basic structure for your contract to interact with the Wormhole relayer using the address supplied to the constructor. By leveraging methods from the `IWormholeRelayer` interface, you can implement message sending and receiving functionalities. The following sections will detail the specific methods you need to use for these tasks.
### Send a Message
To send a message to a contract on another EVM chain, you can call the `sendPayloadToEvm` method provided by the `IWormholeRelayer` interface.
```solidity
function sendPayloadToEvm(
// Chain ID in Wormhole format
uint16 targetChain,
// Contract Address on target chain we're sending a message to
address targetAddress,
// The payload, encoded as bytes
bytes memory payload,
// How much value to attach to the delivery transaction
uint256 receiverValue,
// The gas limit to set on the delivery transaction
uint256 gasLimit
) external payable returns (
// Unique, incrementing ID, used to identify a message
uint64 sequence
);
```
!!! tip
To reduce transaction confirmation time, you can lower the consistency level using the [`sendToEvm`](https://github.com/wormhole-foundation/wormhole/blob/v{{repositories.wormhole.version}}/sdk/js/src/relayer/relayer/send.ts#L33){target=\_blank} method.
The `sendPayloadToEvm` method is marked `payable` to receive fee payment for the transaction. The value to attach to the invocation is determined by calling the `quoteEVMDeliveryPrice`, which provides an estimate of the cost of gas on the target chain.
```solidity
function quoteEVMDeliveryPrice(
// Chain ID in Wormhole format
uint16 targetChain,
// How much value to attach to delivery transaction
uint256 receiverValue,
// The gas limit to attach to the delivery transaction
uint256 gasLimit
) external view returns (
// How much value to attach to the send call
uint256 nativePriceQuote,
uint256 targetChainRefundPerGasUnused
);
```
This method should be called before sending a message, and the value returned for `nativePriceQuote` should be attached to the call to send the payload to cover the transaction's cost on the target chain.
In total, sending a message across EVM chains can be as simple as getting a fee quote and sending the message as follows:
```solidity
// Get a quote for the cost of gas for delivery
(cost, ) = wormholeRelayer.quoteEVMDeliveryPrice(
targetChain,
valueToSend,
GAS_LIMIT
);
// Send the message
wormholeRelayer.sendPayloadToEvm{value: cost}(
targetChain,
targetAddress,
abi.encode(payload),
valueToSend,
GAS_LIMIT
);
```
### Receive a Message
To receive a message using a Wormhole relayer, the target contract must implement the [`IWormholeReceiver`](https://github.com/wormhole-foundation/wormhole-relayer-solidity-sdk/blob/main/src/interfaces/IWormholeReceiver.sol){target=\_blank} interface, as shown in the [previous section](#interact-with-the-wormhole-relayer).
```solidity
function receiveWormholeMessages(
bytes memory payload, // Message passed by source contract
bytes[] memory additionalVaas, // Any additional VAAs that are needed (Note: these are unverified)
bytes32 sourceAddress, // The address of the source contract
uint16 sourceChain, // The Wormhole chain ID
bytes32 deliveryHash // A hash of contents, useful for replay protection
) external payable;
```
The logic inside the function body may be whatever business logic is required to take action on the specific payload.
## Delivery Guarantees
The Wormhole relayer protocol is intended to create a service interface whereby mutually distrustful integrators and delivery providers can work together to provide a seamless dApp experience. You don't trust the delivery providers with your data, and the delivery providers don't trust your smart contract. The primary agreement between integrators and delivery providers is that when a delivery is requested, the provider will attempt to deliver the VAA within the provider's stated delivery timeframe.
This creates a marketplace whereby providers can set different price levels and service guarantees. Delivery providers effectively accept the slippage risk premium of delivering your VAAs in exchange for a set fee rate. Thus, the providers agree to deliver your messages even if they do so at a loss.
Delivery providers should set their prices such that they turn a profit on average but not necessarily on every single transfer. Thus, some providers may choose to set higher rates for tighter guarantees or lower rates for less stringent guarantees.
## Delivery Statuses
All deliveries result in one of the following four outcomes before the delivery provider's delivery timeframe. When they occur, these outcomes are emitted as EVM events from the Wormhole relayer contract. The four possible outcomes are:
- (0) Delivery Success
- (1) Receiver Failure
- (2) Forward Request Success
- (3) Forward Request Failure
A receiver failure is a scenario in which the selected provider attempted the delivery but it could not be completely successfully. The three possible causes for a delivery failure are:
- The target contract does not implement the `IWormholeReceiver` interface
- The target contract threw an exception or reverted during the execution of `receiveWormholeMessages`
- The target contract exceeded the specified `gasLimit` while executing `receiveWormholeMessages`
All three of these scenarios can be avoided with correct design by the integrator, and thus, it is up to the integrator to resolve them. Any other scenario that causes a delivery to not be performed should be considered an outage by some component of the system, including potentially the blockchains themselves.
`Forward Request Success` and `Forward Failure` represent when the delivery succeeded and the user requested a forward during the delivery. If the user has enough funds left over as a refund to complete the forward, the forward will be executed, and the status will be `Forward Request Success`. Otherwise, it will be `Forward Request Failure`.
## Other Considerations
Some implementation details should be considered during development to ensure safety and a pleasant UX. Ensure that your engineering efforts have appropriately considered each of the following areas:
- Receiving a message from a relayer
- Checking for expected emitter
- Calling `parseAndVerify` on any additional VAAs
- Replay protection
- Message ordering (no guarantees on order of messages delivered)
- Forwarding and call chaining
- Refunding overpayment of `gasLimit`
- Refunding overpayment of value sent
## Track the Progress of Messages with the Wormhole CLI
While no off-chain programs are required, a developer may want to track the progress of messages in flight. To track the progress of messages in flight, use the [Wormhole CLI](/docs/build/toolkit/cli/) tool's `status` subcommand. As an example, you can use the following commands to track the status of a transfer by providing the environment, origin network, and transaction hash to the `worm status` command:
=== "Mainnet"
```bash
worm status mainnet ethereum INSERT_TRANSACTION_HASH
```
=== "Testnet"
```bash
worm status testnet ethereum INSERT_TRANSACTION_HASH
```
See the [Wormhole CLI tool docs](/docs/build/toolkit/cli/) for installation and usage.
## Step-by-Step Tutorial
For detailed, step-by-step guidance on creating cross-chain contracts that interact with the Wormhole relayer, refer to the [Create Cross-Chain Contracts](/docs/tutorials/solidity-sdk/cross-chain-contracts/) tutorial.
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/build/start-building/products/
--- BEGIN CONTENT ---
---
title: Compare Wormhole's Cross-Chain Solutions
description: Compare Wormhole’s cross-chain solutions for bridging, native transfers, data queries, and governance to enable seamless blockchain interoperability.
categories: Transfer, Basics
---
# Products
Wormhole provides a comprehensive suite of cross-chain solutions, enabling seamless asset transfers, data retrieval, and governance across blockchain ecosystems.
Wormhole provides multiple options for asset transfers: Connect for a plug-and-play bridging UI, Native Token Transfers (NTT) for moving native assets without wrapped representations, and Token Bridge for a secure lock-and-mint mechanism.
Beyond transfers, Wormhole extends interoperability with tools for cross-chain data access, decentralized governance, and an intent-based protocol through Wormhole Settlement.
## Transfer Products
Wormhole offers different solutions for cross-chain asset transfer, each designed for various use cases and integration requirements.
- [**Connect**](/docs/build/transfers/connect/overview/){target=\_blank} - a pre-built bridging UI for cross-chain token transfers, requiring minimal setup. Best for projects seeking an easy-to-integrate UI for bridging without modifying contracts
- [**Native Token Transfers (NTT)**](/docs/learn/transfers/native-token-transfers/overview/){target=\_blank} - a mechanism to transfer native tokens cross-chain seamlessly without conversion to wrapped asset. Best for projects that require maintaining token fungibility and native chain functionality across multiple networks
- [**Token Bridge**](/docs/learn/transfers/token-bridge/){target=\_blank} - a bridging solution that uses a lock and mint mechanism. Best for projects that need cross-chain liquidity using wrapped assets and the ability to send messages
- [**Settlement**](/docs/learn/messaging/wormhole-settlement/overview/){target=\_blank} - intent-based protocols enabling fast multichain transfers, optimized liquidity flows, and interoperability without relying on traditional bridging methods
Beyond asset transfers, Wormhole provides additional tools for cross-chain data and governance.
## Real-time Data
[**Queries**](/docs/build/queries/overview/){target=\_blank} is a data retrieval service to fetch on-chain data from multiple networks. Best for applications that need multichain analytics, reporting, and data aggregation.
## Multichain Governance
[**MultiGov**](/docs/learn/governance/overview/){target=\_blank} is a unified governance framework that manages multichain protocol governance through a single mechanism. Best for projects managing multichain governance and protocol updates.
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/build/start-building/use-cases/
--- BEGIN CONTENT ---
---
title: Use Cases
description: Explore Wormhole's use cases, from cross-chain swaps to DeFi, lending, gaming, and more. See how projects integrate Wormhole solutions.
categories: Basics
---
# Wormhole Use Cases
## Cross-Chain Swaps and Liquidity Aggregation
Enable seamless swaps between chains with real-time liquidity routing.
## Memecoin Launchpads
Launch and distribute memecoins across multiple chains, enabling cross-chain fundraising and liquidity access.
🛠 **Wormhole products used:**
- [**Native Token Transfer**](/docs/build/transfers/native-token-transfers/){target=\_blank} – enables native asset transfers for seamless fundraising
- [**Messaging**](/docs/learn/infrastructure/){target=\_blank} – facilitates cross-chain token distribution and claim processes
🔗 **Used in:** Token launchpads, IDOs, and meme token ecosystems
## Cross-Chain Perpetuals
Enable leveraged perpetual trading across chains with seamless collateral and liquidity management.
🛠 **Wormhole products used:**
- [**Queries**](/docs/build/queries/overview/){target=\_blank} – fetches real-time asset prices and manages position state across chains
- [**Wormhole Settlement**](/docs/learn/transfers/settlement/overview/){target=\_blank} - for quick cross-chain token execution, providing efficient and seamless user experiences
🔗 **Used in:** Perpetual DEXs, trading platforms and cross-chain derivatives
## Gas Abstraction
Allow users to pay gas fees with any token across different networks, removing friction in multichain interactions.
🛠 **Wormhole products used:**
- [**Messaging**](/docs/learn/infrastructure/){target=\_blank} – routes gas fee payments across chains
- [**Native Token Transfer**](/docs/build/transfers/native-token-transfers/){target=\_blank} – facilitates native token conversion for gas payments
🔗 **Used in:** Wallets, dApps, and multichain user experience improvements
## Bridging Intent Library
Provide developers with a library of bridging intents and automation functions, enabling plug-and-play interoperability logic.
🛠 **Wormhole products used:**
- [**Messaging**](/docs/learn/infrastructure/){target=\_blank} – enables predefined cross-chain actions and triggers.
- [**Wormhole Settlement**](/docs/learn/transfers/settlement/overview/){target=\_blank} - provides a framework for executing user-defined bridging intents
🔗 **Used in:** Bridging protocols, DeFi automation, and smart contract libraries
## Multichain Prediction Markets
Allow users to place bets, manage positions, and receive payouts seamlessly across different networks.
🛠 **Wormhole products used:**
- [**Queries**](/docs/build/queries/overview/){target=\_blank} – fetches real-time market data, tracks collateral, and manages odds across chains
- [**Wormhole Settlement**](/docs/learn/transfers/settlement/overview/){target=\_blank} – automates token execution for efficient and seamless cross-chain prediction market interactions
🔗 **Used in:** Decentralized betting, prediction markets, and cross-chain gaming
## Cross-Chain Payment Widgets
Allow merchants and platforms to accept payments in any token, auto-converting them into a desired asset.
## Oracle Networks
Fetch and verify cross-chain data, enabling reliable, decentralized Oracle services for multichain applications.
🛠 **Wormhole products used:**
- [**Queries**](/docs/build/queries/overview/){target=\_blank} – fetches data from multiple chains and Oracle providers
- [**Messaging**](/docs/learn/infrastructure/){target=\_blank} – ensures tamper-proof data relay across networks
🔗 **Used in:** Price feeds, DeFi protocols, and smart contract automation 🏗️ **Used by:** [Pyth](https://wormhole.com/case-studies/pyth){target=\_blank}
## Cross-Chain Staking
Enable users to stake assets on one chain while earning rewards or securing networks on another.
🛠 **Wormhole products used:**
- [**Messaging**](/docs/learn/infrastructure/){target=\_blank} – moves staking rewards and governance signals across chains
- [**Native Token Transfer**](/docs/build/transfers/native-token-transfers/){target=\_blank} – transfers staked assets natively between networks
🔗 **Used in:** Liquid staking, cross-chain governance, and PoS networks 🏗️ **Used by:** [Lido](https://lido.fi/){target=\_blank}
--- END CONTENT ---
## Reference Concepts [shared: true]
The following section contains reference material for Wormhole.
It includes Wormhole chain IDs, canonical contract addresses, and finality levels for Guardians for each of the supported blockchains in the Wormhole ecosystem.
While it may not be required for all use cases, it offers a deeper technical layer for advanced development work.
---
## List of shared concept pages:
## Full content for shared concepts:
Doc-Content: https://wormhole.com/docs/build/reference/
--- BEGIN CONTENT ---
---
title: Reference
description: Find essential reference information for development, including canonical contract addresses, Wormhole chain IDs, and Wormhole finality levels for Guardians.
categories: Reference
---
# Reference
## Get Started
In this section, you'll find reference information that is essential for development. This includes Wormhole chain IDs, canonical contract addresses, and finality levels for Guardians for each of the supported blockchains in the Wormhole ecosystem.
- :octicons-list-ordered-16:{ .lg .middle } **Chain IDs**
---
Find a mapping of Wormhole chain IDs to the names and network IDs of the supported blockchains.
[:custom-arrow: View list of chain IDs](/docs/build/reference/chain-ids/)
- :material-timer-sand:{ .lg .middle } **Wormhole Finality**
---
See the levels of finality (consistency) a transaction should meet before being signed by a Guardian for each network.
[:custom-arrow: View list of finality levels](/docs/build/reference/consistency-levels/)
- :octicons-file-code-16:{ .lg .middle } **Contract Addresses**
---
Discover the contract addresses for Wormhole-deployed contracts on each of the supported blockchains.
This includes the following protocol contracts:
- Core Contract
- Token Bridge
- NFT Bridge
- Wormhole relayer
- CCTP
[:custom-arrow: View list of contract addresses](/docs/build/reference/contract-addresses/)
- :octicons-checkbox-16:{ .lg .middle } **Wormhole Formatted Addresses**
---
Learn how Wormhole formats addresses into a 32-byte hex format for cross-chain compatibility.
This includes converting addresses between their native formats and the Wormhole format across multiple blockchains.
[:custom-arrow: View details on Wormhole formatted addresses](/docs/build/reference/wormhole-formatted-addresses/)
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/build/reference/chain-ids/
--- BEGIN CONTENT ---
---
title: Chain IDs
description: This page documents the Wormhole-specific chain IDs for each chain and contrasts them to the more commonly referenced EVM chain IDs originating in EIP-155.
categories: Reference
---
# Chain IDs
The following table documents the chain IDs used by Wormhole and places them alongside the more commonly referenced [EVM Chain IDs](https://chainlist.org/){target=\_blank}.
!!! note
Please note, Wormhole chain IDs are different than the more commonly referenced EVM [chain IDs](https://eips.ethereum.org/EIPS/eip-155){target=\_blank}, specified in the Mainnet and Testnet ID columns.
=== "Mainnet"
| Ethereum | 2 | 1 |
| Solana | 1 | Mainnet Beta-5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d |
| Acala | 12 | 787 |
| Algorand | 8 | mainnet-v1.0 |
| Aptos | 22 | 1 |
| Arbitrum | 23 | Arbitrum One-42161 |
| Avalanche | 6 | C-Chain-43114 |
| Base | 30 | Base-8453 |
| Berachain | 39 | |
| Blast | 36 | 81457 |
| BNB Smart Chain | 4 | 56 |
| Celestia | 4004 | celestia |
| Celo | 14 | 42220 |
| Cosmos Hub | 4000 | cosmoshub-4 |
| Dymension | 4007 | dymension_1100-1 |
| Evmos | 4001 | evmos_9001-2 |
| Fantom | 10 | 250 |
| Gnosis | 25 | 100 |
| HyperEVM | 47 | |
| Injective | 19 | injective-1 |
| Ink | 46 | |
| Kaia | 13 | 8217 |
| Karura | 11 | 686 |
| Kujira | 4002 | kaiyo-1 |
| Linea | 38 | 59144 |
| Mantle | 35 | 5000 |
| Mezo | 50 | |
| Monad | 48 | |
| Moonbeam | 16 | 1284 |
| NEAR | 15 | mainnet |
| Neon | 17 | 245022934 |
| Neutron | 4003 | neutron-1 |
| Noble | 4009 | noble-1 |
| Oasis | 7 | 42262 |
| Optimism | 24 | 10 |
| Osmosis | 20 | osmosis-1 |
| Polygon | 5 | 137 |
| Provenance | 4008 | pio-mainnet-1 |
| Pythnet | 26 | |
| Scroll | 34 | 534352 |
| SEDA | 4006 | |
| Sei | 32 | pacific-1 |
| Seievm | 40 | |
| SNAXchain | 43 | 2192 |
| Stargaze | 4005 | stargaze-1 |
| Sui | 21 | 35834a8a |
| Terra | 3 | columbus-5 |
| Terra 2.0 | 18 | phoenix-1 |
| Unichain | 44 | |
| World Chain | 45 | 480 |
| X Layer | 37 | 196 |
| XPLA | 28 | dimension_37-1 |
=== "Testnet"
| Ethereum Holesky | 10006 | Holesky-17000 |
| Ethereum Sepolia | 10002 | Sepolia-11155111 |
| Solana | 1 | Devnet-EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG |
| Acala | 12 | 597 |
| Algorand | 8 | testnet-v1.0 |
| Aptos | 22 | 2 |
| Arbitrum Sepolia | 10003 | Sepolia-421614 |
| Avalanche | 6 | Fuji-43113 |
| Base Sepolia | 10004 | Base Sepolia-84532 |
| Berachain | 39 | 80084 |
| Blast | 36 | 168587773 |
| BNB Smart Chain | 4 | 97 |
| Celestia | 4004 | mocha-4 |
| Celo | 14 | Alfajores-44787 |
| Cosmos Hub | 4000 | theta-testnet-001 |
| Dymension | 4007 | |
| Evmos | 4001 | evmos_9000-4 |
| Fantom | 10 | 4002 |
| Gnosis | 25 | Chiado-10200 |
| HyperEVM | 47 | 998 |
| Injective | 19 | injective-888 |
| Ink | 46 | 763373 |
| Kaia | 13 | Kairos-1001 |
| Karura | 11 | 596 |
| Kujira | 4002 | harpoon-4 |
| Linea | 38 | 59141 |
| Mantle | 35 | Sepolia-5003 |
| Mezo | 50 | 31611 |
| Monad | 48 | 10143 |
| Moonbeam | 16 | Moonbase-Alphanet-1287 |
| NEAR | 15 | testnet |
| Neon | 17 | 245022940 |
| Neutron | 4003 | pion-1 |
| Noble | 4009 | grand-1 |
| Oasis | 7 | 42261 |
| Optimism Sepolia | 10005 | Optimism Sepolia-11155420 |
| Osmosis | 20 | osmo-test-5 |
| Polygon Amoy | 10007 | Amoy-80002 |
| Provenance | 4008 | |
| Pythnet | 26 | |
| Scroll | 34 | Sepolia-534351 |
| SEDA | 4006 | seda-1-testnet |
| Sei | 32 | atlantic-2 |
| Seievm | 40 | |
| SNAXchain | 43 | 13001 |
| Stargaze | 4005 | |
| Sui | 21 | 4c78adac |
| Terra | 3 | bombay-12 |
| Terra 2.0 | 18 | pisco-1 |
| Unichain | 44 | Unichain Sepolia-1301 |
| World Chain | 45 | 4801 |
| X Layer | 37 | 195 |
| XPLA | 28 | cube_47-5 |
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/build/reference/consistency-levels/
--- BEGIN CONTENT ---
---
title: Wormhole Finality | Consistency Levels
description: This page documents how long to wait for finality before signing, based on each chain’s consistency (finality) level and consensus mechanism.
categories: Reference
---
# Wormhole Finality
The following table documents each chain's `consistencyLevel` values (i.e., finality reached before signing). The consistency level defines how long the Guardians should wait before signing a VAA. The finalization time depends on the specific chain's consensus mechanism. The consistency level is a `u8`, so any single byte may be used. However, a small subset has particular meanings. If the `consistencyLevel` isn't one of those specific values, the `Otherwise` column describes how it's interpreted.
| Ethereum | 200 | 201 | | finalized | ~ 19min | Details |
| Solana | | 0 | 1 | | ~ 14s | Details |
| Acala | 200 | 201 | | finalized | ~ 24s | |
| Algorand | | | 0 | | ~ 4s | Details |
| Aptos | | | 0 | | ~ 4s | Details |
| Arbitrum | 200 | 201 | | finalized | ~ 18min | Details |
| Avalanche | 200 | | | finalized | ~ 2s | Details |
| Base | 200 | 201 | | finalized | ~ 18min | |
| Berachain | 200 | | | finalized | ~ 4s | |
| Blast | 200 | 201 | | finalized | ~ 18min | |
| BNB Smart Chain | 200 | 201 | | finalized | ~ 48s | Details |
| Celestia | | | 0 | | ~ 5s | |
| Celo | 200 | | | finalized | ~ 10s | |
| Cosmos Hub | | | 0 | | ~ 5s | |
| Dymension | | | 0 | | ~ 5s | |
| Evmos | | | 0 | | ~ 2s | |
| Fantom | 200 | | | finalized | ~ 5s | |
| Injective | | | 0 | | ~ 3s | |
| Ink | | | 0 | | ~ 9min | |
| Kaia | 200 | | | finalized | ~ 1s | |
| Karura | 200 | 201 | | finalized | ~ 24s | Details |
| Kujira | | | 0 | | ~ 3s | |
| Mantle | 200 | 201 | | finalized | ~ 18min | |
| Mezo | | | 0 | | ~ 8s | |
| Monad | | | 0 | | ~ 2s | |
| Moonbeam | 200 | 201 | | finalized | ~ 24s | Details |
| NEAR | | | 0 | | ~ 2s | Details |
| Neutron | | | 0 | | ~ 5s | |
| Oasis | 200 | | | finalized | ~ 12s | |
| Optimism | 200 | 201 | | finalized | ~ 18min | |
| Osmosis | | | 0 | | ~ 6s | |
| Polygon | 200 | | | finalized | ~ 66s | Details |
| Scroll | 200 | | | finalized | ~ 16min | |
| Sei | | | 0 | | ~ 1s | |
| Stargaze | | | 0 | | ~ 5s | |
| Sui | | | 0 | | ~ 3s | Details |
| Terra | | | 0 | | ~ 6s | |
| Terra 2.0 | | | 0 | | ~ 6s | |
| Unichain | 200 | 201 | | finalized | ~ 18min | |
| World Chain | | | 0 | | ~ 18min | |
| X Layer | 200 | 201 | | finalized | ~ 16min | |
| XPLA | | | 0 | | ~ 5s | |
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/build/reference/contract-addresses/
--- BEGIN CONTENT ---
---
title: Contract Addresses
description: This page documents the deployed contract addresses of the Wormhole contracts on each chain, including Core Contracts, TokenBridge, and more.
categories: Reference
---
# Contract Addresses
## Core Contracts
=== "Mainnet"
| Ethereum | 0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B |
| Solana | worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth |
| Acala | 0xa321448d90d4e5b0A732867c18eA198e75CAC48E |
| Algorand | 842125965 |
| Aptos | 0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625 |
| Arbitrum | 0xa5f208e072434bC67592E4C49C1B991BA79BCA46 |
| Avalanche | 0x54a8e5f9c4CbA08F9943965859F6c34eAF03E26c |
| Base | 0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6 |
| Berachain | 0xCa1D5a146B03f6303baF59e5AD5615ae0b9d146D |
| Blast | 0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6 |
| BNB Smart Chain | 0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B |
| Celo | 0xa321448d90d4e5b0A732867c18eA198e75CAC48E |
| Fantom | 0x126783A6Cb203a3E35344528B26ca3a0489a1485 |
| Gnosis | 0xa321448d90d4e5b0A732867c18eA198e75CAC48E |
| Injective | inj17p9rzwnnfxcjp32un9ug7yhhzgtkhvl9l2q74d |
| Ink | 0xCa1D5a146B03f6303baF59e5AD5615ae0b9d146D |
| Kaia | 0x0C21603c4f3a6387e241c0091A7EA39E43E90bb7 |
| Karura | 0xa321448d90d4e5b0A732867c18eA198e75CAC48E |
| Mantle | 0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6 |
| Moonbeam | 0xC8e2b0cD52Cf01b0Ce87d389Daa3d414d4cE29f3 |
| NEAR | contract.wormhole_crypto.near |
| Neutron | neutron16rerygcpahqcxx5t8vjla46ym8ccn7xz7rtc6ju5ujcd36cmc7zs9zrunh |
| Oasis | 0xfE8cD454b4A1CA468B57D79c0cc77Ef5B6f64585 |
| Optimism | 0xEe91C335eab126dF5fDB3797EA9d6aD93aeC9722 |
| Polygon | 0x7A4B5a56256163F07b2C80A7cA55aBE66c4ec4d7 |
| Pythnet | H3fxXJ86ADW2PNuDDmZJg6mzTtPxkYCpNuQUTgmJ7AjU |
| Scroll | 0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6 |
| Sei | sei1gjrrme22cyha4ht2xapn3f08zzw6z3d4uxx6fyy9zd5dyr3yxgzqqncdqn |
| SNAXchain | 0xc1BA3CC4bFE724A08FbbFbF64F8db196738665f4 |
| Sui | 0xaeab97f96cf9877fee2883315d459552b2b921edc16d7ceac6eab944dd88919c |
| Terra | terra1dq03ugtd40zu9hcgdzrsq6z2z4hwhc9tqk2uy5 |
| Terra 2.0 | terra12mrnzvhx3rpej6843uge2yyfppfyd3u9c3uq223q8sl48huz9juqffcnhp |
| Unichain | 0xCa1D5a146B03f6303baF59e5AD5615ae0b9d146D |
| World Chain | 0xcbcEe4e081464A15d8Ad5f58BB493954421eB506 |
| X Layer | 0x194B123c5E96B9b2E49763619985790Dc241CAC0 |
| XPLA | xpla1jn8qmdda5m6f6fqu9qv46rt7ajhklg40ukpqchkejcvy8x7w26cqxamv3w |
=== "Testnet"
| Ethereum Holesky | 0xa10f2eF61dE1f19f586ab8B6F2EbA89bACE63F7a |
| Ethereum Sepolia | 0x4a8bc80Ed5a4067f1CCf107057b8270E0cC11A78 |
| Solana | 3u8hJUVTA4jH1wYAyUur7FFZVQ8H635K3tSHHF4ssjQ5 |
| Acala | 0x64fb09E405D2043ed7785a29E296C766D56F2056 |
| Algorand | 86525623 |
| Aptos | 0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625 |
| Arbitrum Sepolia | 0x6b9C8671cdDC8dEab9c719bB87cBd3e782bA6a35 |
| Avalanche | 0x7bbcE28e64B3F8b84d876Ab298393c38ad7aac4C |
| Base Sepolia | 0x79A1027a6A159502049F10906D333EC57E95F083 |
| Berachain | 0xBB73cB66C26740F31d1FabDC6b7A46a038A300dd |
| Blast | 0x473e002D7add6fB67a4964F13bFd61280Ca46886 |
| BNB Smart Chain | 0x68605AD7b15c732a30b1BbC62BE8F2A509D74b4D |
| Celo | 0x88505117CA88e7dd2eC6EA1E13f0948db2D50D56 |
| Fantom | 0x1BB3B4119b7BA9dfad76B0545fb3F531383c3bB7 |
| Gnosis | 0xBB73cB66C26740F31d1FabDC6b7A46a038A300dd |
| HyperEVM | 0xBB73cB66C26740F31d1FabDC6b7A46a038A300dd |
| Injective | inj1xx3aupmgv3ce537c0yce8zzd3sz567syuyedpg |
| Ink | 0xBB73cB66C26740F31d1FabDC6b7A46a038A300dd |
| Kaia | 0x1830CC6eE66c84D2F177B94D544967c774E624cA |
| Karura | 0x64fb09E405D2043ed7785a29E296C766D56F2056 |
| Linea | 0x79A1027a6A159502049F10906D333EC57E95F083 |
| Mantle | 0x376428e7f26D5867e69201b275553C45B09EE090 |
| Mezo | 0x268557122Ffd64c85750d630b716471118F323c8 |
| Monad | 0xBB73cB66C26740F31d1FabDC6b7A46a038A300dd |
| Moonbeam | 0xa5B7D85a8f27dd7907dc8FdC21FA5657D5E2F901 |
| NEAR | wormhole.wormhole.testnet |
| Neon | 0x268557122Ffd64c85750d630b716471118F323c8 |
| Neutron | neutron1enf63k37nnv9cugggpm06mg70emcnxgj9p64v2s8yx7a2yhhzk2q6xesk4 |
| Oasis | 0xc1C338397ffA53a2Eb12A7038b4eeb34791F8aCb |
| Optimism Sepolia | 0x31377888146f3253211EFEf5c676D41ECe7D58Fe |
| Osmosis | osmo1hggkxr0hpw83f8vuft7ruvmmamsxmwk2hzz6nytdkzyup9krt0dq27sgyx |
| Polygon Amoy | 0x6b9C8671cdDC8dEab9c719bB87cBd3e782bA6a35 |
| Pythnet | EUrRARh92Cdc54xrDn6qzaqjA77NRrCcfbr8kPwoTL4z |
| Scroll | 0x055F47F1250012C6B20c436570a76e52c17Af2D5 |
| Sei | sei1nna9mzp274djrgzhzkac2gvm3j27l402s4xzr08chq57pjsupqnqaj0d5s |
| Seievm | 0xBB73cB66C26740F31d1FabDC6b7A46a038A300dd |
| SNAXchain | 0xBB73cB66C26740F31d1FabDC6b7A46a038A300dd |
| Sui | 0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790 |
| Terra | terra1pd65m0q9tl3v8znnz5f5ltsfegyzah7g42cx5v |
| Terra 2.0 | terra19nv3xr5lrmmr7egvrk2kqgw4kcn43xrtd5g0mpgwwvhetusk4k7s66jyv0 |
| Unichain | 0xBB73cB66C26740F31d1FabDC6b7A46a038A300dd |
| World Chain | 0xe5E02cD12B6FcA153b0d7fF4bF55730AE7B3C93A |
| X Layer | 0xA31aa3FDb7aF7Db93d18DDA4e19F811342EDF780 |
| XPLA | xpla1upkjn4mthr0047kahvn0llqx4qpqfn75lnph4jpxfn8walmm8mqsanyy35 |
=== "Devnet"
| Ethereum | 0xC89Ce4735882C9F0f0FE26686c53074E09B0D550 |
| Solana | Bridge1p5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o |
| Algorand | 1004 |
| Aptos | 0xde0036a9600559e295d5f6802ef6f3f802f510366e0c23912b0655d972166017 |
| BNB Smart Chain | 0xC89Ce4735882C9F0f0FE26686c53074E09B0D550 |
| NEAR | wormhole.test.near |
| Sui | 0x5a5160ca3c2037f4b4051344096ef7a48ebf4400b3f385e57ea90e1628a8bde0 |
| Terra | terra14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9ssrc8au |
| Terra 2.0 | terra14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9ssrc8au |
## Token Bridge
=== "Mainnet"
| Ethereum | 0x3ee18B2214AFF97000D974cf647E7C347E8fa585 |
| Solana | wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb |
| Acala | 0xae9d7fe007b3327AA64A32824Aaac52C42a6E624 |
| Algorand | 842126029 |
| Aptos | 0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f |
| Arbitrum | 0x0b2402144Bb366A632D14B83F244D2e0e21bD39c |
| Avalanche | 0x0e082F06FF657D94310cB8cE8B0D9a04541d8052 |
| Base | 0x8d2de8d2f73F1F4cAB472AC9A881C9b123C79627 |
| Berachain | 0x3Ff72741fd67D6AD0668d93B41a09248F4700560 |
| Blast | 0x24850c6f61C438823F01B7A3BF2B89B72174Fa9d |
| BNB Smart Chain | 0xB6F6D86a8f9879A9c87f643768d9efc38c1Da6E7 |
| Celo | 0x796Dff6D74F3E27060B71255Fe517BFb23C93eed |
| Fantom | 0x7C9Fc5741288cDFdD83CeB07f3ea7e22618D79D2 |
| Injective | inj1ghd753shjuwexxywmgs4xz7x2q732vcnxxynfn |
| Ink | 0x3Ff72741fd67D6AD0668d93B41a09248F4700560 |
| Kaia | 0x5b08ac39EAED75c0439FC750d9FE7E1F9dD0193F |
| Karura | 0xae9d7fe007b3327AA64A32824Aaac52C42a6E624 |
| Mantle | 0x24850c6f61C438823F01B7A3BF2B89B72174Fa9d |
| Moonbeam | 0xb1731c586ca89a23809861c6103f0b96b3f57d92 |
| NEAR | contract.portalbridge.near |
| Oasis | 0x5848C791e09901b40A9Ef749f2a6735b418d7564 |
| Optimism | 0x1D68124e65faFC907325e3EDbF8c4d84499DAa8b |
| Polygon | 0x5a58505a96D1dbf8dF91cB21B54419FC36e93fdE |
| Scroll | 0x24850c6f61C438823F01B7A3BF2B89B72174Fa9d |
| Sei | sei1smzlm9t79kur392nu9egl8p8je9j92q4gzguewj56a05kyxxra0qy0nuf3 |
| SNAXchain | 0x8B94bfE456B48a6025b92E11Be393BAa86e68410 |
| Sui | 0xc57508ee0d4595e5a8728974a4a93a787d38f339757230d441e895422c07aba9 |
| Terra | terra10nmmwe8r3g99a9newtqa7a75xfgs2e8z87r2sf |
| Terra 2.0 | terra153366q50k7t8nn7gec00hg66crnhkdggpgdtaxltaq6xrutkkz3s992fw9 |
| Unichain | 0x3Ff72741fd67D6AD0668d93B41a09248F4700560 |
| World Chain | 0xc309275443519adca74c9136b02A38eF96E3a1f6 |
| X Layer | 0x5537857664B0f9eFe38C9f320F75fEf23234D904 |
| XPLA | xpla137w0wfch2dfmz7jl2ap8pcmswasj8kg06ay4dtjzw7tzkn77ufxqfw7acv |
=== "Testnet"
| Ethereum Holesky | 0x76d093BbaE4529a342080546cAFEec4AcbA59EC6 |
| Ethereum Sepolia | 0xDB5492265f6038831E89f495670FF909aDe94bd9 |
| Solana | DZnkkTmCiFWfYTfT41X3Rd1kDgozqzxWaHqsw6W4x2oe |
| Acala | 0xe157115ef34c93145Fec2FE53706846853B07F42 |
| Algorand | 86525641 |
| Aptos | 0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f |
| Arbitrum Sepolia | 0xC7A204bDBFe983FCD8d8E61D02b475D4073fF97e |
| Avalanche | 0x61E44E506Ca5659E6c0bba9b678586fA2d729756 |
| Base Sepolia | 0x86F55A04690fd7815A3D802bD587e83eA888B239 |
| Berachain | 0xa10f2eF61dE1f19f586ab8B6F2EbA89bACE63F7a |
| Blast | 0x430855B4D43b8AEB9D2B9869B74d58dda79C0dB2 |
| BNB Smart Chain | 0x9dcF9D205C9De35334D646BeE44b2D2859712A09 |
| Celo | 0x05ca6037eC51F8b712eD2E6Fa72219FEaE74E153 |
| Fantom | 0x599CEa2204B4FaECd584Ab1F2b6aCA137a0afbE8 |
| HyperEVM | 0x4a8bc80Ed5a4067f1CCf107057b8270E0cC11A78 |
| Injective | inj1q0e70vhrv063eah90mu97sazhywmeegp7myvnh |
| Ink | 0x376428e7f26D5867e69201b275553C45B09EE090 |
| Kaia | 0xC7A13BE098720840dEa132D860fDfa030884b09A |
| Karura | 0xe157115ef34c93145Fec2FE53706846853B07F42 |
| Linea | 0xC7A204bDBFe983FCD8d8E61D02b475D4073fF97e |
| Mantle | 0x75Bfa155a9D7A3714b0861c8a8aF0C4633c45b5D |
| Mezo | 0xA31aa3FDb7aF7Db93d18DDA4e19F811342EDF780 |
| Monad | 0xF323dcDe4d33efe83cf455F78F9F6cc656e6B659 |
| Moonbeam | 0xbc976D4b9D57E57c3cA52e1Fd136C45FF7955A96 |
| NEAR | token.wormhole.testnet |
| Neon | 0xEe3dB83916Ccdc3593b734F7F2d16D630F39F1D0 |
| Oasis | 0x88d8004A9BdbfD9D28090A02010C19897a29605c |
| Optimism Sepolia | 0x99737Ec4B815d816c49A385943baf0380e75c0Ac |
| Polygon Amoy | 0xC7A204bDBFe983FCD8d8E61D02b475D4073fF97e |
| Scroll | 0x22427d90B7dA3fA4642F7025A854c7254E4e45BF |
| Sei | sei1jv5xw094mclanxt5emammy875qelf3v62u4tl4lp5nhte3w3s9ts9w9az2 |
| Seievm | 0x23908A62110e21C04F3A4e011d24F901F911744A |
| SNAXchain | 0xa10f2eF61dE1f19f586ab8B6F2EbA89bACE63F7a |
| Sui | 0x6fb10cdb7aa299e9a4308752dadecb049ff55a892de92992a1edbd7912b3d6da |
| Terra | terra1pseddrv0yfsn76u4zxrjmtf45kdlmalswdv39a |
| Terra 2.0 | terra1c02vds4uhgtrmcw7ldlg75zumdqxr8hwf7npseuf2h58jzhpgjxsgmwkvk |
| Unichain | 0xa10f2eF61dE1f19f586ab8B6F2EbA89bACE63F7a |
| World Chain | 0x430855B4D43b8AEB9D2B9869B74d58dda79C0dB2 |
| X Layer | 0xdA91a06299BBF302091B053c6B9EF86Eff0f930D |
| XPLA | xpla1kek6zgdaxcsu35nqfsyvs2t9vs87dqkkq6hjdgczacysjn67vt8sern93x |
=== "Devnet"
| Ethereum | 0x0290FB167208Af455bB137780163b7B7a9a10C16 |
| Solana | B6RHG3mfcckmrYN1UhmJzyS1XX3fZKbkeUcpJe9Sy3FE |
| Algorand | 1006 |
| Aptos | 0x84a5f374d29fc77e370014dce4fd6a55b58ad608de8074b0be5571701724da31 |
| BNB Smart Chain | 0x0290FB167208Af455bB137780163b7B7a9a10C16 |
| NEAR | token.test.near |
| Sui | 0xa6a3da85bbe05da5bfd953708d56f1a3a023e7fb58e5a824a3d4de3791e8f690 |
| Terra | terra1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrquka9l6 |
| Terra 2.0 | terra1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrquka9l6 |
## Wormhole Relayer
=== "Mainnet"
| Ethereum | 0x27428DD2d3DD32A4D7f7C497eAaa23130d894911 |
| Arbitrum | 0x27428DD2d3DD32A4D7f7C497eAaa23130d894911 |
| Avalanche | 0x27428DD2d3DD32A4D7f7C497eAaa23130d894911 |
| Base | 0x706f82e9bb5b0813501714ab5974216704980e31 |
| Berachain | 0x27428DD2d3DD32A4D7f7C497eAaa23130d894911 |
| Blast | 0x27428DD2d3DD32A4D7f7C497eAaa23130d894911 |
| BNB Smart Chain | 0x27428DD2d3DD32A4D7f7C497eAaa23130d894911 |
| Celo | 0x27428DD2d3DD32A4D7f7C497eAaa23130d894911 |
| Fantom | 0x27428DD2d3DD32A4D7f7C497eAaa23130d894911 |
| Ink | 0x27428DD2d3DD32A4D7f7C497eAaa23130d894911 |
| Kaia | 0x27428DD2d3DD32A4D7f7C497eAaa23130d894911 |
| Mantle | 0x27428DD2d3DD32A4D7f7C497eAaa23130d894911 |
| Moonbeam | 0x27428DD2d3DD32A4D7f7C497eAaa23130d894911 |
| Optimism | 0x27428DD2d3DD32A4D7f7C497eAaa23130d894911 |
| Polygon | 0x27428DD2d3DD32A4D7f7C497eAaa23130d894911 |
| Scroll | 0x27428DD2d3DD32A4D7f7C497eAaa23130d894911 |
| SNAXchain | 0x27428DD2d3DD32A4D7f7C497eAaa23130d894911 |
| Unichain | 0x27428DD2d3DD32A4D7f7C497eAaa23130d894911 |
| World Chain | 0x1520cc9e779c56dab5866bebfb885c86840c33d3 |
| X Layer | 0x27428DD2d3DD32A4D7f7C497eAaa23130d894911 |
=== "Testnet"
| Ethereum Sepolia | 0x7B1bD7a6b4E61c2a123AC6BC2cbfC614437D0470 |
| Arbitrum Sepolia | 0x7B1bD7a6b4E61c2a123AC6BC2cbfC614437D0470 |
| Avalanche | 0xA3cF45939bD6260bcFe3D66bc73d60f19e49a8BB |
| Base Sepolia | 0x93BAD53DDfB6132b0aC8E37f6029163E63372cEE |
| Berachain | 0x362fca37E45fe1096b42021b543f462D49a5C8df |
| BNB Smart Chain | 0x80aC94316391752A193C1c47E27D382b507c93F3 |
| Celo | 0x306B68267Deb7c5DfCDa3619E22E9Ca39C374f84 |
| Fantom | 0x7B1bD7a6b4E61c2a123AC6BC2cbfC614437D0470 |
| Ink | 0x362fca37E45fe1096b42021b543f462D49a5C8df |
| Monad | 0x362fca37E45fe1096b42021b543f462D49a5C8df |
| Moonbeam | 0x0591C25ebd0580E0d4F27A82Fc2e24E7489CB5e0 |
| Optimism Sepolia | 0x93BAD53DDfB6132b0aC8E37f6029163E63372cEE |
| Seievm | 0x362fca37E45fe1096b42021b543f462D49a5C8df |
| Unichain | 0x362fca37E45fe1096b42021b543f462D49a5C8df |
=== "Devnet"
| Ethereum | 0xcC680D088586c09c3E0E099a676FA4b6e42467b4 |
| BNB Smart Chain | 0xcC680D088586c09c3E0E099a676FA4b6e42467b4 |
## CCTP
=== "Mainnet"
| Ethereum | 0xAaDA05BD399372f0b0463744C09113c137636f6a |
| Arbitrum | 0x2703483B1a5a7c577e8680de9Df8Be03c6f30e3c |
| Avalanche | 0x09Fb06A271faFf70A651047395AaEb6265265F13 |
| Base | 0x03faBB06Fa052557143dC28eFCFc63FC12843f1D |
| Optimism | 0x2703483B1a5a7c577e8680de9Df8Be03c6f30e3c |
| Polygon | 0x0FF28217dCc90372345954563486528aa865cDd6 |
=== "Testnet"
| Ethereum Sepolia | 0x2703483B1a5a7c577e8680de9Df8Be03c6f30e3c |
| Arbitrum Sepolia | 0x2703483B1a5a7c577e8680de9Df8Be03c6f30e3c |
| Avalanche | 0x58f4c17449c90665891c42e14d34aae7a26a472e |
| Base Sepolia | 0x2703483B1a5a7c577e8680de9Df8Be03c6f30e3c |
| Optimism Sepolia | 0x2703483B1a5a7c577e8680de9Df8Be03c6f30e3c |
=== "Devnet"
N/A
## Read-Only Deployments
=== "Mainnet"
| Corn | 0xa683c66045ad16abb1bCE5ad46A64d95f9A25785 |
| Gnosis | 0xa321448d90d4e5b0A732867c18eA198e75CAC48E |
| Goat | 0x352A86168e6988A1aDF9A15Cb00017AAd3B67155 |
| LightLink | 0x352A86168e6988A1aDF9A15Cb00017AAd3B67155 |
| Rootstock | 0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6 |
| Sonic | 0x352A86168e6988A1aDF9A15Cb00017AAd3B67155 |
| Telos | 0x352A86168e6988A1aDF9A15Cb00017AAd3B67155 |
!!!note
Read-only deployments allow Wormhole messages to be received on chains not fully integrated with Wormhole Guardians. These deployments support cross-chain data verification but cannot originate messages. For example, a governance message can be sent from a fully integrated chain and processed on a read-only chain, but the read-only chain cannot send messages back.
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/build/reference/wormhole-formatted-addresses/
--- BEGIN CONTENT ---
---
title: Wormhole Formatted Addresses
description: Explanation of Wormhole formatted 32-byte hex addresses, their conversion, and usage across different blockchain platforms.
categories: Reference
---
# Wormhole Formatted Addresses
## Introduction
Wormhole formatted addresses are 32-byte hex representations of addresses from any supported blockchain. Whether an address originates from EVM, Solana, Cosmos, or another ecosystem, Wormhole standardizes all addresses into this format to ensure cross-chain compatibility.
This uniform format is essential for smooth interoperability in token transfers and messaging across chains. Wormhole uses formatted addresses throughout the [Wormhole SDK](https://github.com/wormhole-foundation/wormhole-sdk-ts){target=\_blank}, especially in cross-chain transactions, such as transfer functions that utilize the `bytes32` representation for recipient addresses.
## Platform-Specific Address Formats
Each blockchain ecosystem Wormhole supports has its method for formatting native addresses. To enable cross-chain compatibility, Wormhole converts these native addresses into the standardized 32-byte hex format.
Here’s an overview of the native address formats and how they are normalized to the Wormhole format:
| Platform | Native Address Format | Wormhole Formatted Address |
|-----------------|----------------------------------|----------------------------|
| EVM | Hex (e.g., 0x...) | 32-byte Hex |
| Solana | Base58 | 32-byte Hex |
| CosmWasm | Bech32 | 32-byte Hex |
| Algorand | Algorand App ID | 32-byte Hex |
| Sui | Hex | 32-byte Hex |
| Aptos | Hex | 32-byte Hex |
| Near | SHA-256 | 32-byte Hex |
These conversions allow Wormhole to interact seamlessly with various chains using a uniform format for all addresses.
### Address Format Handling
The Wormhole SDK provides mappings that associate each platform with its native address format. You can find this mapping in the Wormhole SDK file [`platforms.ts`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/007f61b27c650c1cf0fada2436f79940dfa4f211/core/base/src/constants/platforms.ts#L93-L102){target=\_blank}:
```typescript
const platformAddressFormatEntries = [
['Evm', 'hex'],
['Solana', 'base58'],
['Cosmwasm', 'bech32'],
['Algorand', 'algorandAppId'],
['Sui', 'hex'],
['Aptos', 'hex'],
['Near', 'sha256'],
];
```
These entries define how the [`UniversalAddress`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/007f61b27c650c1cf0fada2436f79940dfa4f211/core/definitions/src/universalAddress.ts#L23){target=\_blank} class handles different address formats based on the platform.
## Universal Address Methods
The `UniversalAddress` class is essential for working with Wormhole formatted addresses. It converts native blockchain addresses into the standardized 32-byte hex format used across Wormhole operations.
Key functions:
- **`new UniversalAddress()`** - use the `UniversalAddress` constructor to convert native addresses into the Wormhole format
```typescript
const universalAddress = new UniversalAddress('0x123...', 'hex');
```
- **`toUniversalAddress()`** - converts a platform-specific address into the Wormhole formatted 32-byte hex address
```typescript
const ethAddress: NativeAddress<'Evm'> = toNative('Ethereum', '0x0C9...');
const universalAddress = ethAddress.toUniversalAddress().toString();
```
- **`toNative()`** - converts the Wormhole formatted address back to a native address for a specific blockchain platform
```typescript
const nativeAddress = universalAddress.toNative('Evm');
```
- **`toString()`** - returns the Wormhole formatted address as a hex string, which can be used in various SDK operations
```typescript
console.log(universalAddress.toString());
```
These methods allow developers to convert between native addresses and the Wormhole format, ensuring cross-chain compatibility.
## Convert Between Native and Wormhole Formatted Addresses
The Wormhole SDK allows developers to easily convert between native addresses and Wormhole formatted addresses when building cross-chain applications.
### Convert a Native Address to a Wormhole Formatted Address
Example conversions for EVM and Solana:
=== "EVM"
```typescript
import { toNative } from '@wormhole-foundation/sdk-core';
const ethAddress: NativeAddress<'Evm'> = toNative(
'Ethereum',
'0x0C99567DC6f8f1864cafb580797b4B56944EEd28'
);
const universalAddress = ethAddress.toUniversalAddress().toString();
console.log('Universal Address (EVM):', universalAddress);
```
=== "Solana"
```typescript
import { toNative } from '@wormhole-foundation/sdk-core';
const solAddress: NativeAddress<'Solana'> = toNative(
'Solana',
'6zZHv9EiqQYcdg52ueADRY6NbCXa37VKPngEHaokZq5J'
);
const universalAddressSol = solAddress.toUniversalAddress().toString();
console.log('Universal Address (Solana):', universalAddressSol);
```
The result is a standardized address format that is ready for cross-chain operations.
### Convert Back to Native Addresses
Below is how you can convert a Wormhole formatted address back to an EVM or Solana native address:
```typescript
const nativeAddressEvm = universalAddress.toNative('Evm');
console.log('EVM Native Address:', nativeAddressEvm);
const nativeAddressSolana = universalAddress.toNative('Solana');
console.log('Solana Native Address:', nativeAddressSolana);
```
These conversions ensure that your cross-chain applications can seamlessly handle addresses across different ecosystems.
## Use Cases for Wormhole Formatted Addresses
### Cross-chain Token Transfers
Cross-chain token transfers require addresses to be converted into a standard format. For example, when transferring tokens from Ethereum to Solana, the Ethereum address is converted into a Wormhole formatted address to ensure compatibility. After the transfer, the Wormhole formatted address is converted back into the Solana native format.
### Smart Contract Interactions
In smart contract interactions, especially when building dApps that communicate across multiple chains, Wormhole formatted addresses provide a uniform way to reference addresses. This ensures that addresses from different blockchains can interact seamlessly, whether you're sending messages or making cross-chain contract calls.
### DApp Development
For cross-chain dApp development, Wormhole formatted addresses simplify handling user wallet addresses across various blockchains. This allows developers to manage addresses consistently, regardless of whether they work with EVM, Solana, or another supported platform.
### Relayers and Infrastructure
Finally, relayers and infrastructure components, such as Wormhole Guardians, rely on the standardized format to efficiently process and relay cross-chain messages. A uniform address format simplifies operations, ensuring smooth interoperability across multiple blockchains.
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/build/start-building/supported-networks/
--- BEGIN CONTENT ---
---
title: Supported Networks
description: Learn about the compatible environments and individual networks that Wormhole supports. Readers can click on each of the blockchain logos for more information.
categories: Reference
---
# Supported Networks
Wormhole supports several different blockchains and environments. Since many of the concepts for using Wormhole within a given blockchain environment are the same, this section is organized by environment, and individual chains are detailed within the environment page.
## Supported Environments
- [EVM (Ethereum and compatible chains)](#evm)
- [SVM (Solana and compatible chains)](#svm)
- [CosmWasm (Cosmos ecosystem chains)](#cosmwasm)
- [AVM (Algorand)](#avm)
- [NEAR VM (NEAR)](#near-vm)
- [Move VM (Aptos)](#move-vm)
- [Sui Move VM (Sui)](#sui-move-vm)
## Supported Blockchains by Environment
### EVM
| Ethereum | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Acala | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Arbitrum | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Avalanche | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Base | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Berachain | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Blast | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| BNB Smart Chain | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Celo | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Fantom | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Gnosis | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| HyperEVM | EVM | :x: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs |
| Ink | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Kaia | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Karura | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs |
| Linea | EVM | :x: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Mantle | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Mezo | EVM | :x: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Monad | EVM | :x: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Moonbeam | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Neon | EVM | :x: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Oasis | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Optimism | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Polygon | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Scroll | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Seievm | EVM | :x: | :white_check_mark: | |
| SNAXchain | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Unichain | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| World Chain | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| X Layer | EVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
### SVM
| Solana | SVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Pythnet | SVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
### AVM
| Algorand | AVM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
### CosmWasm
| Injective | CosmWasm | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Neutron | CosmWasm | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Osmosis | CosmWasm | :x: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Sei | CosmWasm | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Terra | CosmWasm | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| Terra 2.0 | CosmWasm | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
| XPLA | CosmWasm | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
### Move VM
| Aptos | Move VM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
### NEAR VM
| NEAR | NEAR VM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
### Sui Move VM
| Sui | Sui Move VM | :white_check_mark: | :white_check_mark: | :material-web:Website:material-file-document:Developer Docs:octicons-package-16:Block Explorer |
--- END CONTENT ---
Doc-Content: https://wormhole.com/docs/build/start-building/testnet-faucets/
--- BEGIN CONTENT ---
---
title: Testnet Faucets
description: This page includes resources to quickly find the Testnet tokens you need to deploy and test applications and contracts on Wormhole's supported networks.
categories: Reference
---
# Testnet Faucets
## Get Started
Don't let the need for testnet tokens get in the way of buildling your next great idea with Wormhole. Use this guide to quickly locate the testnet token faucets you need to deploy and test applications and contracts on Wormhole's supported networks.
### EVM
| Ethereum Holesky | EVM | ETH | Alchemy Faucet |
| Ethereum Sepolia | EVM | ETH | Alchemy Faucet |
| Acala | EVM | ACA | Discord Faucet |
| Arbitrum Sepolia | EVM | ETH | List of Faucets |
| Avalanche | EVM | AVAX | Official Avalanche Faucet |
| Base Sepolia | EVM | ETH | List of Faucets |
| Berachain | EVM | BERA | Official Berachain Faucet |
| Blast | EVM | ETH | List of Faucets |
| BNB Smart Chain | EVM | BNB | Official BNB Faucet |
| Celo | EVM | CELO | Official Celo Faucet |
| Fantom | EVM | FTM | Official Fantom Faucet |
| Gnosis | EVM | xDAI | Official Gnosis Faucet |
| HyperEVM | EVM | mock USDC | Official Hyperliquid Faucet |
| Ink | EVM | ETH | Official Ink Faucet |
| Kaia | EVM | KAIA | Official Kaia Faucet |
| Karura | EVM | ACA | Discord Faucet |
| Linea | EVM | ETH | List of Faucets |
| Mantle | EVM | MNT | Official Mantle Faucet |
| Monad | EVM | MON | Official Monad Faucet |
| Moonbeam | EVM | DEV | Official Moonbeam Faucet |
| Neon | EVM | NEON | Official Neon Faucet |
| Oasis | EVM | TEST | Official Oasis Faucet |
| Optimism Sepolia | EVM | ETH | Superchain Faucet |
| Polygon Amoy | EVM | POL | Official Polygon Faucet |
| Scroll | EVM | ETH | List of Faucets |
| Unichain | EVM | ETH | QuickNode Faucet |
| World Chain | EVM | ETH | Alchemy Faucet |
| X Layer | EVM | OKB | X Layer Official Faucet |
### SVM
| Pythnet | SVM | ETH | Superchain Faucet |
### AVM
| Algorand | AVM | ALGO | Official Algorand Faucet |
### CosmWasm
| Celestia | CosmWasm | TIA | Discord Faucet |
| Cosmos Hub | CosmWasm | ATOM | Discord Faucet |
| Evmos | CosmWasm | TEVMOS | Official Evmos Faucet |
| Injective | CosmWasm | INJ | Official Injective Faucet |
| Kujira | CosmWasm | KUJI | Discord Faucet |
| Neutron | CosmWasm | NTRN | List of Faucets |
| Noble | CosmWasm | USDC | Circle Faucet |
| Osmosis | CosmWasm | OSMO | Official Osmosis Faucet |
| SEDA | CosmWasm | SEDA | Official SEDA Faucet |
| Sei | CosmWasm | SEI | Sei Atlantic-2 Faucet |
| Terra | CosmWasm | LUNA | Terra Official Faucet |
| Terra 2.0 | CosmWasm | LUNA | Terra Official Faucet |
| XPLA | CosmWasm | XPLA | XPLA Official Faucet |
### Move VM
| Aptos | Move VM | APT | Official Aptos Faucet |
### NEAR VM
| NEAR | NEAR VM | NEAR | Official NEAR Faucet |
### Sui Move VM
| Sui | Sui Move VM | SUI | List of Faucets |