Demos

## 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.
- **[Demo Tutorials](https://github.com/wormhole-foundation/demo-tutorials){target=\_blank}**: Explore various demos that showcase Wormhole's capabilities across different blockchains.

!!! 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 Networks by Product

## Supported Networks by Product

Wormhole supports a growing number of blockchains. Check out the [Supported Networks by Product](/docs/products/reference/supported-networks/){target=\_blank} page to see which networks are supported for each Wormhole product.


Next Steps

## Next Steps

<div class="grid cards" markdown>

-   :octicons-book-16:{ .lg .middle } **Architecture Overview**

    ---

    Get an overview of Wormhole's architecture, detailing key on-chain and off-chain components like the Core Contract, Guardian Network, and relayers.

    [:custom-arrow: Learn More](/docs/protocol/architecture/)

-   :octicons-tools-16:{ .lg .middle } **Wormhole Dev Arena**

    ---

    A structured learning hub with hands-on tutorials across the Wormhole ecosystem.

    [:custom-arrow: Explore the Dev Arena](https://arena.wormhole.com/){target=\_blank}

</div>


Core Security Assumptions

## Core Security Assumptions

At its core, Wormhole is secured by a network of [Guardian](/docs/protocol/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/protocol/infrastructure/vaas/){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.
- The [Executor](/docs/protocol/infrastructure/relayers/executor-framework/){target=\_blank} is considered untrusted in the Wormhole ecosystem. It can affect message availability (timing of delivery) but cannot alter or forge VAAs, as validity is enforced by Guardian signatures.

In summary:

- **Core integrators are not exposed to risk from chains and contracts they do not 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

## Guardian Network

Wormhole is an evolving platform. While the canonical Guardian set consists of 19 members, not all chains require all 19 Guardians to perform direct on-chain observation. For delegated chains, a delegated subset of Guardians performs direct on-chain observation while the final VAA signature threshold remains 13-of-19.

Delegated Guardian Sets introduces a per-chain trust assumption: the delegate quorum threshold determines how many Delegated Guardians must independently agree before Canonical Guardians sign. This model does not weaken the final 13-of-19 VAA requirement, but it means the observation layer for that chain depends on fewer nodes. The `WormholeDelegatedGuardians` governance contract allows these thresholds to be adjusted as network requirements evolve.


Governance

### 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 Wrapped Token Transfers (WTT) 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.
- Configure per-chain Delegated Guardian sets and security thresholds via the `WormholeDelegatedGuardians` contract.

The governance system is fully open source in the core repository. See the [Open Source section](#open-source){target=\_blank} for contract source.


Monitoring

## 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.

For full Guardian Set chains, all Guardians run full nodes and independently monitor block production and contract activity. For delegated chains, Delegated Guardians perform direct on-chain monitoring while Canonical Guardians monitor delegate observations and enforce quorum safeguards.

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

## 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.

For delegated chains, delegate quorum must be reached before Canonical Guardians contribute signatures, ensuring that per-chain delegate thresholds are respected without altering the Global Accountant's 13-of-19 security model.

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

## 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/protocol/infrastructure/core-contracts/){target=\_blank}**


Audits

## 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

## 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}.


Next Steps

## Next Steps

<div class="grid cards" markdown>

-   :octicons-book-16:{ .lg .middle } **View Latest Security Policies**

    ---

    The `SECURITY.md` from the official Wormhole repository on GitHub has the latest security policies and updates.

    [:custom-arrow: See SECURITY.md](https://github.com/wormhole-foundation/wormhole/blob/main/SECURITY.md){target=\_blank}

</div>


Installation

## 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

## 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

### Subcommands

??? interface "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 <package-dir>           Deploy an Aptos package
      worm aptos deploy-resource <seed>         Deploy an Aptos package using a
      <package-dir>                             resource account
      worm aptos send-example-message           Send example message
      <message>
      worm aptos derive-resource-account        Derive resource account address
      <account> <seed>
      worm aptos derive-wrapped-address         Derive wrapped coin type
      <chain> <origin-address>
      worm aptos hash-contracts <package-dir>   Hash contract bytecodes for upgrade
      worm aptos upgrade <package-dir>          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]
    ```

??? interface "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]
    ```

??? interface "EVM"
    ```bash
    worm evm INSERT_COMMAND

    Commands:
      worm evm address-from-secret <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]
    ```

??? interface "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]
    ```

??? interface "Info"
    ```bash
    worm info INSERT_COMMAND

    Commands:
      worm info chain-id <chain>                Print the wormhole chain ID integer
                                                associated with the specified chain
                                                name
      worm info contract <network> <chain>      Print contract address
      <module>
      worm info emitter <chain> <address>       Print address in emitter address
                                                format
      worm info origin <chain> <address>        Print the origin chain and address
                                                of the asset that corresponds to the
                                                given chain and address.
      worm info registrations <network>         Print chain registrations
      <chain> <module>
      worm info rpc <network> <chain>           Print RPC address
      worm info wrapped <origin-chain>          Print the wrapped address on the
      <origin-address> <target-chain>           target chain that corresponds with
                                                the specified origin chain and
                                                address.

    Options:
      --help     Show help                                                 [boolean]
      --version  Show version number                                       [boolean]
    ```

??? interface "NEAR"
    ```bash
    worm near INSERT_COMMAND

    Commands:
      worm near contract-update <file>  Submit a contract update using our specific
                                        APIs
      worm near deploy <file>           Submit a contract update using near APIs

    Options:
          --help      Show help                                            [boolean]
          --version   Show version number                                  [boolean]
      -m, --module    Module to query  [choices: "Core", "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]
    ```

??? interface "Parse"
    ```bash
    worm parse INSERT_VAA

    Positionals:
      vaa  vaa                                                              [string]

    Options:
      --help     Show help                                                 [boolean]
      --version  Show version number                                       [boolean]
    ```

??? interface "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]
    ```

??? interface "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]
    ```

??? interface "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]
    ```

??? interface "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 <package-dir>          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 <owner>               Get owned objects by owner
      worm sui package-id <state-object-id>  Get package ID from State object ID
      worm sui tx <transaction-digest>       Get transaction details

    Options:
      --help     Show help                                                 [boolean]
      --version  Show version number                                       [boolean]
    ```

??? interface "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]
    ```

??? interface "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"]
    ```


Tooling Installation

## Tooling Installation

The [Wormhole CLI Tool](/docs/tools/cli/get-started/){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/products/reference/supported-networks/){target=\_blank}.


Development Stages

## Development Stages

Different approaches to development and testing are recommended at various stages of application development.


Initial 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 VAAs for 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

### 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/products/reference/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

### 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

## Validator Setup with Tilt


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

## Deploying to Public Networks


Testnet

### 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/products/reference/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

### Mainnet

The Mainnet contract addresses are available on the page for each [environment](/docs/products/reference/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
```


## 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/products/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.


Install the SDK

## Install the SDK

To install the Wormhole TypeScript SDK, use the following command:

```bash
npm install @wormhole-foundation/sdk
```

This package combines all the individual packages to make setup easier.

You can choose to install a specific set of packages as needed. For example, to install EVM-specific utilities, you can run:

```bash
npm install @wormhole-foundation/sdk-evm
```

??? example "Complete list of individually published packages"

    Platform-Specific Packages

    - `@wormhole-foundation/sdk-evm`
    - `@wormhole-foundation/sdk-solana`
    - `@wormhole-foundation/sdk-algorand`
    - `@wormhole-foundation/sdk-aptos`
    - `@wormhole-foundation/sdk-cosmwasm`
    - `@wormhole-foundation/sdk-sui`

    ---

    Protocol-Specific Packages

    - Core Protocol
        - `@wormhole-foundation/sdk-evm-core`
        - `@wormhole-foundation/sdk-solana-core`
        - `@wormhole-foundation/sdk-algorand-core`
        - `@wormhole-foundation/sdk-aptos-core`
        - `@wormhole-foundation/sdk-cosmwasm-core`
        - `@wormhole-foundation/sdk-sui-core`

    - WTT
        - `@wormhole-foundation/sdk-evm-tokenbridge`
        - `@wormhole-foundation/sdk-solana-tokenbridge`
        - `@wormhole-foundation/sdk-algorand-tokenbridge`
        - `@wormhole-foundation/sdk-aptos-tokenbridge`
        - `@wormhole-foundation/sdk-cosmwasm-tokenbridge`
        - `@wormhole-foundation/sdk-sui-tokenbridge`

    - CCTP
        - `@wormhole-foundation/sdk-evm-cctp`
        - `@wormhole-foundation/sdk-solana-cctp`
        - `@wormhole-foundation/sdk-aptos-cctp`
        - `@wormhole-foundation/sdk-sui-cctp`

    - Other Protocols
        - `@wormhole-foundation/sdk-evm-portico`
        - `@wormhole-foundation/sdk-evm-tbtc`
        - `@wormhole-foundation/sdk-solana-tbtc`

    ---

    Utility Packages

    - `@wormhole-foundation/sdk-base`
    - `@wormhole-foundation/sdk-definitions`
    - `@wormhole-foundation/sdk-connect`


Initialize the SDK

## Initialize the SDK

Getting your integration started is simple. First, import Wormhole:

```ts
import { wormhole } from '@wormhole-foundation/sdk';
```

Then, import each of the ecosystem [platforms](/docs/tools/typescript-sdk/sdk-reference/#platforms) that you wish to support:

```ts
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';
```

To make the [platform](/docs/tools/typescript-sdk/sdk-reference/#platforms) modules available for use, pass them to the Wormhole constructor and specify the network (`Mainnet`, `Testnet`, or `Devnet`) you want to interact with:

```ts
  const wh = await wormhole('Testnet', [
    evm,
    solana,
    aptos,
    algorand,
    cosmwasm,
    sui,
  ]);
```

With a configured `Wormhole` object, you can begin to interact with these chains.


Example Usage

## Example Usage

Follow these steps to confirm that the SDK is initialized correctly and can fetch basic chain information for your target chains.


Prerequisites

### Prerequisites

Before you begin, make sure you have the following:

 - [Node.js and npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm){target=\_blank} installed.
 - [TypeScript](https://www.typescriptlang.org/download/){target=\_blank} installed.

??? example "Project setup instructions"

    Use the following commands to create a TypeScript project:

    1. Create a directory and initialize a Node.js project:

        ```bash
        mkdir wh-ts-demo
        cd wh-ts-demo
        npm init -y
        ```

    2. Install TypeScript, `tsx` (for running TypeScript files), Node.js type definitions, the base Wormhole SDK, and the platform-specific packages for the chains you want to interact with:

        ```bash
        npm install --save-dev tsx typescript @types/node @wormhole-foundation/sdk @wormhole-foundation/sdk-evm @wormhole-foundation/sdk-solana
        ```

    3. Create a `tsconfig.json` if you don't have one. You can generate a basic one using the following command:

        ```bash
        npx tsc --init
        ```

        Make sure your `tsconfig.json` includes the following settings:

        ```json
        {
            "compilerOptions": {
                // es2020 or newer
                "target": "es2020",
                // Use esnext if you configured your package.json with type: "module"
                "module": "commonjs",
                "esModuleInterop": true,
                "forceConsistentCasingInFileNames": true,
                "strict": true,
                "skipLibCheck": true,
                "resolveJsonModule": true
            }
        }
        ```

    4. Initialize the main `Wormhole` class to use the SDK. Create a new TypeScript file named `src/main.ts` in your project directory:

        ```bash
        mkdir src
        touch src/main.ts
        ```

    5. Add the following code to initialize the SDK and use the `Wormhole` instance to return the chain ID and RPC for the chains this instance supports:

        ```ts title="src/main.ts"
        import { wormhole } from '@wormhole-foundation/sdk';
        // Import specific platform modules for the chains you intend to use
        import evm from '@wormhole-foundation/sdk/evm';
        import solana from '@wormhole-foundation/sdk/solana';

        async function main() {
          console.log('Initializing Wormhole SDK...');

          // Determine the network: "Mainnet", "Testnet", or "Devnet"
          const network = 'Testnet';

          // Initialize the SDK with the chosen network and platform contexts
          const wh = await wormhole(network, [evm, solana]);

          console.log('Wormhole SDK Initialized!');
        }

        main().catch((e) => {
          console.error('Error initializing Wormhole SDK', e);
          process.exit(1);
        });
        ```


Fetch Chain Information

### Fetch Chain Information

1. Update the `main` function as follows to retrieve the chain ID and RPC for the chains your project supports:

    ```ts title="src/main.ts"
    import { wormhole } from '@wormhole-foundation/sdk';
    import evm from '@wormhole-foundation/sdk/evm';
    import solana from '@wormhole-foundation/sdk/solana';

    async function main() {
      console.log('Initializing Wormhole SDK...');

      const network = 'Testnet';
      const wh = await wormhole(network, [evm, solana]);

      console.log('Wormhole SDK Initialized!');

      // Example: Get a chain ID and RPC for Solana
      const solanaDevnetChain = wh.getChain('Solana');
      console.log(
        `Chain ID for Solana Testnet: ${solanaDevnetChain.config.chainId}`
      );
      console.log(`RPC for Solana Testnet: ${solanaDevnetChain.config.rpc}`);

      // Example: Get a chain ID for Sepolia (EVM Testnet)
      const sepoliaChain = wh.getChain('Sepolia');
      console.log(`Chain ID for Sepolia: ${sepoliaChain.config.chainId}`);
      console.log(`RPC for Sepolia: ${sepoliaChain.config.rpc}`);
    }

    main().catch((e) => {
      console.error(
        'Error initializing Wormhole SDK or fetching chain information:',
        e
      );
      process.exit(1);
    });
    ```

2. Run the script with the following command, replacing `INSERT_FILE_NAME` with your file name:

    ```bash
    npx tsx INSERT_FILE_NAME
    ```

    You will see terminal output similar to the following:

        npx tsx src/main.ts
        Initializing Wormhole SDK...
        Wormhole SDK Initialized!
        Chain ID for Solana Testnet: 1
        RPC for Solana Testnet: https://api.devnet.solana.com
        Chain ID for Sepolia: 10002
        RPC for Sepolia: https://ethereum-sepolia.publicnode.com

Congratulations! You’ve successfully installed the Wormhole TypeScript SDK and initialized a `Wormhole` instance. Consider the following options to build on what you've accomplished.


Next Steps

## Next Steps

<div class="grid cards" markdown>

-   :octicons-book-16:{ .lg .middle } **TypeScript SDK Reference**

    ---

    Explore Wormhole's TypeScript SDK and learn how to perform different types of transfers, including native, token, and USDC.

    [:custom-arrow: Get Familiar with the SDK](/docs/tools/typescript-sdk/sdk-reference/)

-   :octicons-tools-16:{ .lg .middle } **Send a Multichain Message**

    ---

    Use Wormhole's core protocol to publish a multichain message and return transaction information with VAA identifiers.

    [:custom-arrow: Get Started](/docs/products/messaging/get-started/)

-   :octicons-tools-16:{ .lg .middle } **Transfer Assets via WTT**

    ---

    Build a cross-chain native token transfer app using the TypeScript SDK, supporting native token transfers across EVM and non-EVM chains.

    [:custom-arrow: Get Started](/docs/products/token-transfers/wrapped-token-transfers/tutorials/transfer-workflow/)

-   :octicons-tools-16:{ .lg .middle } **Transfer USDC via the CCTP Bridge**

    ---

    Perform USDC cross-chain transfers using the TypeScript SDK and Circle's CCTP.

    [:custom-arrow: Get Started](/docs/products/cctp-bridge/tutorials/complete-usdc-transfer/)

</div>


What is a Protocol?

## 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?

## 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

## 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

### 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<N, C> {
      TokenBridge: TokenBridge<N, C>;
    }
    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

### 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 `<ProtocolName>:<PayloadName>`. 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<LayoutLiteral, Layout>();

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

## 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/tools/typescript-sdk/guides/sdk-layout/){target=\_blank}.


Payload Discriminators

### 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<B extends boolean = false>(
  layouts: readonly Layout[],
  allowAmbiguous?: B
): Discriminator<B> {
  // 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<B>;
}
```

 - [`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: Wrapped Token Transfers (WTT) 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.

!!! note "Terminology"
    The SDK and smart contracts use the name Token Bridge. In documentation, this product is referred to as Wrapped Token Transfers (WTT). Both terms describe the same protocol.

#### WTT 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}.

#### WTT 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}.


Key Concepts

## Key Concepts


Layout Items

### 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 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

### 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<number, Chain>;
```

This setup allows Wormhole to convert between human-readable formats and binary-encoded data used in payloads.


Error Handling

### 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

## 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

### 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

### 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

### 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

### 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

## 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

### 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

### 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<typeof nestedLayout>;
```

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

## 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

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<C[number], N> => { ... },
      from: (val: AllowNull<C[number], N>): 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 = <const C extends Chain>(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

### 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<Uint8Array, UniversalAddress>,
} 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

### 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<typeof signatureLayout>) =>
      new Signature(val.r, val.s, val.v),
    from: (val: Signature) => ({ r: val.r, s: val.s, v: val.v }),
  } satisfies CustomConversion<LayoutToType<typeof signatureLayout>, 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

## 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

## 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 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/products/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<typeof layout>);
    ```

#### 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

### 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/tools/typescript-sdk/guides/protocols-payloads/){target=\_blank} page for a detailed guide.


Common Pitfalls & Best Practices

## 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

### 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

### 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

## 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

### 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

## 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.


VAA Structure

## 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 Wrapped Token Transfers (WTT) 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`](https://github.com/wormhole-foundation/wormhole-solidity-sdk/blob/main/src/libraries/VaaLib.sol){target=\_blank} to decode and execute protocol actions.


VAAs in Protocol Contexts

## 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 [WTT](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                            |
|------------------|-----------------------------------------------------------|------------------------------------|
| WTT              | 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.