This commit is contained in:
spacemandev 2022-09-23 11:06:21 -05:00
commit f5d5a37ac4
43 changed files with 965 additions and 321 deletions

View File

@ -1,5 +1,5 @@
[book]
title = "Wormhole xDapp Development Book v0.1.0"
title = "Wormhole Development Book"
authors = [
"Dev Bharel"
]

View File

@ -8,8 +8,8 @@
- [xDapps](./dapps/0_xdappOverview.md)
- [Dapp Ecosystem Basics](./dapps/1_defiBasics.md)
- [Cross-Chain Interoperability](./dapps/2_crossChainInteroperability.md)
- [Ecosystem Basics](./dapps/1_defiBasics.md)
- [Blockchain Interoperability](./dapps/2_crossChainInteroperability.md)
- [xData & xAssets](./dapps/3_xdataxassets.md)
- [What is an xDapp?](./dapps/4_whatIsanXdapp.md)
- [Advantages of xDapps](./dapps/5_advantages.md)
@ -22,7 +22,7 @@
- [VAA: Verified Action Approval](./wormhole/4_vaa.md)
- [Guardian Network](./wormhole/5_guardianNetwork.md)
- [Relayers](./wormhole/6_relayers.md)
- [xAsset Bridge](./wormhole/7_TokenBridge.md)
- [xAsset Bridge](./wormhole/7_xAssetBridge.md)
- [Wormchain](./wormhole/8_wormchain.md)
- [xDapp Design](./dapps/architecture/0_dappDesign.md)
@ -45,40 +45,36 @@
- [Testnet](./technical/env/testnet.md)
- [Tooling](./technical/env/tooling.md)
- [Contract Development]()
- [Contract Development](./technical/overview.md)
- [EVM](./technical/evm//overview.md)
- [EVM](./technical/evm/overview.md)
- [Core Layer](./technical/evm/coreLayer.md)
- [xAsset Module](./technical/evm/xassetLayer.md)
- [NFT Module](./technical/evm/nftLayer.md)
- [Relayer Module](./technical/evm/relayer.md)
- [Token Bridge Module](./technical/evm/tokenLayer.md)
- [NFT Bridge Module](./technical/evm/nftLayer.md)
- [Best Practices](./technical/evm/bestPractices.md)
- [Solana]()
- [Cosmos]()
- [Algorand]()
- [Near]()
- [Aptos]()
<!-- - [Relayer Module](./technical/evm/relayer.md) -->
- [Solana](./technical/solana/overview.md)
- [Cosmos](./technical/cosmos/overview.md)
- [Algorand](./technical/algorand/overview.md)
- [Near](./technical/near/overview.md)
- [Aptos](./technical/aptos/overview.md)
- [Sui]()
- [Relayers](./technical/relayer/overview.md)
- [Generic Relayers](./technical/relayer/genericRelayer.md)
- [Specialized Relayers](./technical/relayer/pluginRelayers.md)
- [Specialized Relayers](./technical/relayer/specializedRelayers.md)
- [Wormhole Typescript SDK](./development/portal/overview.md)
- [EVM]()
- [Attesting](./development/portal/evm/attestingToken.md)
- [Transfer Tokens](./development/portal/evm/tokenTransfer.md)
- [Portal JS SDK](./development/portal/sdkjs/overview.md)
- [EVM to Solana Transfer](./development/portal/sdkjs/evm-solana-transfer.md)
- [Polygon to Oasis with Relayers](./development/portal/sdkjs/polygon-oasis-relayer.md)
- [Wormhole Typescript SDK](./technical/typescript/overview.md)
- [Token Registration](./technical/typescript/attestingToken.md)
- [Token Transfer Basics](./technical/typescript/tokenTransfer.md)
- [Cross-Ecosystem Transfer](./technical/typescript/cross-ecosystem-transfer.md)
- [Using Relayers](./technical/typescript/using-relayer.md)
---
# Other Resources
- [Glossary](./reference/glossary.md)
- [Tools](./reference/tools.md)
- [Github & Useful Links](./reference/github.md)
- [Deployed Contracts](./reference/contracts.md)
- [RPC Nodes](./reference/rpcnodes.md)
- [Other Resources](./reference/overview.md)
- [Glossary](./reference/glossary.md)
- [Useful Links](./reference/usefulLinks.md)
- [Deployed Contracts](./reference/contracts.md)
- [RPC Nodes](./reference/rpcnodes.md)

View File

@ -1,4 +1,4 @@
# Dapp Basics
# Ecosystem Basics
Since the launch of Bitcoin in 2009, the cryptocurrency and decentralized computing ecosystem has rapidly evolved and expanded. The ecosystem now includes hundreds of blockchains, often also referred to as **Layer 1s**.

View File

@ -1,8 +1,8 @@
# Cross-Chain Interoperability
# Blockchain Interoperability
Because blockchains are siloed by nature, individual cryptocurrencies being bound to their own chains has been a longtime limitation of blockchain technology. The first attempt at solving this problem was the creation of cryptocurrency exchanges like Coinbase and Binance. Today these are refered to as centralized exchanges (CEXs).
Centralized exchanges play an important role in cryptocurrency, but they are not a complete solution for cross-chain interoperability for two primary reasons: (1) they're centralized, which is counterproductive to creating a decentralized platform, and (2) they deal only with tokens.
Centralized exchanges play an important role in cryptocurrency, but they are not a complete solution for blockchain interoperability for two primary reasons: (1) they're centralized, which is counterproductive to creating a decentralized platform, and (2) they deal only with tokens.
To solve the centralization problems with CEXs, decentralized exchanges (DEXs) were created. A DEX operates inside a smart contract runtime and can be as decentralized as the blockchain it runs on. Unfortunately, a DEX is only able to utilize the tokens on its native blockchain. In order to obtain a token which is not native to that chain, the DEX must be used in combination with a **bridge**.

View File

@ -1,6 +1,6 @@
# Ecosystems
At present, there are 3 ecosystems supported by Wormhole, though the number of supported ecosystems is always growing.
At present, there are 6 ecosystems supported by Wormhole, though the number of supported ecosystems is always growing.
### EVM
@ -27,6 +27,18 @@ Solana is characterized by its high transaction throughput, increased computatio
Cosmos is a network of blockchains that share a common ecosystem. Cosmos is a general purpose environment, but excels in certain areas like application-specific blockchains and the use of Cosmos-wide standards via its sdk 'modules.' It uses CosmWasm for its smart contract runtime, which is based in Rust.
### Algorand
Algorand is a leading blockchain on the state proof front and repesents the bleeding edge of trustlessness. These contracts are written in Python.
### Aptos
Aptos is characterized by its optimisitic approach to computation parallelization to bring increased performance. These contracts are written in Move.
### NEAR
NEAR is characterized by its sharding technology that may allow for greater transaction capacity and security. These contracts are written in Rust.
### Read-Only Chains
Some chains in the Wormhole ecosystem are 'Read-Only.' These chains are able to verify messages emitted from other chains in the network, but are not able to emit messages themselves. For information about these chains, check the [contracts page](../../reference/contracts.md).

View File

@ -1,6 +1,6 @@
# Portal JS SDK Overview
# Wormhole Typescript SDK Overview
For applications that only need to interact with the Core and Token Bridge contracts off-chain, there is a Wormhole JS SDK provided.
For applications that only need to interact with the Core and Token Bridge contracts off-chain, there is a Wormhole Typescript SDK provided.
It can be installed using npm:

View File

@ -1,10 +1,10 @@
# Polygon to Oasis with Relayers
In this example, well fetch the fee schedule and attach a relayer fee onto our transaction. This is a non-trivial example as well also use Polygon as a source chain, which has some quirks when it comes to gas estimation.
In this example, well fetch the fee schedule and attach a relayer fee onto our transaction. This is a non-trivial example as well also use Polygon as a source chain, which has some quirks when it comes to gas estimation.
NOTE: We're working on streamlining this process, so check back in the future for a much simpler version of this example.
To start, well need a couple of packages:
To start, well need a couple of packages:
```bash
npm i --save @certusone/wormhole-sdk ethers node-fetch
@ -16,15 +16,15 @@ Then, get started writing some code:
import { BigNumber, ethers } from "ethers";
import fetch from "node-fetch";
import {
getEmitterAddressEth,
hexToUint8Array,
nativeToHexString,
parseSequenceFromLogEth,
CHAIN_ID_POLYGON,
CHAIN_ID_OASIS,
transferFromEthNative,
getIsTransferCompletedEth,
setDefaultWasm
getEmitterAddressEth,
hexToUint8Array,
nativeToHexString,
parseSequenceFromLogEth,
CHAIN_ID_POLYGON,
CHAIN_ID_OASIS,
transferFromEthNative,
getIsTransferCompletedEth,
setDefaultWasm,
} from "@certusone/wormhole-sdk";
```
@ -34,56 +34,59 @@ Now, set up the two wallets well be sending and receiving from. While we are
```ts
const EmeraldWallet = new ethers.Wallet(
privatekey_emerald,
new ethers.providers.JsonRpcProvider("https://emerald.oasis.dev")
privatekey_emerald,
new ethers.providers.JsonRpcProvider("https://emerald.oasis.dev")
);
const PolygonWallet = new ethers.Wallet(
privatekey_polygon,
new ethers.providers.JsonRpcProvider("https://polygon-rpc.com/")
privatekey_polygon,
new ethers.providers.JsonRpcProvider("https://polygon-rpc.com/")
);
```
### Fetch the fee schedule
Fetch the fee schedule for the Portal Token Bridge relayer. This fee schedule outlines the minimum fee for each recipient chain that the relayer will accept. As long as we attach at least that fee in the relayer fee, we can be fairly confident that the relayer will pick up the transaction and relay it to the recipient chain. The fee will cover the gas cost for the relayer along with a little extra to make it worth their time to run the relayer service.
We will also define the transfer amount in this step. The fee schedule will either return a flat fee in USD for the recipient chain, or a percentage fee (usually only for Ethereum). Either way, well need to calculate the fee in in BigNumber format (no decimals).
Fetch the fee schedule for the token bridge relayers. This fee schedule outlines the minimum fee for each recipient chain that the relayer will accept. As long as we attach at least that fee in the relayer fee, we can be fairly confident that the relayer will pick up the transaction and relay it to the recipient chain. The fee will cover the gas cost for the relayer along with a little extra to make it worth their time to run the relayer service.
For example, 1 MATIC on Polygon is 1e18 wei, or 1000000000000000000 wei. Because EVM has a hard time with floating point math, we have to do all our transactions in this small unit, to avoid decimal numbers.
We will also define the transfer amount in this step. The fee schedule will either return a flat fee in USD for the recipient chain, or a percentage fee (usually only for Ethereum). Either way, well need to calculate the fee in in BigNumber format (no decimals).
For example, 1 MATIC on Polygon is 1e18 wei, or 1000000000000000000 wei. Because EVM has a hard time with floating point math, we have to do all our transactions in this small unit, to avoid decimal numbers.
```ts
const transferAmount = BigNumber.from("1000000000000000000"); // We are sending 1 MATIC over the wall to Oasis
const relayerFeeSchedule = await (await fetch(
"https://raw.githubusercontent.com/certusone/wormhole-relayer-list/main/relayer.json"
)).json();
const relayerFeeSchedule = await(
await fetch(
"https://raw.githubusercontent.com/certusone/wormhole-relayer-list/main/relayer.json"
)
).json();
```
The fee schedule has the following interface:
```ts
export interface RelayerFeeSchedule {
supportedTokens: ChainAddress[];
relayers: Relayer[];
feeSchedule: FeeSchedule;
supportedTokens: ChainAddress[];
relayers: Relayer[];
feeSchedule: FeeSchedule;
}
interface ChainAddress {
chainId: number;
address: string;
coingeckoId: string;
chainId: number;
address: string;
coingeckoId: string;
}
interface Relayer {
name: string;
url: string;
name: string;
url: string;
}
interface FeeSchedule {
[chainId: string]: {
type: "flat" | "percent";
feeUsd?: number;
feePercent?: number;
gasEstimate?: number;
};
[chainId: string]: {
type: "flat" | "percent";
feeUsd?: number;
feePercent?: number;
gasEstimate?: number;
};
}
```
@ -92,70 +95,65 @@ After fetching the fee schedule, find the fee in wei that needs to be paid to th
```ts
let feeWei: number;
if (relayerFeeSchedule.feeSchedule[CHAIN_ID_OASIS].type == "flat") {
const feeUsd = relayerFeeSchedule.feeSchedule[CHAIN_ID_OASIS].feeUsd
const MATIC_PRICE = (
await (
await fetch(
"https://api.coingecko.com/api/v3/simple/token_price/polygon-pos?contract_addresses=0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270&vs_currencies=usd"
)
).json()
)["0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270"]["usd"];
const feeUsd = relayerFeeSchedule.feeSchedule[CHAIN_ID_OASIS].feeUsd;
const MATIC_PRICE = await(
await fetch(
"https://api.coingecko.com/api/v3/simple/token_price/polygon-pos?contract_addresses=0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270&vs_currencies=usd"
)
).json()["0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270"]["usd"];
feeWei = (feeUsd / MATIC_PRICE) * 1e18;
feeWei = (feeUsd / MATIC_PRICE) * 1e18;
} else if (relayerFeeSchedule.feeSchedule[CHAIN_ID_OASIS].type == "percent") {
let feeWei = (relayerFeeSchedule.feeSchedule[CHAIN_ID_OASIS].feePercent /100) * transferAmount.toNumber();
let feeWei =
(relayerFeeSchedule.feeSchedule[CHAIN_ID_OASIS].feePercent / 100) *
transferAmount.toNumber();
}
```
### Add override for gas estimation for Polygon
When the source chain is Polygon, there's an additional step to overestimate the gas. This is because Ethers library has some problems with fee estimation after EIP-1559.
```ts
let overrides;
let feeData = await PolygonWallet.provider.getFeeData();
overrides = {
maxFeePerGas: feeData.maxFeePerGas?.mul(50) || undefined,
maxPriorityFeePerGas:
feeData.maxPriorityFeePerGas?.mul(50) || undefined,
maxFeePerGas: feeData.maxFeePerGas?.mul(50) || undefined,
maxPriorityFeePerGas: feeData.maxPriorityFeePerGas?.mul(50) || undefined,
};
```
### Emit Portal Message
Now we have all the pieces we need to emit a Portal Bridge message with a relay fee attached. We do this using the transferFromEthNative() method. EthNative is used because were transferring the native token of the Polygon network rather than an ERC20 token.
### Emit Token Bridge Message
Now we have all the pieces we need to emit a token bridge message with a relay fee attached. We do this using the transferFromEthNative() method. EthNative is used because were transferring the native token of the Polygon network rather than an ERC20 token.
```ts
const POLYGON_TOKEN_BRIDGE = "0x5a58505a96D1dbf8dF91cB21B54419FC36e93fdE";
const receipt = await transferFromEthNative(
POLYGON_TOKEN_BRIDGE,
PolygonWallet,
transferAmount,
CHAIN_ID_OASIS,
hexToUint8Array(
nativeToHexString(
await EmeraldWallet.getAddress(),
CHAIN_ID_OASIS
) || ""
),
BigNumber.from(feeWei.toString()),
overrides
POLYGON_TOKEN_BRIDGE,
PolygonWallet,
transferAmount,
CHAIN_ID_OASIS,
hexToUint8Array(
nativeToHexString(await EmeraldWallet.getAddress(), CHAIN_ID_OASIS) || ""
),
BigNumber.from(feeWei.toString()),
overrides
);
console.log("Receipt: ", receipt);
const POLYGON_CORE_BRIDGE_ADDRESS =
"0x7A4B5a56256163F07b2C80A7cA55aBE66c4ec4d7";
const sequence = parseSequenceFromLogEth(
receipt,
POLYGON_CORE_BRIDGE_ADDRESS
);
"0x7A4B5a56256163F07b2C80A7cA55aBE66c4ec4d7";
const sequence = parseSequenceFromLogEth(receipt, POLYGON_CORE_BRIDGE_ADDRESS);
const emitterAddress = getEmitterAddressEth(POLYGON_TOKEN_BRIDGE);
console.log("Sequence: ", sequence);
console.log("EmitterAddress: ", emitterAddress);
```
Lets walk through each of the arguments of this function and what they mean.
Lets walk through each of the arguments of this function and what they mean.
`POLYGON_TOKEN_BRIDGE` is the address of the Portal Token Bridge on the Polygon network. You can find it and other addresses on the Deployment Info page.
`POLYGON_TOKEN_BRIDGE` is the address of the token bridge module on the Polygon network. You can find it and other addresses on the Deployment Info page.
`PolygonWallet` is a signer you get from the Ethers library that holds a private key that can sign transactions.
@ -165,7 +163,7 @@ Lets walk through each of the arguments of this function and what they mean.
`hexToUint8Array()` translates the target publickey into a wormhole public key.
`BigNumber.from(feeWei.toString())` identifies the fee in smallest unit of the network for the relayer.
`BigNumber.from(feeWei.toString())` identifies the fee in smallest unit of the network for the relayer.
`overrides` are used if we need to override the gas cost, which we need to do for Polygon.
@ -178,17 +176,15 @@ await new Promise((r) => setTimeout(r, 900000)); //15m in seconds
const WORMHOLE_RPC = "https://wormhole-v2-mainnet-api.certus.one";
let vaaBytes = undefined;
while (!vaaBytes) {
try {
vaaBytes = (
await (
await fetch(
`${WORMHOLE_RPC}/v1/signed_vaa/${CHAIN_ID_POLYGON}/${emitterAddress}/${sequence}`
)
).json()
).vaaBytes;
} catch (e) {
await new Promise((r) => setTimeout(r, 5000));
}
try {
vaaBytes = await(
await fetch(
`${WORMHOLE_RPC}/v1/signed_vaa/${CHAIN_ID_POLYGON}/${emitterAddress}/${sequence}`
)
).json().vaaBytes;
} catch (e) {
await new Promise((r) => setTimeout(r, 5000));
}
}
console.log("VAA Bytes: ", vaaBytes);
```
@ -201,17 +197,17 @@ In the final step, use the getIsTransferCompletedEth() method to check if the tr
setDefaultWasm("node"); //only needed if running in node.js
const EMERALD_TOKEN_BRIDGE = "0x5848C791e09901b40A9Ef749f2a6735b418d7564";
let transferCompleted = await getIsTransferCompletedEth(
EMERALD_TOKEN_BRIDGE,
EmeraldWallet.provider,
vaaBytes
);
while (!transferCompleted) {
await new Promise((r) => setTimeout(r, 5000));
transferCompleted = await getIsTransferCompletedEth(
EMERALD_TOKEN_BRIDGE,
EmeraldWallet.provider,
vaaBytes
);
while (!transferCompleted) {
await new Promise((r) => setTimeout(r, 5000));
transferCompleted = await getIsTransferCompletedEth(
EMERALD_TOKEN_BRIDGE,
EmeraldWallet.provider,
vaaBytes
);
);
}
console.log("VAA Relayed!");

View File

@ -1,17 +1,30 @@
# Contracts and Accounts
The devnet environment deploys the Wormhole and Portal contracts to each of the chains at the same addresses every time. It also provides specific wallets with funds.
The devnet environment deploys the core layer and token bridge to each of the chains at the same addresses every time. It also provides specific wallets with funds.
## Tilt
## Guardian
- REST Port: 7071
- gRPC Port: 7070
## ETH0
- RPC Port: 8545
## ETH1
- RPC Port: 8546
## Solana
- RPC Port: 8899
## Algorand
- RPC Port:
- RPC Port:
## Terra
- RPC Port:
- RPC Port:

View File

@ -1,8 +1,8 @@
# Tilt Development Environment
For a faster development cycle, especially when developing blockchain programs that interact with Wormhole or Portal contracts, consider setting up the Tilt Devnet Environment.
For a faster development cycle, especially when developing blockchain programs that interact with Wormhole contracts, consider setting up the Tilt Devnet Environment.
Tilt is a Kubernetes and Docker orchestration tool that will spin up all the Wormhole supported chains in containers, alongside a Guardian node that will observe and store VAAs.
Tilt is a Kubernetes and Docker orchestration tool that will spin up all the Wormhole supported chains in containers, alongside a Guardian node that will observe and store VAAs.
This devnet environment can be set up on your computer or in a Linux VM that has at least 4 CPU cores and 16GB of RAM.
@ -15,22 +15,25 @@ tilt up --host=0.0.0.0 -- --webHost=0.0.0.0
While the exact commands for each environment might differ, the basic setup process for Tilt is the following:
1. Install Go
2. Install Docker Desktop (Or Docker CE)
a. Install Minikube if Docker CE
2. Install Docker Desktop (Or Docker CE)
a. Install Minikube if Docker CE
3. Install Tilt
4. Clone Wormhole Repo and Tilt Up
## FAQ
## FAQ
### Where are Fantom/Celo/Polygon/other EVM chains?
For all chains that support EVM, the smart contract development environment is effectively the same. For changes in gas costs and transaction times, consider testing contract logic on devnet and then using testnet environments to get chain-specific answers.
For all chains that support EVM, the smart contract development environment is effectively the same. For changes in gas costs and transaction times, consider testing contract logic on devnet and then using testnet environments to get chain-specific answers.
### Solana is taking forever
Due to Solana's architecture, it often takes 25-40min to build the Solana pod. Consider increasing CPU cores assigned to devnet for a faster build.
### Solana program deploy doesn't work
Kubernetes doesn't currently allow port forwarding for UDP ports, which is what Solana uses for `solana program deploy`. Instead, we recommend using [Solana Deployer](https://github.com/acheroncrypto/solana-deployer). Not only does this deploy programs over regular RPC (thus bypassing UDP port requirements), it's also much faster than `solana program deploy`.
### Reset state for a pod
If you want to quickly iterate and don't want to bring Tilt down and back up, you can reset state for a pod by clicking the 🔄 button next to the pod name in Tilt UI.
If you want to quickly iterate and don't want to bring Tilt down and back up, you can reset state for a pod by clicking the 🔄 button next to the pod name in Tilt UI.

View File

@ -67,48 +67,50 @@ The [constants](https://github.com/wormhole-foundation/wormhole/blob/dev.v2/sdk/
### Core Bridge
| Chain Name | Wormhole Chain ID | Network ID | Address |
| :---------------------- | :---------------- | :--------- | :--------------------------------------------------------------- |
| Solana | 1 | devnet | 3u8hJUVTA4jH1wYAyUur7FFZVQ8H635K3tSHHF4ssjQ5 |
| Ethereum (Goerli) | 2 | 5 | 0x706abc4E45D419950511e474C7B9Ed348A4a716c |
| Ethereum (Ropsten) | 10001 | 3 | 0x210c5F5e2AF958B4defFe715Dc621b7a3BA888c5 |
| Terra | 3 | bombay-12 | terra1pd65m0q9tl3v8znnz5f5ltsfegyzah7g42cx5v |
| Binance Smart Chain | 4 | 97 | 0x68605AD7b15c732a30b1BbC62BE8F2A509D74b4D |
| Polygon (Mumbai) | 5 | 80001 | 0x0CBE91CF822c73C2315FB05100C2F714765d5c20 |
| Avalanche (Fuji) | 6 | 43113 | 0x7bbcE28e64B3F8b84d876Ab298393c38ad7aac4C |
| Oasis (Emerald Testnet) | 7 | 42261 | 0xc1C338397ffA53a2Eb12A7038b4eeb34791F8aCb |
| Algorand (Testnet) | 8 | | 86525623 |
| Aurora | 9 | 1313161555 | 0xBd07292de7b505a4E803CEe286184f7Acf908F5e |
| Fantom | 10 | 4002 | 0x1BB3B4119b7BA9dfad76B0545fb3F531383c3bB7 |
| Karura | 11 | 686 | 0xE4eacc10990ba3308DdCC72d985f2a27D20c7d03 |
| Acala | 12 | 787 | 0x4377B49d559c0a9466477195C6AdC3D433e265c0 |
| Klaytn | 13 | 1001 | 0x1830CC6eE66c84D2F177B94D544967c774E624cA |
| Celo | 14 | 44787 | 0x88505117CA88e7dd2eC6EA1E13f0948db2D50D56 |
| NEAR | 15 | | wormhole.wormhole.testnet |
| Terra | 18 | pisco-1 | terra19nv3xr5lrmmr7egvrk2kqgw4kcn43xrtd5g0mpgwwvhetusk4k7s66jyv0 |
| Injective | 19 | testnet | inj1xx3aupmgv3ce537c0yce8zzd3sz567syuyedpg |
| Chain Name | Wormhole Chain ID | Network ID | Address |
| :---------------------- | :---------------- | :--------- | :----------------------------------------------------------------- |
| Solana | 1 | devnet | 3u8hJUVTA4jH1wYAyUur7FFZVQ8H635K3tSHHF4ssjQ5 |
| Ethereum (Goerli) | 2 | 5 | 0x706abc4E45D419950511e474C7B9Ed348A4a716c |
| Ethereum (Ropsten) | 10001 | 3 | 0x210c5F5e2AF958B4defFe715Dc621b7a3BA888c5 |
| Terra | 3 | bombay-12 | terra1pd65m0q9tl3v8znnz5f5ltsfegyzah7g42cx5v |
| Binance Smart Chain | 4 | 97 | 0x68605AD7b15c732a30b1BbC62BE8F2A509D74b4D |
| Polygon (Mumbai) | 5 | 80001 | 0x0CBE91CF822c73C2315FB05100C2F714765d5c20 |
| Avalanche (Fuji) | 6 | 43113 | 0x7bbcE28e64B3F8b84d876Ab298393c38ad7aac4C |
| Oasis (Emerald Testnet) | 7 | 42261 | 0xc1C338397ffA53a2Eb12A7038b4eeb34791F8aCb |
| Algorand (Testnet) | 8 | | 86525623 |
| Aurora | 9 | 1313161555 | 0xBd07292de7b505a4E803CEe286184f7Acf908F5e |
| Fantom | 10 | 4002 | 0x1BB3B4119b7BA9dfad76B0545fb3F531383c3bB7 |
| Karura | 11 | 686 | 0xE4eacc10990ba3308DdCC72d985f2a27D20c7d03 |
| Acala | 12 | 787 | 0x4377B49d559c0a9466477195C6AdC3D433e265c0 |
| Klaytn | 13 | 1001 | 0x1830CC6eE66c84D2F177B94D544967c774E624cA |
| Celo | 14 | 44787 | 0x88505117CA88e7dd2eC6EA1E13f0948db2D50D56 |
| NEAR | 15 | | wormhole.wormhole.testnet |
| Terra | 18 | pisco-1 | terra19nv3xr5lrmmr7egvrk2kqgw4kcn43xrtd5g0mpgwwvhetusk4k7s66jyv0 |
| Injective | 19 | testnet | inj1xx3aupmgv3ce537c0yce8zzd3sz567syuyedpg |
| Aptos | 22 | | 0x1b1752e26b65fc24971ee5ec9718d2ccdd36bf20486a10b2973ea6dedc6cd197 |
### Token Bridge
| Chain Name | Wormhole Chain ID | Network ID | Address |
| :---------------------- | :---------------- | :--------- | :------------------------------------------- |
| Solana | 1 | devnet | DZnkkTmCiFWfYTfT41X3Rd1kDgozqzxWaHqsw6W4x2oe |
| Ethereum (Goerli) | 2 | 5 | 0xF890982f9310df57d00f659cf4fd87e65adEd8d7 |
| Ethereum (Ropsten) | 10001 | 3 | 0xF174F9A837536C449321df1Ca093Bb96948D5386 |
| Terra | 3 | bombay-12 | terra1pseddrv0yfsn76u4zxrjmtf45kdlmalswdv39a |
| Binance Smart Chain | 4 | 97 | 0x9dcF9D205C9De35334D646BeE44b2D2859712A09 |
| Polygon (Mumbai) | 5 | 80001 | 0x377D55a7928c046E18eEbb61977e714d2a76472a |
| Avalanche (Fuji) | 6 | 43113 | 0x61E44E506Ca5659E6c0bba9b678586fA2d729756 |
| Oasis (Emerald Testnet) | 7 | 42261 | 0x88d8004A9BdbfD9D28090A02010C19897a29605c |
| Algorand (Testnet) | 8 | | 86525641 |
| Aurora | 9 | 1313161555 | 0xD05eD3ad637b890D68a854d607eEAF11aF456fba |
| Fantom | 10 | 4002 | 0x599CEa2204B4FaECd584Ab1F2b6aCA137a0afbE8 |
| Karura | 11 | 686 | 0xd11De1f930eA1F7Dd0290Fe3a2e35b9C91AEFb37 |
| Acala | 12 | 787 | 0xebA00cbe08992EdD08ed7793E07ad6063c807004 |
| Klaytn | 13 | 1001 | 0xC7A13BE098720840dEa132D860fDfa030884b09A |
| Celo | 14 | 44787 | 0x05ca6037eC51F8b712eD2E6Fa72219FEaE74E153 |
| Celo | 15 | | token.wormhole.testnet |
| Injective | 19 | testnet | inj1q0e70vhrv063eah90mu97sazhywmeegp7myvnh |
| Chain Name | Wormhole Chain ID | Network ID | Address |
| :---------------------- | :---------------- | :--------- | :----------------------------------------------------------------- |
| Solana | 1 | devnet | DZnkkTmCiFWfYTfT41X3Rd1kDgozqzxWaHqsw6W4x2oe |
| Ethereum (Goerli) | 2 | 5 | 0xF890982f9310df57d00f659cf4fd87e65adEd8d7 |
| Ethereum (Ropsten) | 10001 | 3 | 0xF174F9A837536C449321df1Ca093Bb96948D5386 |
| Terra | 3 | bombay-12 | terra1pseddrv0yfsn76u4zxrjmtf45kdlmalswdv39a |
| Binance Smart Chain | 4 | 97 | 0x9dcF9D205C9De35334D646BeE44b2D2859712A09 |
| Polygon (Mumbai) | 5 | 80001 | 0x377D55a7928c046E18eEbb61977e714d2a76472a |
| Avalanche (Fuji) | 6 | 43113 | 0x61E44E506Ca5659E6c0bba9b678586fA2d729756 |
| Oasis (Emerald Testnet) | 7 | 42261 | 0x88d8004A9BdbfD9D28090A02010C19897a29605c |
| Algorand (Testnet) | 8 | | 86525641 |
| Aurora | 9 | 1313161555 | 0xD05eD3ad637b890D68a854d607eEAF11aF456fba |
| Fantom | 10 | 4002 | 0x599CEa2204B4FaECd584Ab1F2b6aCA137a0afbE8 |
| Karura | 11 | 686 | 0xd11De1f930eA1F7Dd0290Fe3a2e35b9C91AEFb37 |
| Acala | 12 | 787 | 0xebA00cbe08992EdD08ed7793E07ad6063c807004 |
| Klaytn | 13 | 1001 | 0xC7A13BE098720840dEa132D860fDfa030884b09A |
| Celo | 14 | 44787 | 0x05ca6037eC51F8b712eD2E6Fa72219FEaE74E153 |
| Near | 15 | | token.wormhole.testnet |
| Injective | 19 | testnet | inj1q0e70vhrv063eah90mu97sazhywmeegp7myvnh |
| Aptos | 22 | | 0xdd0a2618dc5564ccf38d0eca7877198fef51157fea74a6bc2e5e40b52c2a0a08 |
### NFT Bridge
@ -127,3 +129,67 @@ The [constants](https://github.com/wormhole-foundation/wormhole/blob/dev.v2/sdk/
| Acala | 12 | 787 | 0x96f1335e0AcAB3cfd9899B30b2374e25a2148a6E |
| Klaytn | 13 | 1001 | 0x94c994fC51c13101062958b567e743f1a04432dE |
| Celo | 14 | 44787 | 0xaCD8190F647a31E56A656748bC30F69259f245Db |
## Devnet / Tilt
### Core Bridge
| Chain Name | Wormhole Chain ID | Network ID | Address |
| :---------------------- | :---------------- | :--------- | :--------------------------------------------------------------- |
| Solana | 1 | | Bridge1p5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o |
| Ethereum | 2 | | 0xC89Ce4735882C9F0f0FE26686c53074E09B0D550 |
| Terra | 3 | | terra18vd8fpwxzck93qlwghaj6arh4p7c5n896xzem5 |
| Binance Smart Chain | 4 | | 0xC89Ce4735882C9F0f0FE26686c53074E09B0D550 |
| Algorand | 8 | | 4 |
| NEAR | 15 | | wormhole.test.near |
| Terra2 | 18 | | terra14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9ssrc8au |
| Aptos | 22 | | |
| Wormholechain | 3104 | | wormhole1ap5vgur5zlgys8whugfegnn43emka567dtq0jl |
### Token Bridge
| Chain Name | Wormhole Chain ID | Network ID | Address |
| :---------------------- | :---------------- | :--------- | :--------------------------------------------------------------- |
| Solana | 1 | | B6RHG3mfcckmrYN1UhmJzyS1XX3fZKbkeUcpJe9Sy3FE |
| Ethereum | 2 | | 0x0290FB167208Af455bB137780163b7B7a9a10C16 |
| Terra | 3 | | terra10pyejy66429refv3g35g2t7am0was7ya7kz2a4 |
| Binance Smart Chain | 4 | | 0x0290FB167208Af455bB137780163b7B7a9a10C16 |
| Algorand | 8 | | 6 |
| NEAR | 15 | | token.test.near |
| Terra2 | 18 | | terra1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrquka9l6 |
| Aptos | 22 | | |
| Wormholechain | 3104 | | wormhole1zugu6cajc4z7ue29g9wnes9a5ep9cs7yu7rn3z |
### NFT Bridge
| Chain Name | Wormhole Chain ID | Network ID | Address |
| :---------------------- | :---------------- | :--------- | :--------------------------------------------------------------- |
| Solana | 1 | | NFTWqJR8YnRVqPDvTJrYuLrQDitTG5AScqbeghi4zSA |
| Ethereum | 2 | | 0x26b4afb60d6c903165150c6f0aa14f8016be4aec |
| Terra | 3 | | terra1plju286nnfj3z54wgcggd4enwaa9fgf5kgrgzl |
| Binance Smart Chain | 4 | | 0x26b4afb60d6c903165150c6f0aa14f8016be4aec |
## Blockchain Finality Recommendations
The goal of Wormhole is to provide high confidence that only _finalized_ messages are observed and attested. Different chains use different consensus mechanisms and so there are different finality assumptions with each one.
Below is a table of suggested finality recommendations for each of the chains supported by the Wormhole ecosystem to have the highest confidence of finality.
However, these are just suggestions and developers are free to define their own finality windows for their applications. Ultimately, the tradeoff is between speed and security.
| Chain Name | Wormhole Chain ID | Suggested Number of Block Confirmations |
| :------------------ | :---------------- | :---------------------------------------- |
| Solana | 1 | 32 |
| Ethereum | 2 | 15 |
| Terra Classic | 3 | Instant |
| Binance Smart Chain | 4 | 15 |
| Polygon | 5 | 512 |
| Avalanche (C-Chain) | 6 | 1 |
| Oasis (Emerald) | 7 | 1 |
| Aurora | 9 | 1 |
| Fantom | 10 | 1 |
| Karura | 11 | 1 |
| Acala | 12 | 1 |
| Klaytn | 13 | 1 |
| Celo | 14 | 1 |
| Terra | 18 | Instant |

View File

@ -1,8 +0,0 @@
# Repository
The Wormhole core repository can be found at [https://github.com/certusone/wormhole](https://github.com/certusone/wormhole).
# Design Documents
Wormhole's component design specifications can be found at [https://github.com/certusone/wormhole/tree/dev.v2/whitepapers](https://github.com/certusone/wormhole/tree/dev.v2/whitepapers). These outline the reasoning behind design decisions with added technical depth.

View File

@ -1,22 +1,21 @@
# Glossary
In some instances, Wormhole uses general terms fo decentralized, cross-chain elements as branded verbiage. In most casese, the definition of the general term does not differ from Wormhole's definition though Wormhole's definitions may be more narrow than general interpretations.
**xChain** - Term that referrs to the full range of cross-blockchain interoperability.
[**xData**](../dapps/3_xdataxassets.md) - Data that exists in a layer outside of Layer 1 blockchains, which is accessible by all chains.
[**xAssets**](../dapps/3_xdataxassets.md) - Chain-and-path agnostic token that exists on a layer outside the blockchain ecosystem, which can be used to conduct transactions on any blockchain. There are currently two implemented modules: (1) [Token Bridge Module](../technical/evm/xassetLayer.md) and (2) [NFT Bridge Module](../technical/evm/nftLayer.md)
[**xDapp**](../dapps/4_whatIsanXdapp.md) - Decentralized application that enables users to create and/or use xData.
**Guardian** - One of the 19 validators in the Guardian Network that Contributes to the VAA multisig.
[**Guardian Network**](../wormhole/5_guardianNetwork.md) - Validators that exist in their own p2p network that serve as Wormhole's oracle by observing activity on-chain and generating signed messages attesting to that activity.
[**Relayer**](../wormhole/6_relayers.md) - Any process which delivers VAAs to a destination.
**Guardian** - One of the 19 validators in the Guardian Network that Contributes to the VAA multisig.
[**VAA**](../wormhole/4_vaa.md) - Verifiable Action Approvals (VAAs) are the key piece of data in the Wormhole ecosystem, containing the messages emitted by xDapps along with information such as what contract emitted the message. The VAAs are signed by the Guardians and need 13/19 signatures to be considered authentic.
[**Wormchain**](../wormhole/8_wormchain.md) - A purpose-built cosmos blockchain which aids the Guardian Network and allows for formal interaction with the Guardians.
[**Wormchain**](../wormhole/8_wormchain.md) - A purpose-built cosmos blockchain which aids the Guardian Network and allows for formal interaction with the Guardians.
[**xAssets**](../dapps/3_xdataxassets.md) - Chain-and-path agnostic token that exists on a layer outside the blockchain ecosystem, which can be used to conduct transactions on any blockchain. There are currently two implemented modules: (1) [Token Bridge Module](../technical/evm/xassetLayer.md) and (2) [NFT Bridge Module](../technical/evm/nftLayer.md)
**xChain** - Term that referrs to the full range of cross-blockchain interoperability.
[**xDapp**](../dapps/4_whatIsanXdapp.md) - Decentralized application that enables users to create and/or use xData.
[**xData**](../dapps/3_xdataxassets.md) - Data that exists in a layer outside of Layer 1 blockchains, which is accessible by all chains.

10
src/reference/overview.md Normal file
View File

@ -0,0 +1,10 @@
# Other Resources
Here is a collection of other resources and reference sources which you're likely to find helpful.
- [Glossary & Terms](./glossary.md)
- [Tools & Helpful Links](./tools.md)
- [Github](./github.md)
- [Contract Addresses & Environment Information](./contracts.md)
- [RPC Info](./rpcnodes.md)
- [Block Finality Suggestions](./finality.md)

View File

@ -1,17 +0,0 @@
# Tools
There are a variety of tools in the Wormhole ecosystem that can help you develop xDapps. Here are a few of the most notable:
### Testnet
Wormhole has deployed Core Bridge, Token Bridge and NFT Bridge contracts on various testnets of the chains connected by Wormhole. You can see the deployed addresses at [./contracts.md](./contracts.md). There's only a single Guardian that oversees the testnets, so you might get a higher rate of missed VAAs than you would on mainnet.
### Wormhole Explorer
Wormhole Explorer is a tool that will help you parse VAAs after they've been picked up the Guardian network. It's available at [https://wormholenetwork.com/en/explorer](https://wormholenetwork.com/en/explorer).
### Testnet Bridge UI
If you'd like to try out Portal Bridge on testnet, there's a UI you can use to attest and transfer tokens for testnet, hosted at [https://certusone.github.io/wormhole](https://certusone.github.io/wormhole).
### Tilt
Tilt is a Kubernetes-based tool that runs a copy of every chain along side a Guardian node to create a simulated testing environment. To set it up and test against it, start at [../development/tilt/overview.md](../development/tilt/overview.md).
### Wormhole SDK
The SDK is a set of Javascript tools to help you do Token Bridge transfers, plus fetch and submit VAAs from one chain to another. You can install it via NPM at [https://www.npmjs.com/package/@certusone/wormhole-sdk](https://www.npmjs.com/package/@certusone/wormhole-sdk).

View File

@ -0,0 +1,31 @@
# Useful Links
Below are a variety of useful links to tools and information in the Wormhole ecosystem that can help you develop xDapps.
### Design Documents
Wormhole's component design specifications can be found [here](https://github.com/certusone/wormhole/tree/dev.v2/whitepapers). These outline the reasoning behind design decisions with added technical depth.
### Testnet
Wormhole has deployed Core Bridge, Token Bridge and NFT Bridge contracts on various testnets of the chains connected by Wormhole. You can see the deployed addresses [here](./contracts.md). There's only a single Guardian that oversees the testnets, so you might get a higher rate of missed VAAs than you would on mainnet.
### Testnet Bridge UI
If you'd like to try out bridging tokens on testnet, there's a UI you can use to attest and transfer tokens for testnet, hosted [here](https://wormhole-foundation.github.io/example-token-bridge-ui/#/transfer).
### Tilt
Tilt is a Kubernetes-based tool that runs a copy of every chain along side a Guardian node to create a simulated testing environment. To set it up and test against it, start [here](../development/tilt/overview.md).
### Wormhole Core Repository
The Wormhole core repository can be found at [https://github.com/wormhole-foundation/wormhole](https://github.com/wormhole-foundation/wormhole).
### Wormhole Explorer
[Wormhole Explorer](https://wormholenetwork.com/en/explorer) is a tool that will help you parse VAAs after they've been picked up the Guardian network.
### Wormhole SDK
The SDK is a set of Javascript tools to help you do Token Bridge transfers, plus fetch and submit VAAs from one chain to another. You can install it via [NPM](https://www.npmjs.com/package/@certusone/wormhole-sdk).

View File

@ -0,0 +1,9 @@
# Algorand
The implementation contracts for Wormhole's official Algorand integration can be found [here](https://github.com/wormhole-foundation/wormhole/tree/dev.v2/algorand).
An overview of the contracts and how they work is outlined [here](https://github.com/wormhole-foundation/wormhole/blob/dev.v2/algorand/README.md).
The deployed contract addresses can be found on the [Contracts page](../../reference/contracts.md).
The Algorand integration is also fully supported by the [Wormhole Typescript SDK](https://github.com/wormhole-foundation/wormhole/tree/dev.v2/sdk/js).

View File

@ -0,0 +1,9 @@
# Aptos
Aptos is currently only supported in testnet.
The official Wormhole integration can be found [here](https://github.com/wormhole-foundation/wormhole/tree/aptos/integration).
Information for how to integrate with these contracts can be found [here](https://github.com/wormhole-foundation/wormhole/tree/aptos/integration/aptos/README.md).
The deployed contract addresses can be found on the [Contracts page](../../reference/contracts.md).

View File

@ -0,0 +1,9 @@
# Cosmos
The implementation contracts for Wormhole's official Cosmos integration can be found [here](https://github.com/wormhole-foundation/wormhole/tree/dev.v2/cosmwasm).
The deployed contract addresses can be found on the [Contracts page](../../reference/contracts.md).
Cosmos is a rust-based programming environment. You'll likely find the [Wormhole Rust SDK](https://github.com/wormhole-foundation/wormhole/tree/dev.v2/sdk/rust) useful.
The Cosmos integration is also fully supported by the [Wormhole Typescript SDK](https://github.com/wormhole-foundation/wormhole/tree/dev.v2/sdk/js).

View File

@ -6,14 +6,18 @@ However, as you get deeper into cross-chain development, you'll likely find your
### What components do I need now? What components will I need in the future?
- You may be able to get a lot done with just an EVM chain and a Guardian. However, as your application gets more sophisticated, components like relayers, frontends, automated tests, databases, explorers, and other blockchains are likely to get added in to the environment.
- You may be able to get a lot done with just an EVM chain and a Guardian. However, as your application gets more sophisticated, components like relayers, frontends, automated tests, databases, explorers, and other blockchains are likely to get added into the environment.
### What are my dependencies?
- If your smart contracts have no dependencies, it may be possible for you to develop in a vacuum.
- If your smart contracts does have dependencies, there are several options that range from deploying your dependencies in Tilt or use something like [Foundry](https://github.com/foundry-rs/foundry) to simulate an existing testnet or mainnet in your local devnet to working to working directly in testnet alongside other teams.
- If your smart contracts does have dependencies, there are several options that range from deploying your dependencies in [Tilt](./tilt.md) to simulating an existing testnet/mainnet in [Foundry](https://github.com/foundry-rs/foundry) to working directly in [testnet](./testnet.md) alongside other teams.
### How am I going to collaborate?
- You should consider how your teammates or collaborators are going to work in this environment from the start. There are some basic considerations like "how will they access it", but also some subtler points such as ensuring that contracts will deploy deterministically and that automated tests can be trusted to run reliably. The two paths to accomplish this are to use a public environment (testnet), or to ensure the local environment is well controlled (like tilt).
---
In the following sections we'll describe three different development environments that are available -- Tilt, Wormhole Local Validator, and Testnet -- in more details as well as some additional tools that should be helpful in your xDapp development.

View File

@ -2,21 +2,27 @@
Wormhole testnet is spread across many of the most popular testnet blockchains.
### Is Testnet right for you?
The primary reason to use Wormhole testnet is to simplify the management of your dependent contracts. This will vary from blockchain to blockchain.
For example, some blockchain ecosystems have the standard that their contracts are closed-source, and there are no tools to fork mainnet. Other ecosystems, such as EVM, have tools like [foundry](https://github.com/foundry-rs/foundry), which allow you to hardfork the mainnet ecosystem into a local development node.
In short, testnet tends to be the correct choice only when you have contract dependencies, and those dependencies are difficult to get working in a local environment. In most other cases, testnet tends to be more work than it's worth.
If you elect to use testnet, the Wormhole contracts addresses can be found in the [Reference](../../reference/contracts.md) section.
Here's a succinct list of the pros and cons of the environment, so you can decide if it's the right fit for you.
Pros:
**Pros**
- Many other projects deploy their contracts to testnet.
- In ecosystems without extensive local tooling, this may be the preferred development environment.
Cons:
**Cons**
- Many testnets are somewhat unstable and have outages or partitioning events.
- Wormhole Testnet sometimes misses VAAs due to testnet instabilities.
- Testnet tokens are often difficult to acquire.
## Using Testnet
If you elect to use testnet, the Wormhole contracts addresses can be found in the [Contracts](../../reference/contracts.md) page.

View File

@ -1,10 +1,10 @@
# Tilt (Devnet)
### What is Tilt?
## What is Tilt?
[Tilt](https://tilt.dev/) is part of the official Docker ecosystem. It's a tool which allows developers to easily configure a Kubernetes environment for development.
However, in the context of Wormhole, 'Tilt' usually refers to the development environment used by the [Wormhole Core Repository](https://github.com/wormhole-foundation/wormhole). This environment uses Tilt to stand up docker images for all the tools necessary to build across multiple blockchains, including:
However, in the context of Wormhole, 'Tilt' refers to the development environment used by the [Wormhole Core Repository](https://github.com/wormhole-foundation/wormhole). This environment stands up docker images for all the tools necessary to build across multiple blockchains, including:
- All the Wormhole supported blockchains / ecosystems
- A Guardian Node
@ -12,30 +12,32 @@ However, in the context of Wormhole, 'Tilt' usually refers to the development en
- Databases, Redis
- Utility frontends
The 'Tilt' environment (also referred to as Wormhole 'Devnet') is meant to provide an entire cross-chain development stack right out of the box.
The 'Tilt' environment is meant to provide an entire cross-chain development stack right out of the box.
_Note: Tilt is often referred to as 'Devnet' in the Wormhole ecosystem so any information that is labelled as 'devnet' also applies to Tilt._
### Is Tilt Right for You?
Tilt is generally a good starting point for most developers. Here's a succinct list of the pros and cons of the environment, so you can decide if it's the right fit for you.
### Pros
**Pros**
- Out-of-the-box support for the many components needed to develop across the heterogenous blockchain space.
- Out-of-the-box support for the many components needed to develop across the heterogenous blockchain spaces.
- Consistent development environment, where contracts deploy deterministically and everything is already linked up.
- Ability to easily enable/disable components as needed.
- Regularly updated as new components join the Wormhole ecosystem.
### Cons
**Cons**
- Relatively high system requirements. This can be mitigated by disabling components.
- Most blockchains are 'fresh' and have no contracts by default. Thus, you may have to deploy your own dependencies, or alter the default tilt configuration.
- Spin-up and rebuild times can be slow. This can result in a slow workflow if you rely on docker rebuilds.
- Relatively high system requirements but this can be mitigated by disabling components.
- Most blockchains are 'fresh' and have no contracts by default. Thus, if your contracts have any dependencies, you may have to deploy them yourself or alter the default tilt configuration.
- Spin-up and rebuild times can be slow which can result in a slow workflow.
# Setting up Tilt
## Setting up Tilt
Tilt functions best in a UNIX-style environment. For Windows users, using a WSL environment is recommended.
Tilt functions best in a UNIX-style environment. For Windows users, a WSL environment is recommended.
In order to run the Tilt environment, you'll first need to make sure you have [Tilt](https://docs.tilt.dev/install.html) and [Go](https://go.dev/doc/install) installed.
In order to run the Tilt environment, make sure you have [Tilt](https://docs.tilt.dev/install.html) and [Go](https://go.dev/doc/install) installed.
Once you've installed these two dependencies, just clone the Wormhole Core Repository and start Tilt.
@ -47,25 +49,27 @@ cd wormhole
tilt up
```
Be sure to check out the [**Tiltfile**](https://github.com/wormhole-foundation/wormhole/blob/dev.v2/Tiltfile), which has much of the configuration and arguments for the development environment. It's relatively straightforward to enable and disable components. For example, you can disable blockchains by setting them to false at startup
Be sure to check out the [**Tiltfile**](https://github.com/wormhole-foundation/wormhole/blob/dev.v2/Tiltfile), which has much of the configuration and arguments for the development environment. It's relatively straightforward to enable and disable components.
For example, you can disable blockchains by setting them to false at startup
```
tilt up -- --algorand=false --near=false --solana=false terra_classic=false terra2=false
```
# Using Tilt
## Using Tilt
Tilt can pretty much be treated as though it's an external environment that you can easily spin up and tear down.
Tilt can pretty much be treated as an external environment / testnet that you can easily spin up and tear down.
If you've followed the standard setup, all your resources will be bound to various ports on localhost. To see all the endpoints which are being hosted in your Tilt environment, you should check the Tilt dashboard, located at [http://localhost:10350/overview](http://localhost:10350/overview).
Tilt is alos referred to as 'Devnet' in the Wormhole ecosystem, so anywhere you see information labeled as 'Devnet', you can apply it to Tilt.
All the deployed contract addresses can be found under the 'Devnet / Tilt' section of [contracts](../../reference/contracts.md).
For example, you can find all the deployed contract addresses in the 'Devnet' [constants](https://github.com/wormhole-foundation/wormhole/blob/dev.v2/sdk/js/src/utils/consts.ts) of the Wormhole Typescript SDK.
Useful information pertaining to funded wallets & private keys can also be found in the [devnet.md](https://github.com/wormhole-foundation/wormhole/blob/dev.v2/docs/devnet.md) file of the docs.
Useful information pertaining to funded wallets & useful private keys can also be found in the [devnet.md](https://github.com/wormhole-foundation/wormhole/blob/dev.v2/docs/devnet.md) file of the docs.
Additional helpful resources can be found in the [Tooling](./tooling.md) page.
From here, Tilt is quite similar to using Testnet, and you should look at the [Tooling](./tooling.md) page for additional resources.
## Shutting down Tilt
In order to shut down Tilt, simply run

View File

@ -6,7 +6,9 @@ Tilt, Kubernetes, and Docker may be new tools for developers entering the Wormho
## Prerequisites
Having `homebrew` on your system makes the installation really straightforward. You can grab it with:
Install [Homebrew](https://brew.sh) if you don't already have it.
You can grab it with:
```sh
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
@ -38,9 +40,6 @@ brew install tilt
```sh
git clone --branch dev.v2 https://github.com/wormhole-foundation/wormhole.git
```
```sh
cd wormhole/
tilt up
```

View File

@ -4,17 +4,17 @@
[Wormhole Local Validator](https://github.com/wormhole-foundation/xdapp-book/tree/main/projects/wormhole-local-validator) is meant to be the simplest custom environment. It consists only of a dockerized Guardian image, and some utility tooling to aid with contract management. This allows you to set it up with any blockchain you'd like.
## Is WLV Right for You?
### Is WLV Right for You?
Here's a succinct list of the pros and cons of the environment, so you can decide if it's the right fit for you.
### Pros
**Pros**
- Lightweight, low system resource demand.
- Fast iteration times.
- Can be added into an existing blockchain development setup.
### Cons
**Cons**
- You may end up reinventing the tilt/testnet environment as you add more components.
@ -30,4 +30,4 @@ Further information can be found in the project's [README](https://github.com/wo
Q: Anvil isn't working
- While Foundry's 'forge' tool is the generally recommended tool for EVM contract compilation, anvil isn't currently compatible with guardiand. Anvil reports block headers in a way which is non-compliant with go-ethereum, which means the guardian node can't correctly read anvil headers.
- While Foundry's 'forge' tool is the generally recommended tool for EVM contract compilation, Anvil isn't currently compatible with guardiand. Anvil reports block headers in a way which is non-compliant with go-ethereum, which means the guardian node can't correctly read anvil headers.

View File

@ -120,14 +120,18 @@ function receiveVAA(bytes32 memory batchVAA) public {
// Headless VAAs are verifiable by parseAndVerifyVM.
(IWormhole.VM2 memory vm2, bool valid, string memory reason) =
core_bridge.parseAndVerifyBatchVM(batchVAA, true)
core_bridge.parseAndVerifyBatchVM(batchVAA, true);
// I know from sendMyMessage that the first VAA is a token bridge VAA,
// so let's hand that off to the token bridge module.
bytes vaaData = token_bridge.completeTransferWithPayload(vm2.payloads[0])
bytes vaaData = token_bridge.completeTransferWithPayload(vm2.payloads[0]);
// The second VAA is my message, let's hand that off to my module.
processMyMessage(vm2.payloads[1])
processMyMessage(vm2.payloads[1]);
// Lastly, uncache the headless VAAs from the core bridge.
// This refunds a significant amount of gas.
core_bridge.clearBatchCache(vm2.hashes);
}
```

View File

@ -6,7 +6,7 @@ Messages in Wormhole take the form of a Verified Action Approval (VAA) and both
## Configuring the Interface
[Here](https://github.com/wormhole-foundation/wormhole/blob/dev.v2/ethereum/contracts/interfaces/IWormhole.sol) is the interface for applications to interact with Wormhole's Core Contract to publish VAAs or verify and parse a received VAAs.
[Here](https://github.com/wormhole-foundation/wormhole/blob/dev.v2/ethereum/contracts/interfaces) is the interface for applications to interact with Wormhole's Core Contract to publish VAAs or verify and parse a received VAAs.
Instantiating the interface will depend on the contract address of your development ecosystem and blockchain.
@ -24,8 +24,9 @@ The Wormhole Core Layer effectively only has two important interactions -- (1) e
### Emitting a VAA
There are two forms that VAAs can be emitted within Wormhole:
- Single VAA: all messages will be emitted in this format
- Batch VAA: messages that are generated from the same transaction will be emitted in this format. This feature was developed to provide an easier paradigm for composability and better gas efficiency for more involved cross-chain activity.
- Batch VAA: messages that are generated from the same transaction will be emitted in this format. This feature was developed to provide an easier paradigm for composability and better gas efficiency for more involved cross-chain activity.
To emit a VAA, always use `publishMessage` which takes in the following arguments:
@ -34,24 +35,25 @@ To emit a VAA, always use `publishMessage` which takes in the following argument
- How Batch VAAs are generated based on a message's `nonce` is described below.
2. `Consistency` (uint8): the number of blocks that Guardians will wait before signing a message
- Each blockchain has different finality periods. In general, higher consistencies mean more security against blockchain reorgs.
- [Here]() are the consistency levels by blockchain that are used by the xAsset layer to have a high level of guarantee against reorgs.
- [Here](../../reference/contracts.md) are the consistency levels by blockchain that are used by the xAsset layer to have a high level of guarantee against reorgs.
3. `Payload` (bytes[]): raw bytes to emit
- It is up to the emitting contract to properly define this arbitrary set of bytes.
`publishMessage` will output a `sequence` (uint64) that is used in conjunction with `emitterChainID` and `emitterAddress` to retrive the generated VAA from the Guardian Network.
> How Batch VAAs are generated
>
> There are two mechanisms that allow messages to be Batched together that represent a base and more advanced level of compsability.
>
>
> There are two mechanisms that allow messages to be Batched together that represent a base and more advanced level of composability.
>
> 1. All messages originating from the same transaction will be batched together.
> 2. Messages that originate from the same transaction and are assigned the same nonce are additionally batched together.
>
> _Note: Single VAAs will always be emitted for each message within a transaction, regardless of if a message is included in a batch or not._
>
> Here is an example of how messages generated from the same transaction may be batched together:
>
>
> A transaction X that generates 6 messages [A, B, C, D, E, F] that are assigned `nonce` [1, 2, 2, 3, 3, 4] respectively will generate the following VAAs:
>
> - (1) full transaction batch VAA
> - [A, B, C, D, E, F]
> - (2) smaller batch VAA
@ -65,7 +67,6 @@ To emit a VAA, always use `publishMessage` which takes in the following argument
> - [E]
> - [F]
### Parsing and Verifying a VAA
Parsing and Verifying a VAA will depend on the type of VAA that your application expects: a Single VAA or a Batch VAA.
@ -81,18 +82,9 @@ To properly parse and verify a single VAA, always use `parseAndVerifyVM` which t
2. `valid` (bool): Boolean that reflects whether or not the VAA was properly signed by the Guardian Network
3. `reason` (string): Explanatory error message if a VAA is invalid, or an empty string if it is valid.
<!--
TODO
everything about this
**Batch VAA**
To properly parse and verify a batch VAA, always use `parseAndVerifyBatchVM` which takes in two arguments: `encodedVM` (bytes) and `cache` (bool).
Batch VAAs are designed so that relayers can choose to submit any subset of the observations batched together. It is the receiving contract's responsiblity to verify that all VAAs contained in a batch are submitted.
In most scenarios, you'll want to set `cache` equal to true.
---
Code recommendation, write the code which expects to receive a VAA to utilize parseAndVerifyVM(? unsure if this is the correct call). That way, your code will be able to handle either type 1 VAAs (single VAAs), or type 3 VAAs (headless VAAs). This allows it to utilize both single & batch VAAs and dramatically increases composability. \*this only requires like two or three lines of code, so this would be a good candidate for a code example which shows how to properly use batch vaas without breaking composability. Should note that the module code still ALWAYS needs to verify, but should do so with the 'single' message verifying and then expose that function publicly in order to enable composability.
-->
This will return a VM2 object, containing all the 'headless' VAAs contained inside the batch VAA. These headless VAAs can be verified by `parseAndVerifyVM`, which means that modules which verify messages can be agnostic as to if the message was original part of a batch VAA or a single VAA. This is gone into in more depth in the [Best Practices](./bestPractices.md) section.

View File

@ -4,7 +4,7 @@ This section will explain how to properly interact with the NFT Bridge Module in
## Configuring the interface
[Here](https://github.com/wormhole-foundation/wormhole/tree/dev.v2/ethereum/contracts/interfaces) is the interface for applications to interact with Wormhole's NFT Bridge.
[Here](https://github.com/wormhole-foundation/wormhole/tree/wonge97/evm-interface/ethereum/contracts/nft/interfaces) is the interface for applications to interact with Wormhole's NFT Bridge.
<!---
TODO
@ -24,7 +24,7 @@ INFTBridge NFT_bridge = INFTBridge(wormhole_nft_bridge_address);
The Wormhole NFT Bridge only supports tokens compliant with the ERC-721 interface, and functions by creating a 'wrapped NFT' with identical metadata. How this is implemented varies by ecosystem.
**Note**: Unlike xAssets, there is no attestation required for bridging NFTs.
**Note**: Unlike tokens, there is no attestation required for bridging NFTs.
To transfer a NFT, there are three steps:
@ -38,7 +38,7 @@ transferNFT(tokenAddress, tokenID, recipientChain, recipient, nonce);
2. Retrieve the emitted VAA from the Guardian Network. (Usually done by a relayer)
- _Note: NFT Transfer VAAs are retrieved from the Guardian Network by the `emitterChainID`, `emitterAddress`, and `sequence`_
```
```js
const emitterAddr = getEmitterAddressEth(network.NFTBridgeAddress);
const seq = parseSequenceFromLogEth(tx, network.bridgeAddress);
const vaaURL = `${config.wormhole.restAddress}/v1/signed_vaa/${network.wormholeChainId}/${emitterAddr}/${seq}`;

View File

@ -1,9 +1,11 @@
# EVM
**Disclaimer**: This section is written as a guide for how to use Wormhole for experienced EVM developers. If you are new to using the EVM ecosystem, it's recommended for you to get started with a tutorial like [this]().
**Disclaimer**: This section is written as a guide for how to use Wormhole for experienced EVM developers. If you are new to using the EVM ecosystem, it's recommended for you to get started with a tutorial like [this](https://ethereum.org/en/developers/docs/intro-to-ethereum/).
For our purposes, EVM refers to any blockchain in the Wormhole ecosystem that utilizes EVM contracts of Wormhole -- this includes blockchains beyond Ethereum such as Polygon or Avalanche, as well as EVM+ environments such as Acala.
At certain points, it may be easiest to integrate simply by referencing the implementation of the Wormhole contracts. The official implementation for the Wormhole contracts can be found [here](https://github.com/wormhole-foundation/wormhole/tree/dev.v2/ethereum).
### Recommended Tooling for EVM
**Frontend Development**

View File

@ -4,8 +4,7 @@ This section will explain how to properly interact with the Wormhome Token Bridg
## Configuring the interface
[Here]() is the interface for applications to interact with Wormhole's Token Bridge.
//TODO link to file in github so doesn't become stale
[Here](https://github.com/wormhole-foundation/wormhole/tree/wonge97/evm-interface/ethereum/contracts/bridge/interfaces) is the interface for applications to interact with Wormhole's Token Bridge.
Instantiating the interface will depend on your development ecosystem and blockchain. The Wormhole Token Bridge contract address is usually stored in your contract address.
@ -20,9 +19,9 @@ ITokenBridge token_bridge = ITokenBridge(wormhole_token_bridge_address);
Attesting a token from EVM needs to happen once per token. If a token is not attested, it will not be claimable until so. However, there are no restrictions to reattesting a token; doing so will update the metadata.
It is not advised to attest tokens on-chain for most usecases. To attest a token by an off-chain process, you can either do it by hand through one of the Token Bridge UIs (for example [Portal](https://www.portalbridge.com/#/register)) or using the [JS SDK](https://www.npmjs.com/package/@certusone/wormhole-sdk).
It is not advised to attest tokens on-chain for most usecases. To attest a token by an off-chain process, you can either do it by hand through one of the Token Bridge UIs (for example [Portal](https://www.portalbridge.com/#/register)) or using the [Typescript SDK](https://www.npmjs.com/package/@certusone/wormhole-sdk).
_[Here](../../development/portal/evm/attestingToken.md) is an example of how to attest a token using the JS SDK._
_[Here](../../development/portal/evm/attestingToken.md) is an example of how to attest a token using the Typescript SDK._
## Basic Transfer

View File

@ -0,0 +1,9 @@
# NEAR
The implementation contracts for Wormhole's official NEAR integration can be found [here](https://github.com/wormhole-foundation/wormhole/tree/dev.v2/near).
The deployed contract addresses can be found on the [Contracts page](../../reference/contracts.md).
NEAR is a rust-based programming environment. You'll likely find the [Wormhole Rust SDK](https://github.com/wormhole-foundation/wormhole/tree/dev.v2/sdk/rust) useful.
The NEAR integration is also fully supported by the [Wormhole Typescript SDK](https://github.com/wormhole-foundation/wormhole/tree/dev.v2/sdk/js).

View File

@ -0,0 +1,7 @@
# Contract Development
This section should help you get off the ground with contract development in the Wormhole ecosystem.
It is written in a fashion which assumes familiarity with smart contract development in each ecosystem. As such, it doesn't provide information on smart contract basics, and instead focuses on how to properly interact with the provided Wormhole functions.
While the syntax for each programming environment differs, the general structure of the code and best practices tend to be quite similar. You should consider referencing the sections for environments other than the one you're working in, as many of the concepts outlined here are universal to cross-chain development.

View File

@ -0,0 +1,29 @@
# Generic Relayers
The defining characteristic of generic relayers is that they do not have any off-chain components for the xDapp developer. All aspects of this integration are on chain.
The implementation details vary by blockchain, and you should reference the `relayer module` documentation for each ecosystem. The general strategy is the same however.
Developers are responsible for implementing a standardized interface which is part of the API agreement with the generic relayer network. This interface generally looks something like
```
receiveVAA(byte[] batchVAA)
```
This is the entrypoint on your contract which will be called by the relayer.
You are able to request delivery of a VAA via calling the `relayer module` on-chain. As part of the delivery request, you are required to specify and pre-pay a 'future compute' budget, which will designate a limit for how much budget can be spent on the target transaction.
This interface is generally along the lines of:
```
requestDelivery(
targetChain,
targetAddress,
computeBudget,
nonce,
consistencyLevel,
)
```
If the requested delivery either runs out of compute budget or throws an exception, the delivery will fail. In the case of a delivery failure, you're always able to request a second delivery. However, the prepaid fee is not refunded. Thus, it is recommended to always place a top-level try-catch around your entrypoint, and to specify a worst-case computation budget. <!-- TODO mention refunds -->

View File

@ -1,4 +1,5 @@
# Relayer Development
This section will help you get started with specialized relayer development
generic relayers only require on-chain components. If you're using those, everything you need should be encompassed by referencing the relevant 'Relayer Module' sections above.
This chapter will help you with relayer development in the Wormhole ecosystem.
The two broad categorizations of relayers are [Generic Relayers](./genericRelayer.md) and [Specialized Relayers](./specializedRelayers.md).

View File

@ -1 +1,17 @@
# Specialized Relayers
- Link to Plugin relayer codebase
- Recommend plugin relayers as the starting point for anyone developing specialized relayers
- plugin relayers provide a kernel for relayer development. Handles management of all the necessary hotwallets, provides the necessary typescript interfaces for dealing with each ecosystems, and provides an easy integration point to connect to the guardian network
- Follow the instructions provided in the codebase in order to get it running
- to develop a plugin, simply implement the interface provided at [here]
- diagram explaining the flow
- Listener component listens to either incoming REST calls or the guardian network for relevant VAAs,
- When a relevant VAA is detected, your listener code is responsible for producing an action.
- This action is stored in a redis instance
- The executor portion of the interface is responsible for consuming interactions which are provided by the listener.
- The executor is handed an action and is responsible for consuming that action and (optionally) queuing up more actions
- additional configuration info can be found in the README of the codebase.

View File

@ -1,25 +1,9 @@
- Link to Plugin relayer codebase
# Specialized Relayers
- Recommend plugin relayers as the starting point for anyone developing specialized relayers
- plugin relayers provide a kernel for relayer development. Handles management of all the necessary hotwallets, provides the necessary typescript interfaces for dealing with each ecosystems, and provides an easy integration point to connect to the guardian network
Rather than home-rolling a relayer, it's recommended that integrators start from the existing [Spy Relayer](https://github.com/wormhole-foundation/wormhole/tree/dev.v2/relayer/spy_relayer) provided in the Wormhole Core Repository.
- Follow the instructions provided in the codebase in order to get it running
- to develop a plugin, simply implement the interface provided at [here]
- diagram explaining the flow
- Listener component listens to either incoming REST calls or the guardian network for relevant VAAs,
- When a relevant VAA is detected, your listener code is responsible for producing an action.
- This action is stored in a redis instance
- The executor portion of the interface is responsible for consuming interactions which are provided by the listener.
- The executor is handed an action and is responsible for consuming that action and (optionally) queuing up more actions
There's additionally an extensible relayer (called the [Plugin Relayer](https://github.com/wormhole-foundation/wormhole/tree/feat/plugin_relayer/relayer/plugin_relayer)) currently in development.
- additional configuration info can be found in the README of the codebase.
<!-- To aid in the development of relayers, a extensible relayer implementation (called the [plugin relayer]()) has been provided in the Wormhole Core Repository.
# Homerolling a Relayer
If you're totally homerolling a relayer solution, you'll need to interact with the guardian network directly.
link to spydk. Use this to tie directly into the guardian network and receive events. If you're particularly ambitious, you can even join the guardian network as a 'spy' which is the term for a non-validating guardian.
VAAs can also be pulled directly from any public node on the guardian network using REST endpoints. This is a really simple way to grab known VAAs.
- provide the REST endpoints for this
It's recommended that integrators create their own plugin for the plugin relayer, rather than home-roll a relayer themselves. Using the plugin relayer allows integrators to take advantage of the robust hot-wallet and scheduling built into the relayer's kernel, as well as leveraging plugins which are built by other integrators. -->

View File

@ -0,0 +1,9 @@
# Solana
The implementation contracts for Wormhole's official Solana integration can be found [here](https://github.com/wormhole-foundation/wormhole/tree/dev.v2/solana).
The deployed contract addresses can be found on the [Contracts page](../../reference/contracts.md).
Solana is a rust-based programming environment. You'll likely find the [Wormhole Rust SDK](https://github.com/wormhole-foundation/wormhole/tree/dev.v2/sdk/rust) useful.
The Solana integration is also fully supported by the [Wormhole Typescript SDK](https://github.com/wormhole-foundation/wormhole/tree/dev.v2/sdk/js).

View File

@ -0,0 +1,62 @@
# Registering Tokens
Registering tokens with the token bridge can be done from any supported blockchain, and only needs to be done once - globally - per token. This is is typically done via a UI (such as the [Portal UI](portalbridge.com)) rather than done on-chain.
If you need to do it programmatically, you can also use the Typescript SDK to attest a token:
The first step is to create an AttestMeta VAA. We do this by calling `attest()` function from the SDK and passing in the Token Bridge address, and the address of the Token we want to attest.
For example, here is the code to produce an attestation VAA using ethers:
```js
const networkTokenAttestation = await attestFromEth(
network.tokenBridgeAddress, // Token Bridge Address
signer, //Private Key to sign and pay for TX + RPC Endpoint
network.testToken //Token Address
);
```
The attestation transaction will produce a signed VAA. This signed VAA is necessary in order to register the tokens on other chains.
In order to retrieve the VAA, you will need the `emitterAddress` of the Token Bridge and the `sequence` from the logs of the transaction receipt.
With those, you can fetch the VAA from any Guardian REST endpoint. It could take a moment (up to 30 seconds) for the Guardian to see and sign the VAA, so it's a good idea to poll the Guardian every few seconds until the VAA is found.
Here is a relatively compact piece of code which is able to fetch **any** VAA, given an emitter address and sequence number.
```js
const emitterAddr = getEmitterAddressEth(network.tokenBridgeAddress);
const seq = parseSequenceFromLogEth(
networkTokenAttestation,
network.bridgeAddress
);
const vaaURL = `${config.wormhole.restAddress}/v1/signed_vaa/${network.wormholeChainId}/${emitterAddr}/${seq}`;
console.log("Searching for: ", vaaURL);
let vaaBytes = await (await fetch(vaaURL)).json();
while (!vaaBytes.vaaBytes) {
console.log("VAA not found, retrying in 5s!");
await new Promise((r) => setTimeout(r, 5000)); //Timeout to let Guardiand pick up log and have VAA ready
vaaBytes = await (await fetch(vaaURL)).json();
}
```
Lastly, we submit the VAA onto the target chain to create a wrapped version of the token. This is accomplished by calling `createWrapped()`.
You can get the new wrapped token address by calling the `wrappedAsset()` function of the TokenBridge.
Here is how this can be accomplished using Ethers:
```js
await targetTokenBridge.createWrapped(
Buffer.from(vaaBytes.vaaBytes, "base64"),
{
gasLimit: 2000000,
}
);
await new Promise((r) => setTimeout(r, 5000)); //Time out to let block propogate
const wrappedTokenAddress = await targetTokenBridge.wrappedAsset(
network.wormholeChainId,
Buffer.from(tryNativeToHexString(network.testToken, "ethereum"), "hex")
);
console.log("Wrapped token created at: ", wrappedTokenAddress);
```

View File

@ -0,0 +1,109 @@
# Cross-Ecosystem Token Transfer
A defining feature of cross chain apps (xDapps) is the ability to move tokens from one chain to another, even if those blockchains have radically different virtual machine models.
To demonstrate, lets do a simple programmatic transfer from Ethereum to Solana.
First, determine the address on Solana where we're sending the tokens. Unlike EVM chains where the wallet address is used, we need to send the tokens to the recipient's associated token account for that token. We'll use a couple helper functions from the Wormhole Typescript SDK to make this easier.
```ts
import {
Token,
ASSOCIATED_TOKEN_PROGRAM_ID,
TOKEN_PROGRAM_ID,
} from "@solana/spl-token";
import {
getForeignAssetSolana,
hexToUint8Array,
nativeToHexString,
CHAIN_ID_ETH,
} from "@certusone/wormhole-sdk";
const SOLANA_TOKEN_BRIDGE_ADDRESS =
"wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb";
// determine destination address - an associated token account
const solanaMintKey = new PublicKey(
(await getForeignAssetSolana(
connection,
SOLANA_TOKEN_BRIDGE_ADDRESS,
CHAIN_ID_ETH,
hexToUint8Array(nativeToHexString(tokenAddress, CHAIN_ID_ETH) || "")
)) || ""
);
const recipientAddress = await Token.getAssociatedTokenAddress(
ASSOCIATED_TOKEN_PROGRAM_ID,
TOKEN_PROGRAM_ID,
solanaMintKey,
recipientWalletAddress
);
```
After we have the receipt token account on Solana, it's time to submit the transfer message on Ethereum. This will output a log that contains a sequence number (a unique number for the message) and an emitter address (the ETH Token Bridge Address in Wormhole format). The sequence number and emitter address will be used to fetch the VAA after its been signed by Guardians.
```ts
import {
trasnferFromEth,
parseSequenceFromLogEth,
getEmitterAddressEth,
CHAIN_ID_SOLANA,
} from "@certusone/wormhole-sdk";
const ETH_TOKEN_BRIDGE_ADDRESS = "0x3ee18B2214AFF97000D974cf647E7C347E8fa585";
// Submit transaction - results in a Wormhole message being published
const receipt = await transferFromEth(
ETH_TOKEN_BRIDGE_ADDRESS,
signer,
tokenAddress,
amount,
CHAIN_ID_SOLANA,
recipientAddress
);
// Get the sequence number and emitter address required to fetch the signedVAA of our message
const sequence = parseSequenceFromLogEth(receipt, ETH_BRIDGE_ADDRESS);
const emitterAddress = getEmitterAddressEth(ETH_TOKEN_BRIDGE_ADDRESS);
```
Once the Guardians have signed the token bridge VAA, it needs to be retrieved from the Guardian Network. This time we'll use the Guardian GRPC endpoint, though the REST endpoint used in previous sections works as well.
```ts
import { getSignedVAA } from "@certusone/wormhole-sdk";
// Fetch the signedVAA from the Wormhole Network (this may require retries while you wait for confirmation)
const { signedVAA } = await getSignedVAA(
WORMHOLE_RPC_HOST,
CHAIN_ID_ETH,
emitterAddress,
sequence
);
```
Now, we post the VAA to Solana in order to mint the wrapped tokens. Because of the compute limit on Solana, we split the signature verification and token claim into steps. To do that, verify all the signatures and create a claim account for the token.
```ts
const SOL_BRIDGE_ADDRESS = "worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth";
await postVaaSolana(
connection, // Solana Mainnet Connection
wallet, //Solana Wallet Signer
SOL_BRIDGE_ADDRESS,
payerAddress,
signedVAA
);
```
Finally, claim the tokens:
```ts
const transaction = await redeemOnSolana(
connection,
SOL_BRIDGE_ADDRESS,
SOL_TOKEN_BRIDGE_ADDRESS,
payerAddress,
signedVAA,
isSolanaNative,
mintAddress
);
const signed = await wallet.signTransaction(transaction);
const txid = await connection.sendRawTransaction(signed.serialize());
await connection.confirmTransaction(txid);
```

View File

@ -0,0 +1,13 @@
# Wormhole Typescript SDK
For applications that only need to interact with the Core and Token Bridge contracts off-chain, there is a Wormhole Typescript SDK provided.
It can be installed using npm:
```sh
npm i @certusone/wormholesdk
```
An explanation of the key concepts of using the Typescript SDK will be outlined in the following section, as well as some examples. For more examples with a more exhaustive coverage of all the supported blockchains in Wormhole, be sure to check the [official codebase](https://github.com/wormhole-foundation/wormhole/tree/dev.v2/sdk/js) for the Typescript SDK.
Virtually all functions of the SDK are demonstrated in the [reference bridge UI](https://github.com/wormhole-foundation/example-token-bridge-ui), which makes it an excellent source of example code as well.

View File

@ -0,0 +1,57 @@
# Token Transfers
<!-- //TODO this information should be captured elsewhere One challenge that arises for new EVM developers is that, because EVM uses unsigned integers, there's no concept of decimals. Therefore, tokens usually have up to 18 zeros behind them to denote up to 18 decimal places. Wormhole normalizes this to *eight* zeros, with transfer amounts rounded down to the nearest 8th decimal. -->
Before transferring tokens, you should ensure that the token is [Registered](./attestingToken.md) on the chain you are transferring to, and that any necessary prerequisite steps (such as sending token approvals or creating associated token accounts) have already been done.
For example, you'll likely need to do a standard ERC-20 token approval prior to performing a bridge action if you're in the EVM ecosystem.
```js
// Here we are approving and transfering 50 tokens. The ERC20 token we are transfering has 18 decimal places.
const bridgeAmt = ethers.utils.parseUnits("50", "18");
await treasury.approveTokenBridge(bridgeAmt, {
gasLimit: 2000000,
});
```
Once any prerequisite steps have been handled, simply call `transfer` on the token bridge module to initiate a transfer and create a transfer VAA. Note that the target receipient is a Wormhole-format address (referred to as 'hex' format in the Typescript SDK).
```js
const targetRecepient = Buffer.from(
tryNativeToHexString(targetDeployment.deployedAddress, "ethereum"),
"hex"
);
const tx = await (
await treasury.bridgeToken(
bridgeAmt,
targetNetwork.wormholeChainId,
targetRecepient
)
).wait();
```
If you're not using a relayer, you'll have to submit the target chain transaction yourself. [This section](./polygon-oasis-relayer.md) outlines how to use relayers.
This code shows how to retrieve the VAA. (It's the same code as shown in the previous section.)
```js
const emitterAddr = getEmitterAddressEth(network.tokenBridgeAddress);
const seq = parseSequenceFromLogEth(tx, network.bridgeAddress);
const vaaURL = `${config.wormhole.restAddress}/v1/signed_vaa/${network.wormholeChainId}/${emitterAddr}/${seq}`;
let vaaBytes = await (await fetch(vaaURL)).json();
while (!vaaBytes.vaaBytes) {
console.log("VAA not found, retrying in 5s!");
await new Promise((r) => setTimeout(r, 5000)); //Timeout to let Guardiand pick up log and have VAA ready
vaaBytes = await (await fetch(vaaURL)).json();
}
```
After we've fetched the VAA, we can call the `completeTransfer()` function on the target chain.
```js
const completeTransferTx = await targetTokenBridge.completeTransfer(
Buffer.from(vaaBytes.vaaBytes, "base64")
);
```

View File

@ -0,0 +1,210 @@
# Using Relayers
In this example, well utilize the token bridge relayer network to complete a token transfer. We'll start on Polygon and send tokens to Oasis.
This code is written for a browser environment. If you're working in node, consider using node-fetch:
```bash
npm i --save @certusone/wormhole-sdk ethers node-fetch
```
```ts
import { BigNumber, ethers } from "ethers";
import fetch from "node-fetch";
import {
getEmitterAddressEth,
hexToUint8Array,
nativeToHexString,
parseSequenceFromLogEth,
CHAIN_ID_POLYGON,
CHAIN_ID_OASIS,
transferFromEthNative,
getIsTransferCompletedEth,
setDefaultWasm,
} from "@certusone/wormhole-sdk";
```
### Setup the Polygon and Oasis Wallets
Now, set up the two wallets well be sending and receiving from. While we are instantiating both wallets with their private keys, we only need the Public key of the receiving wallet for this example.
```ts
const EmeraldWallet = new ethers.Wallet(
privatekey_emerald,
new ethers.providers.JsonRpcProvider("https://emerald.oasis.dev")
);
const PolygonWallet = new ethers.Wallet(
privatekey_polygon,
new ethers.providers.JsonRpcProvider("https://polygon-rpc.com/")
);
```
### Fetch the fee schedule
Fetch the fee schedule for the token bridge relayers. This fee schedule outlines the minimum fee for each recipient chain that relayers will accept. As long as we attach at least that fee in the relayer fee, we can expect a relayer pick up the transaction and relay it to the recipient chain. The fee will cover the gas cost for the relayer along with a little extra to make it worth their time to run the relayer service.
We will also define the transfer amount in this step. The fee schedule will either return a flat fee in USD for the recipient chain, or a percentage fee (usually only for Ethereum). Either way, well need to calculate the fee in in BigNumber format (no decimals).
```ts
const transferAmount = BigNumber.from("1000000000000000000"); // We are sending 1 MATIC over the wall to Oasis
const relayerFeeSchedule = await(
await fetch(
"https://raw.githubusercontent.com/certusone/wormhole-relayer-list/main/relayer.json"
)
).json();
```
The fee schedule has the following interface:
```ts
export interface RelayerFeeSchedule {
supportedTokens: ChainAddress[];
relayers: Relayer[];
feeSchedule: FeeSchedule;
}
interface ChainAddress {
chainId: number;
address: string;
coingeckoId: string;
}
interface Relayer {
name: string;
url: string;
}
interface FeeSchedule {
[chainId: string]: {
type: "flat" | "percent";
feeUsd?: number;
feePercent?: number;
gasEstimate?: number;
};
}
```
After fetching the fee schedule, find the fee in wei that needs to be paid to the Relayer. At the time of writing, Oasis has a flat fee of $0.50, so to calculate how much MATIC we need to pay for the $0.50 fee, we need to fetch the MATIC price. To do that, use the free CoinGecko api:
```ts
let feeWei: number;
if (relayerFeeSchedule.feeSchedule[CHAIN_ID_OASIS].type == "flat") {
const feeUsd = relayerFeeSchedule.feeSchedule[CHAIN_ID_OASIS].feeUsd;
const MATIC_PRICE = await(
await fetch(
"https://api.coingecko.com/api/v3/simple/token_price/polygon-pos?contract_addresses=0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270&vs_currencies=usd"
)
).json()["0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270"]["usd"];
feeWei = (feeUsd / MATIC_PRICE) * 1e18;
} else if (relayerFeeSchedule.feeSchedule[CHAIN_ID_OASIS].type == "percent") {
let feeWei =
(relayerFeeSchedule.feeSchedule[CHAIN_ID_OASIS].feePercent / 100) *
transferAmount.toNumber();
}
```
### Overrides & Quirks
Dependent on the specific blockchains you are working with, you may need to perform special actions when submitting this transaction. Because we're dealing with Polygon in this example, there's an additional step to overestimate the gas. This is because Ethers library has some problems with fee estimation after EIP-1559.
```ts
let overrides;
let feeData = await PolygonWallet.provider.getFeeData();
overrides = {
maxFeePerGas: feeData.maxFeePerGas?.mul(50) || undefined,
maxPriorityFeePerGas: feeData.maxPriorityFeePerGas?.mul(50) || undefined,
};
```
### Emit Token Bridge Message
Now we have all the pieces we need to emit a token bridge message with a relay fee attached. We do this using the transferFromEthNative() method. EthNative is used because were transferring the native token of the Polygon network rather than an ERC20 token.
```ts
const POLYGON_TOKEN_BRIDGE = "0x5a58505a96D1dbf8dF91cB21B54419FC36e93fdE";
const receipt = await transferFromEthNative(
POLYGON_TOKEN_BRIDGE,
PolygonWallet,
transferAmount,
CHAIN_ID_OASIS,
hexToUint8Array(
nativeToHexString(await EmeraldWallet.getAddress(), CHAIN_ID_OASIS) || ""
),
BigNumber.from(feeWei.toString()),
overrides
);
console.log("Receipt: ", receipt);
const POLYGON_CORE_BRIDGE_ADDRESS =
"0x7A4B5a56256163F07b2C80A7cA55aBE66c4ec4d7";
const sequence = parseSequenceFromLogEth(receipt, POLYGON_CORE_BRIDGE_ADDRESS);
const emitterAddress = getEmitterAddressEth(POLYGON_TOKEN_BRIDGE);
console.log("Sequence: ", sequence);
console.log("EmitterAddress: ", emitterAddress);
```
Lets walk through each of the arguments of this function and what they mean.
`POLYGON_TOKEN_BRIDGE` is the address of the token bridge module on the Polygon network. You can find it and other addresses on the Deployment Info page.
`PolygonWallet` is a signer you get from the Ethers library that holds a private key that can sign transactions.
`transferAmount` is a BigNumber that contains the amount to transfer in the smallest unit of the network.
`CHAIN_ID_OASIS` is a constant that identifies the target chain.
`hexToUint8Array()` translates the target publickey into a wormhole public key.
`BigNumber.from(feeWei.toString())` identifies the fee in smallest unit of the network for the relayer.
`overrides` are used if we need to override the gas cost, which we need to do for Polygon.
### Check VAA was signed
Wait 15 min for finality on Polygon and then check to see if it was submitted. If successful, youll be able to fetch a base64 encoded vaaBytes. We need this in the next step where we check if the transaction was successfully relayed.
```ts
await new Promise((r) => setTimeout(r, 900000)); //15m in seconds
const WORMHOLE_RPC = "https://wormhole-v2-mainnet-api.certus.one";
let vaaBytes = undefined;
while (!vaaBytes) {
try {
vaaBytes = await(
await fetch(
`${WORMHOLE_RPC}/v1/signed_vaa/${CHAIN_ID_POLYGON}/${emitterAddress}/${sequence}`
)
).json().vaaBytes;
} catch (e) {
await new Promise((r) => setTimeout(r, 5000));
}
}
console.log("VAA Bytes: ", vaaBytes);
```
### Check if the transfer was completed
In the final step, use the getIsTransferCompletedEth() method to check if the transfer was completed on the Oasis Emerald chain. If its not, wait 5 seconds and check again.
```ts
setDefaultWasm("node"); //only needed if running in node.js
const EMERALD_TOKEN_BRIDGE = "0x5848C791e09901b40A9Ef749f2a6735b418d7564";
let transferCompleted = await getIsTransferCompletedEth(
EMERALD_TOKEN_BRIDGE,
EmeraldWallet.provider,
vaaBytes
);
while (!transferCompleted) {
await new Promise((r) => setTimeout(r, 5000));
transferCompleted = await getIsTransferCompletedEth(
EMERALD_TOKEN_BRIDGE,
EmeraldWallet.provider,
vaaBytes
);
}
console.log("VAA Relayed!");
```
Success! You've programmatically relayed a transaction!

View File

@ -2,39 +2,39 @@
Wormhole is a complex ecosystem with several noteworthy components. Before we go into each component in depth, let's talk about the names of the major pieces and how they fit together.
![Architecture Diagram](../diagrams/images/architecture.png)
![Architecture Diagram](../diagrams/images/architecture.PNG)
### On-Chain Components
- **xDapp Contracts** - Contracts developed by xDapp developers. They receive transactions from the end user and then interact with other xDapp contracts and Wormhole Ecosystem Contracts in order to provide their service.
- **xDapp Contracts** - Contracts developed by xDapp developers. They receive transactions from the end user and then interact with other xDapp contracts and Wormhole Ecosystem Contracts in order to provide their service.
- **Ecosystem Contracts** - Contracts subject to Wormhole governance which live inside the Wormhole Ecosystem. Their job is to provide the feature suite of Wormhole to xDapp developers.
- **Ecosystem Contracts** - Contracts subject to Wormhole governance which live inside the Wormhole Ecosystem. Their job is to provide the feature suite of Wormhole to xDapp developers.
- **Core Contracts** - Primary ecosystem contracts. These are the contracts which the Guardians observe and which fundamentally allow for cross-chain communication.
- **xAsset Contracts** - Contracts that allow normal tokens to be converted to xAssets and enable these xAssets to be bridged.
- **Relay Contracts** - _in development\*_ - Contracts that allow xDapps to send messages to a specific blockchain via the decentralized Generic Relayer network.
- **Gas Oracle** - _in development\*_ - Oracle for recommended fair gas prices across the ecosystem.
- **Core Contracts** - Primary ecosystem contracts. These are the contracts which the Guardians observe and which fundamentally allow for cross-chain communication.
- **Worm Router Contracts** - _in development\*_ - Contracts that allow developers to make their Dapp an xDapp that users on any Wormhole supported chain can interac with purely through clientside code.
- **xAsset Contracts** - Contracts that allow normal tokens to be converted to xAssets and enable these xAssets to be bridged.
- **Relay Contracts** - _in development\*_ - Contracts that allow xDapps to send messages to a specific blockchain via the decentralized Generic Relayer network.
- **Gas Oracle** - _in development\*_ - Oracle for recommended fair gas prices across the ecosystem.
- **Worm Router Contracts** - _in development\*_ - Contracts that allow developers to make their Dapp an xDapp that users on any Wormhole supported chain can interac with purely through clientside code.
### Off-Chain Components
- **Guardian Network** - Validators that exist in their own p2p network. Guardians observe the Core Contract on each supported chain and produce VAAs (signed messages) when those contracts receive an interaction.
- **Guardian Network** - Validators that exist in their own p2p network. Guardians observe the Core Contract on each supported chain and produce VAAs (signed messages) when those contracts receive an interaction.
- **Guardian** - One of 19 validators in the Guardian Network that contributes to the VAA multisig.
- **Guardian** - One of 19 validators in the Guardian Network that contributes to the VAA multisig.
- **Spy** - Validators on the Guardian Network which are not part of the Guardian set. A spy can observe and forward network traffic, which helps scale up VAA distribution.
- **Spy** - Validators on the Guardian Network which are not part of the Guardian set. A spy can observe and forward network traffic, which helps scale up VAA distribution.
- **VAAs** - Verifiable Action Approvals (VAAs) are the key piece of data in the Wormhole ecosystem, containing the messages emitted by xDapps along with information such as what contract emitted the message. The VAAs are signed by the Guardians and need 13/19 signatures to be considered authentic.
- **VAAs** - Verifiable Action Approvals (VAAs) are the key piece of data in the Wormhole ecosystem, containing the messages emitted by xDapps along with information such as what contract emitted the message. The VAAs are signed by the Guardians and need 13/19 signatures to be considered authentic.
- **Specialized Relayers** - Relayers that only handle VAAs for a specific protocol or xDapp. They can execute custom logic off-chain, which can reduce gas costs and increase cross-chain compatibility. Currently, xDapp developers are responsible for developing and hosting specialized relayers.
- **Specialized Relayers** - Relayers that only handle VAAs for a specific protocol or xDapp. They can execute custom logic off-chain, which can reduce gas costs and increase cross-chain compatibility. Currently, xDapp developers are responsible for developing and hosting specialized relayers.
- **Generic Relayers** - _in development\*_ - A decentralized relayer network which delivers messages that are requested on-chain via the Wormhole Relay Contract.
- **Generic Relayers** - _in development\*_ - A decentralized relayer network which delivers messages that are requested on-chain via the Wormhole Relay Contract.
- **Wormchain** - _in development\*_ - A purpose-built cosmos blockchain which aids the Guardian Network and allows for formal interaction with the Guardians.
- **Wormchain** - _in development\*_ - A purpose-built cosmos blockchain which aids the Guardian Network and allows for formal interaction with the Guardians.
\*Features listed as _in development_ are not yet available.

View File

@ -48,7 +48,7 @@ Wormhole can expand to new ecosystems as quickly as a Core Contract can be devel
## Scalability
Wormhole scales well, as demonstrated by Portal's ability to handle huge TVL and transaction volume--even during tumultuous events.
Wormhole scales well, as demonstrated by its ability to handle huge TVL and transaction volume--even during tumultuous events.
The requirements for running a Guardian are relatively heavy, as they need to run a full node for every single blockchain in the ecosystem. This is another reason why a limited number of robust validator companies are beneficial for this design.

View File

@ -2,9 +2,9 @@
There is a set of ecosystem contracts that provision Wormhole's xAsset layer which allow tokens to be bridged around the Wormhole Ecosystem in a **path-independent** fashion, and are easily composable with other functions in the Wormhole ecosystem.
This section provides a high-level overview of how to interact with two smart contract modules that implement xAssets: (1) Token Bridge module and (2) NFT Bridge Module.
This section provides a high-level overview of how to interact with two smart contract modules that implement xAssets: (1) Token Bridge module and (2) NFT Bridge Module.
If you're looking to interact with the Token Bridge directly from a typescript client or backend, you should start with the [Wormhole Typescript SDK](https://www.npmjs.com/package/@certusone/wormhole-sdk).
If you're looking to interact with the Token Bridge directly from a typescript client or backend, you should start with the [Wormhole Typescript SDK](https://www.npmjs.com/package/@certusone/wormhole-sdk).
## Creating xAssets
@ -14,7 +14,7 @@ xAssets are all **fungible** with each other. This means the Wormhole-wrapped as
**Tokens**
To convert tokens into an xAsset, an **attestation** must first be created. To create an attestation, simply call the **attest** function on the Portal contract of the origin chain.
To convert tokens into an xAsset, an **attestation** must first be created. To create an attestation, simply call the **attest** function on the token bridge contract of the origin chain.
function attestToken(
address tokenAddress,
@ -33,7 +33,7 @@ Calling this function will deploy a new contract for the token on the foreign ch
**NFTs**
NFTs do not need need to be attested before they can be created into a xAsset.
NFTs do not need need to be attested before they can be created into a xAsset.
## Transferring xAssets
@ -54,17 +54,17 @@ All tokens managed by the Token Bridge are backed by the origin asset, allowing
```
**NFTs**
```
function transferNFT(
address token,
uint256 tokenID,
uint16 recipientChain,
bytes32 recipient,
uint256 tokenID,
uint16 recipientChain,
bytes32 recipient,
uint32 nonce) returns (uint64 sequence)
)
```
## Contract-Controlled Transfers
Basic transfers are intended to transfer xAssets from one wallet to another, whereas Contract Controlled Transfers (CCTs) are meant to transfer xAssets from one smart contract to another. If you're writing an xDapp, CCTs will likely be a large component.