diff --git a/book.toml b/book.toml index 8f7fb20..22807e9 100644 --- a/book.toml +++ b/book.toml @@ -1,5 +1,5 @@ [book] -title = "Wormhole xDapp Development Book v0.1.0" +title = "Wormhole Development Book" authors = [ "Dev Bharel" ] diff --git a/src/SUMMARY.md b/src/SUMMARY.md index cf079af..b8217fd 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -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]() + + - [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) diff --git a/src/dapps/1_defiBasics.md b/src/dapps/1_defiBasics.md index fd7ce0a..ab6a454 100644 --- a/src/dapps/1_defiBasics.md +++ b/src/dapps/1_defiBasics.md @@ -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**. diff --git a/src/dapps/2_crossChainInteroperability.md b/src/dapps/2_crossChainInteroperability.md index fb07cc0..91859e2 100644 --- a/src/dapps/2_crossChainInteroperability.md +++ b/src/dapps/2_crossChainInteroperability.md @@ -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**. diff --git a/src/dapps/architecture/2_ecosystems.md b/src/dapps/architecture/2_ecosystems.md index 7efe5f4..8b2b7f9 100644 --- a/src/dapps/architecture/2_ecosystems.md +++ b/src/dapps/architecture/2_ecosystems.md @@ -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). diff --git a/src/development/portal/sdkjs/overview.md b/src/development/portal/sdkjs/overview.md index c603fce..7e780c4 100644 --- a/src/development/portal/sdkjs/overview.md +++ b/src/development/portal/sdkjs/overview.md @@ -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: diff --git a/src/development/portal/sdkjs/polygon-oasis-relayer.md b/src/development/portal/sdkjs/polygon-oasis-relayer.md index 6c51487..e152d4b 100644 --- a/src/development/portal/sdkjs/polygon-oasis-relayer.md +++ b/src/development/portal/sdkjs/polygon-oasis-relayer.md @@ -1,10 +1,10 @@ # Polygon to Oasis with Relayers -In this example, we’ll fetch the fee schedule and attach a relayer fee onto our transaction. This is a non-trivial example as we’ll also use Polygon as a source chain, which has some quirks when it comes to gas estimation. +In this example, we’ll fetch the fee schedule and attach a relayer fee onto our transaction. This is a non-trivial example as we’ll 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, we’ll need a couple of packages: +To start, we’ll 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 we’ll 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, we’ll 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, we’ll 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 we’re 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 we’re 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); ``` -Let’s walk through each of the arguments of this function and what they mean. +Let’s 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 @@ Let’s 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!"); diff --git a/src/development/tilt/constants.md b/src/development/tilt/constants.md index 2e10c3b..aff692c 100644 --- a/src/development/tilt/constants.md +++ b/src/development/tilt/constants.md @@ -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: diff --git a/src/development/tilt/overview.md b/src/development/tilt/overview.md index ef6d2db..94e4284 100644 --- a/src/development/tilt/overview.md +++ b/src/development/tilt/overview.md @@ -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. diff --git a/src/reference/contracts.md b/src/reference/contracts.md index 7b62d18..0b5c964 100644 --- a/src/reference/contracts.md +++ b/src/reference/contracts.md @@ -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 | diff --git a/src/reference/github.md b/src/reference/github.md deleted file mode 100644 index d89238d..0000000 --- a/src/reference/github.md +++ /dev/null @@ -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. diff --git a/src/reference/glossary.md b/src/reference/glossary.md index a9e63ee..cfb3a2e 100644 --- a/src/reference/glossary.md +++ b/src/reference/glossary.md @@ -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. \ No newline at end of file +[**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. \ No newline at end of file diff --git a/src/reference/overview.md b/src/reference/overview.md new file mode 100644 index 0000000..83ea2e2 --- /dev/null +++ b/src/reference/overview.md @@ -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) diff --git a/src/reference/tools.md b/src/reference/tools.md deleted file mode 100644 index 27bac40..0000000 --- a/src/reference/tools.md +++ /dev/null @@ -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). diff --git a/src/reference/usefulLinks.md b/src/reference/usefulLinks.md new file mode 100644 index 0000000..ef4f913 --- /dev/null +++ b/src/reference/usefulLinks.md @@ -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). \ No newline at end of file diff --git a/src/technical/algorand/overview.md b/src/technical/algorand/overview.md new file mode 100644 index 0000000..560b6cf --- /dev/null +++ b/src/technical/algorand/overview.md @@ -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). diff --git a/src/technical/aptos/overview.md b/src/technical/aptos/overview.md new file mode 100644 index 0000000..0132ef8 --- /dev/null +++ b/src/technical/aptos/overview.md @@ -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). diff --git a/src/technical/cosmos/overview.md b/src/technical/cosmos/overview.md new file mode 100644 index 0000000..7a51a06 --- /dev/null +++ b/src/technical/cosmos/overview.md @@ -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). diff --git a/src/technical/env/environments.md b/src/technical/env/environments.md index c537087..b5ed8c8 100644 --- a/src/technical/env/environments.md +++ b/src/technical/env/environments.md @@ -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. \ No newline at end of file diff --git a/src/technical/env/testnet.md b/src/technical/env/testnet.md index 2e64931..b545de0 100644 --- a/src/technical/env/testnet.md +++ b/src/technical/env/testnet.md @@ -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. \ No newline at end of file diff --git a/src/technical/env/tilt.md b/src/technical/env/tilt.md index ed896c3..575a5b2 100644 --- a/src/technical/env/tilt.md +++ b/src/technical/env/tilt.md @@ -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 diff --git a/src/technical/env/troubleshooting.md b/src/technical/env/troubleshooting.md index 2953f66..20f14fa 100644 --- a/src/technical/env/troubleshooting.md +++ b/src/technical/env/troubleshooting.md @@ -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 ``` diff --git a/src/technical/env/wlv.md b/src/technical/env/wlv.md index 3a1529c..78ec06d 100644 --- a/src/technical/env/wlv.md +++ b/src/technical/env/wlv.md @@ -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. diff --git a/src/technical/evm/bestPractices.md b/src/technical/evm/bestPractices.md index 042a2d4..d5d4f4b 100644 --- a/src/technical/evm/bestPractices.md +++ b/src/technical/evm/bestPractices.md @@ -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); } ``` diff --git a/src/technical/evm/coreLayer.md b/src/technical/evm/coreLayer.md index de3e734..e39ad3d 100644 --- a/src/technical/evm/coreLayer.md +++ b/src/technical/evm/coreLayer.md @@ -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. - +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. diff --git a/src/technical/evm/nftLayer.md b/src/technical/evm/nftLayer.md index 9bb088d..5dc8c9b 100644 --- a/src/technical/evm/nftLayer.md +++ b/src/technical/evm/nftLayer.md @@ -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. diff --git a/src/technical/relayer/overview.md b/src/technical/relayer/overview.md index b51c251..d419cc0 100644 --- a/src/technical/relayer/overview.md +++ b/src/technical/relayer/overview.md @@ -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). diff --git a/src/technical/relayer/pluginRelayers.md b/src/technical/relayer/pluginRelayers.md index 5b0034a..2f65c5c 100644 --- a/src/technical/relayer/pluginRelayers.md +++ b/src/technical/relayer/pluginRelayers.md @@ -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. diff --git a/src/technical/relayer/specializedRelayers.md b/src/technical/relayer/specializedRelayers.md index c082a34..118ae7f 100644 --- a/src/technical/relayer/specializedRelayers.md +++ b/src/technical/relayer/specializedRelayers.md @@ -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. + diff --git a/src/technical/solana/overview.md b/src/technical/solana/overview.md new file mode 100644 index 0000000..a49f1ed --- /dev/null +++ b/src/technical/solana/overview.md @@ -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). diff --git a/src/technical/typescript/attestingToken.md b/src/technical/typescript/attestingToken.md new file mode 100644 index 0000000..2797b29 --- /dev/null +++ b/src/technical/typescript/attestingToken.md @@ -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); +``` diff --git a/src/technical/typescript/cross-ecosystem-transfer.md b/src/technical/typescript/cross-ecosystem-transfer.md new file mode 100644 index 0000000..97131cc --- /dev/null +++ b/src/technical/typescript/cross-ecosystem-transfer.md @@ -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, let’s 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 it’s 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); +``` diff --git a/src/technical/typescript/overview.md b/src/technical/typescript/overview.md new file mode 100644 index 0000000..2ffc2d6 --- /dev/null +++ b/src/technical/typescript/overview.md @@ -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. diff --git a/src/technical/typescript/tokenTransfer.md b/src/technical/typescript/tokenTransfer.md new file mode 100644 index 0000000..2f4e878 --- /dev/null +++ b/src/technical/typescript/tokenTransfer.md @@ -0,0 +1,57 @@ +# Token Transfers + + + +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") +); +``` diff --git a/src/technical/typescript/using-relayer.md b/src/technical/typescript/using-relayer.md new file mode 100644 index 0000000..19d704c --- /dev/null +++ b/src/technical/typescript/using-relayer.md @@ -0,0 +1,210 @@ +# Using Relayers + +In this example, we’ll 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 we’ll 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, we’ll 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 we’re 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); +``` + +Let’s 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, you’ll 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 it’s 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! diff --git a/src/wormhole/2_architectureOverview.md b/src/wormhole/2_architectureOverview.md index da26383..e36edbf 100644 --- a/src/wormhole/2_architectureOverview.md +++ b/src/wormhole/2_architectureOverview.md @@ -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. diff --git a/src/wormhole/5_guardianNetwork.md b/src/wormhole/5_guardianNetwork.md index 3c141e8..16e01b1 100644 --- a/src/wormhole/5_guardianNetwork.md +++ b/src/wormhole/5_guardianNetwork.md @@ -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. diff --git a/src/wormhole/7_TokenBridge.md b/src/wormhole/7_xAssetBridge.md similarity index 94% rename from src/wormhole/7_TokenBridge.md rename to src/wormhole/7_xAssetBridge.md index 2005ed8..384189b 100644 --- a/src/wormhole/7_TokenBridge.md +++ b/src/wormhole/7_xAssetBridge.md @@ -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.