clients/js: move towards sdkV2
This commit is contained in:
parent
eebc7ae883
commit
9f98901d2d
|
@ -244,7 +244,7 @@ jobs:
|
|||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: "16"
|
||||
node-version: "20"
|
||||
- run: |
|
||||
cd clients/js && make test
|
||||
make docs
|
||||
|
|
|
@ -78,6 +78,16 @@ Options:
|
|||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary> chains </summary>
|
||||
|
||||
```sh
|
||||
Options:
|
||||
--help Show help [boolean]
|
||||
--version Show version number [boolean]
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary> edit-vaa </summary>
|
||||
|
||||
|
@ -248,16 +258,8 @@ Positionals:
|
|||
Options:
|
||||
--help Show help [boolean]
|
||||
--version Show version number [boolean]
|
||||
-c, --chain chain name
|
||||
[choices: "unset", "solana", "ethereum", "terra", "bsc", "polygon",
|
||||
"avalanche", "oasis", "algorand", "aurora", "fantom", "karura", "acala",
|
||||
"klaytn", "celo", "near", "moonbeam", "neon", "terra2", "injective",
|
||||
"osmosis", "sui", "aptos", "arbitrum", "optimism", "gnosis", "pythnet",
|
||||
"xpla", "btc", "base", "sei", "rootstock", "scroll", "mantle", "blast",
|
||||
"xlayer", "linea", "berachain", "seievm", "wormchain", "cosmoshub", "evmos",
|
||||
"kujira", "neutron", "celestia", "stargaze", "seda", "dymension",
|
||||
"provenance", "sepolia", "arbitrum_sepolia", "base_sepolia",
|
||||
"optimism_sepolia", "holesky", "polygon_sepolia"]
|
||||
-c, --chain chain name. To see a list of supported chains, run
|
||||
`worm chains` [string]
|
||||
-n, --network Network
|
||||
[required] [choices: "mainnet", "testnet", "devnet"]
|
||||
-a, --contract-address Contract to submit VAA to (override config) [string]
|
||||
|
@ -307,26 +309,10 @@ Options:
|
|||
Options:
|
||||
--help Show help [boolean]
|
||||
--version Show version number [boolean]
|
||||
--src-chain source chain
|
||||
[required] [choices: "solana", "ethereum", "terra", "bsc", "polygon",
|
||||
"avalanche", "oasis", "algorand", "aurora", "fantom", "karura", "acala",
|
||||
"klaytn", "celo", "near", "moonbeam", "neon", "terra2", "injective",
|
||||
"osmosis", "sui", "aptos", "arbitrum", "optimism", "gnosis", "pythnet",
|
||||
"xpla", "btc", "base", "sei", "rootstock", "scroll", "mantle", "blast",
|
||||
"xlayer", "linea", "berachain", "seievm", "wormchain", "cosmoshub", "evmos",
|
||||
"kujira", "neutron", "celestia", "stargaze", "seda", "dymension",
|
||||
"provenance", "sepolia", "arbitrum_sepolia", "base_sepolia",
|
||||
"optimism_sepolia", "holesky", "polygon_sepolia"]
|
||||
--dst-chain destination chain
|
||||
[required] [choices: "solana", "ethereum", "terra", "bsc", "polygon",
|
||||
"avalanche", "oasis", "algorand", "aurora", "fantom", "karura", "acala",
|
||||
"klaytn", "celo", "near", "moonbeam", "neon", "terra2", "injective",
|
||||
"osmosis", "sui", "aptos", "arbitrum", "optimism", "gnosis", "pythnet",
|
||||
"xpla", "btc", "base", "sei", "rootstock", "scroll", "mantle", "blast",
|
||||
"xlayer", "linea", "berachain", "seievm", "wormchain", "cosmoshub", "evmos",
|
||||
"kujira", "neutron", "celestia", "stargaze", "seda", "dymension",
|
||||
"provenance", "sepolia", "arbitrum_sepolia", "base_sepolia",
|
||||
"optimism_sepolia", "holesky", "polygon_sepolia"]
|
||||
--src-chain source chain. To see a list of supported chains, run `worm
|
||||
chains` [string] [required]
|
||||
--dst-chain destination chain. To see a list of supported chains, run
|
||||
`worm chains` [string] [required]
|
||||
--dst-addr destination address [string] [required]
|
||||
--token-addr token address [string] [default: native token]
|
||||
--amount token amount [string] [required]
|
||||
|
@ -353,16 +339,8 @@ Options:
|
|||
```sh
|
||||
Positionals:
|
||||
network Network [choices: "mainnet", "testnet", "devnet"]
|
||||
chain Source chain
|
||||
[choices: "unset", "solana", "ethereum", "terra", "bsc", "polygon",
|
||||
"avalanche", "oasis", "algorand", "aurora", "fantom", "karura", "acala",
|
||||
"klaytn", "celo", "near", "moonbeam", "neon", "terra2", "injective",
|
||||
"osmosis", "sui", "aptos", "arbitrum", "optimism", "gnosis", "pythnet",
|
||||
"xpla", "btc", "base", "sei", "rootstock", "scroll", "mantle", "blast",
|
||||
"xlayer", "linea", "berachain", "seievm", "wormchain", "cosmoshub", "evmos",
|
||||
"kujira", "neutron", "celestia", "stargaze", "seda", "dymension",
|
||||
"provenance", "sepolia", "arbitrum_sepolia", "base_sepolia",
|
||||
"optimism_sepolia", "holesky", "polygon_sepolia"]
|
||||
chain Source chain. To see a list of supported chains, run `worm chains`
|
||||
[string]
|
||||
tx Source transaction hash [string]
|
||||
|
||||
Options:
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
0xbeFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe
|
|
@ -0,0 +1 @@
|
|||
evm address-from-secret 0xcfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0
|
|
@ -0,0 +1 @@
|
|||
0100000000010009b7c0612e950779ea6a5458800289925c02a32cca3670f497693df283b503177e757473f94adfa2d18745b9e3d01a04f6b97240459612bd8654e5f91fb3f3d5010000000100000001000100000000000000000000000000000000000000000000000000000000000000040000000005a657f60000000000000000000000000000000000000000000000004e46544272696467650100000004000000000000000000000000706abc4e45d419950511e474c7b9ed348a4a716c
|
|
@ -0,0 +1 @@
|
|||
generate registration --module NFTBridge --chain bsc --contract-address 0x706abc4E45D419950511e474C7B9Ed348A4a716c --guardian-secret cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0
|
|
@ -0,0 +1 @@
|
|||
01000000000100fe357dfbb2661d594da7720bf919bcb5597776c20720065c38748a7f69bc59e30b1a3a9ed564418083162c2f9f12910a799699faafe75494ba68b5813ae4a19a0000000001000000010002000000000000000000000000000000001111111111111111111111111111111500000000051d2e300002000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800020655534443000000000000000000000000000000000000000000000000000000005553444300000000000000000000000000000000000000000000000000000000
|
|
@ -0,0 +1 @@
|
|||
generate attestation --emitter-chain Ethereum --emitter-address 11111111111111111111111111111115 --chain Ethereum --token-address 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 --decimals 6 --symbol USDC --name USDC --guardian-secret cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0
|
|
@ -0,0 +1,69 @@
|
|||
{
|
||||
"address": "0xB6F6D86a8f9879A9c87f643768d9efc38c1Da6E7",
|
||||
"wormhole": "0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B",
|
||||
"implementation": "0x621199f6beB2ba6fbD962E8A52A320EA4F6D4aA3",
|
||||
"isInitialized": true,
|
||||
"tokenImplementation": "0x7f8C5e730121657E17E452c5a1bA3fA1eF96f22a",
|
||||
"chainId": 4,
|
||||
"finality": 15,
|
||||
"evmChainId": "56",
|
||||
"isFork": false,
|
||||
"governanceChainId": 1,
|
||||
"governanceContract": "0x0000000000000000000000000000000000000000000000000000000000000004",
|
||||
"WETH": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
|
||||
"registrations": {
|
||||
"Solana": "0xec7372995d5cc8732397fb0ad35c0121e0eaa90d26f828a534cab54391b3a4f5",
|
||||
"Ethereum": "0x0000000000000000000000003ee18b2214aff97000d974cf647e7c347e8fa585",
|
||||
"Terra": "0x0000000000000000000000007cf7b764e38a0a5e967972c1df77d432510564e2",
|
||||
"Polygon": "0x0000000000000000000000005a58505a96d1dbf8df91cb21b54419fc36e93fde",
|
||||
"Avalanche": "0x0000000000000000000000000e082f06ff657d94310cb8ce8b0d9a04541d8052",
|
||||
"Oasis": "0x0000000000000000000000005848c791e09901b40a9ef749f2a6735b418d7564",
|
||||
"Algorand": "0x67e93fa6c8ac5c819990aa7340c0c16b508abb1178be9b30d024b8ac25193d45",
|
||||
"Aurora": "0x00000000000000000000000051b5123a7b0f9b2ba265f9c4c8de7d78d52f510f",
|
||||
"Fantom": "0x0000000000000000000000007c9fc5741288cdfdd83ceb07f3ea7e22618d79d2",
|
||||
"Karura": "0x000000000000000000000000ae9d7fe007b3327aa64a32824aaac52c42a6e624",
|
||||
"Acala": "0x000000000000000000000000ae9d7fe007b3327aa64a32824aaac52c42a6e624",
|
||||
"Klaytn": "0x0000000000000000000000005b08ac39eaed75c0439fc750d9fe7e1f9dd0193f",
|
||||
"Celo": "0x000000000000000000000000796dff6d74f3e27060b71255fe517bfb23c93eed",
|
||||
"Near": "0x148410499d3fcda4dcfd68a1ebfcdddda16ab28326448d4aae4d2f0465cdfcb7",
|
||||
"Moonbeam": "0x000000000000000000000000b1731c586ca89a23809861c6103f0b96b3f57d92",
|
||||
"Neon": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Terra2": "0xa463ad028fb79679cfc8ce1efba35ac0e77b35080a1abe9bebe83461f176b0a3",
|
||||
"Injective": "0x00000000000000000000000045dbea4617971d93188eda21530bc6503d153313",
|
||||
"Osmosis": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Sui": "0xccceeb29348f71bdd22ffef43a2a19c1f5b5e17c5cca5411529120182672ade5",
|
||||
"Aptos": "0x0000000000000000000000000000000000000000000000000000000000000001",
|
||||
"Arbitrum": "0x0000000000000000000000000b2402144bb366a632d14b83f244d2e0e21bd39c",
|
||||
"Optimism": "0x0000000000000000000000001d68124e65fafc907325e3edbf8c4d84499daa8b",
|
||||
"Gnosis": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Pythnet": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Xpla": "0x8f9cf727175353b17a5f574270e370776123d90fd74956ae4277962b4fdee24c",
|
||||
"Btc": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Base": "0x0000000000000000000000008d2de8d2f73f1f4cab472ac9a881c9b123c79627",
|
||||
"Sei": "0x86c5fd957e2db8389553e1728f9c27964b22a8154091ccba54d75f4b10c61f5e",
|
||||
"Rootstock": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Scroll": "0x00000000000000000000000024850c6f61c438823f01b7a3bf2b89b72174fa9d",
|
||||
"Mantle": "0x00000000000000000000000024850c6f61c438823f01b7a3bf2b89b72174fa9d",
|
||||
"Blast": "0x00000000000000000000000024850c6f61c438823f01b7a3bf2b89b72174fa9d",
|
||||
"Xlayer": "0x0000000000000000000000005537857664b0f9efe38c9f320f75fef23234d904",
|
||||
"Linea": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Berachain": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Seievm": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Wormchain": "0xaeb534c45c3049d380b9d9b966f9895f53abd4301bfaff407fa09dea8ae7a924",
|
||||
"Cosmoshub": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Evmos": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Kujira": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Neutron": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Celestia": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Stargaze": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Seda": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Dymension": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Provenance": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Sepolia": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"ArbitrumSepolia": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"BaseSepolia": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"OptimismSepolia": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Holesky": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"PolygonSepolia": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
evm info -c Bsc -n mainnet -m TokenBridge
|
|
@ -0,0 +1,4 @@
|
|||
Mismatches found on Ethereum Mainnet!
|
||||
{
|
||||
Mantle: 'Expected null , found 0x00000000000000000000000024850c6f61c438823f01b7a3bf2b89b72174fa9d'
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
info registrations mainnet ethereum TokenBridge -v
|
|
@ -0,0 +1 @@
|
|||
0x3ee18B2214AFF97000D974cf647E7C347E8fa585
|
|
@ -0,0 +1 @@
|
|||
info contract mainnet ethereum TokenBridge
|
|
@ -0,0 +1 @@
|
|||
0x5a58505a96D1dbf8dF91cB21B54419FC36e93fdE
|
|
@ -0,0 +1 @@
|
|||
info contract mainnet Bsc NFTBridge
|
|
@ -0,0 +1 @@
|
|||
https://bsc-dataseed.binance.org/
|
|
@ -0,0 +1 @@
|
|||
info rpc mainnet Bsc
|
|
@ -0,0 +1 @@
|
|||
0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN
|
|
@ -0,0 +1 @@
|
|||
info wrapped ethereum 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 sui
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
isWrapped: true,
|
||||
chainId: 2,
|
||||
assetAddress: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
info origin sui 0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN
|
File diff suppressed because it is too large
Load Diff
|
@ -42,11 +42,13 @@
|
|||
"@solana/web3.js": "^1.22.0",
|
||||
"@terra-money/terra.js": "^3.1.9",
|
||||
"@types/config": "^3.3.0",
|
||||
"@wormhole-foundation/sdk": "^0.7.0-beta.5",
|
||||
"@xpla/xpla.js": "^0.2.1",
|
||||
"algosdk": "^2.4.0",
|
||||
"aptos": "^1.3.16",
|
||||
"axios": "^0.24.0",
|
||||
"base-64": "^1.0.0",
|
||||
"bech32": "^2.0.0",
|
||||
"binary-parser": "^2.0.2",
|
||||
"bn.js": "^5.2.0",
|
||||
"bs58": "^4.0.1",
|
||||
|
@ -65,12 +67,13 @@
|
|||
"@types/bn.js": "^5.1.0",
|
||||
"@types/bs58": "^4.0.1",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^20.12.12",
|
||||
"@types/node-fetch": "^2.6.3",
|
||||
"@types/yargs": "^17.0.24",
|
||||
"copy-dir": "^1.3.0",
|
||||
"jest": "^29.7.0",
|
||||
"ts-jest": "^29.1.2",
|
||||
"tsx": "^4.12.0",
|
||||
"typescript": "^4.6"
|
||||
"typescript": "^5.4.5"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This is here for ease of generating outputs.
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
test_directory="info_tests"
|
||||
|
||||
function usage() {
|
||||
cat <<EOF >&2
|
||||
Usage:
|
||||
|
||||
$(basename "$0") [-h] [-a] -- Run info golden tests in $test_directory
|
||||
|
||||
where:
|
||||
-h show this help text
|
||||
-a accept new results (override test files)
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
accept=false
|
||||
while getopts ':ha' option; do
|
||||
case "$option" in
|
||||
h) usage
|
||||
;;
|
||||
a) accept=true
|
||||
;;
|
||||
:) printf "missing argument for -%s\n" "$OPTARG" >&2
|
||||
usage
|
||||
;;
|
||||
\?) printf "illegal option: -%s\n" "$OPTARG" >&2
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
test_files=$(find "$test_directory" -type f | grep "\.test$")
|
||||
|
||||
failed_tests=0
|
||||
for test in ${test_files[@]}; do
|
||||
test_name="${test%.*}"
|
||||
expected="$test_name.expected"
|
||||
|
||||
result=$(mktemp)
|
||||
node build/main.js $(cat "$test") > "$result" 2>&1
|
||||
if [ $accept = true ]; then
|
||||
echo "Updating $test_name"
|
||||
cat "$result" > "$expected"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ ! -f "$expected" ]; then
|
||||
echo "Missing '$expected' (re-run with -a flag to create)"
|
||||
failed_tests=$(($failed_tests + 1))
|
||||
else
|
||||
echo "Testing $test_name"
|
||||
git --no-pager diff --no-index "$expected" "$result"
|
||||
failed_tests=$(($failed_tests + $?))
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ! $failed_tests = 0 ]; then
|
||||
echo "$failed_tests failed test(s)"
|
||||
exit 1
|
||||
else
|
||||
echo "All tests passed"
|
||||
fi
|
|
@ -2,24 +2,26 @@ import {
|
|||
_submitVAAAlgorand,
|
||||
signSendAndConfirmAlgorand,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/algorand";
|
||||
import {
|
||||
CONTRACTS,
|
||||
ChainName,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import { Account, Algodv2, mnemonicToSecretKey } from "algosdk";
|
||||
import { NETWORKS } from "./consts";
|
||||
import { Network } from "./utils";
|
||||
import { Payload, impossible } from "./vaa";
|
||||
import { transferFromAlgorand } from "@certusone/wormhole-sdk/lib/esm/token_bridge/transfer";
|
||||
import { tryNativeToHexString } from "@certusone/wormhole-sdk/lib/esm/utils";
|
||||
import { tryNativeToHexString } from "./sdk/array";
|
||||
import {
|
||||
Chain,
|
||||
chainToChainId,
|
||||
contracts,
|
||||
Network,
|
||||
toChainId,
|
||||
} from "@wormhole-foundation/sdk-base";
|
||||
|
||||
export async function execute_algorand(
|
||||
payload: Payload,
|
||||
vaa: Uint8Array,
|
||||
network: Network
|
||||
) {
|
||||
const chainName = "algorand";
|
||||
const { key, rpc } = NETWORKS[network][chainName];
|
||||
const chain: Chain = "Algorand";
|
||||
const { key, rpc } = NETWORKS[network][chain];
|
||||
if (!key) {
|
||||
throw Error(`No ${network} key defined for Algorand`);
|
||||
}
|
||||
|
@ -28,19 +30,15 @@ export async function execute_algorand(
|
|||
throw Error(`No ${network} rpc defined for Algorand`);
|
||||
}
|
||||
|
||||
const contracts = CONTRACTS[network][chainName];
|
||||
console.log("contracts", contracts);
|
||||
const coreContract = contracts.coreBridge.get(network, chain);
|
||||
if (!coreContract) {
|
||||
throw new Error(`Core bridge address not defined for Algorand ${network}`);
|
||||
}
|
||||
|
||||
let target_contract: string;
|
||||
switch (payload.module) {
|
||||
case "Core": {
|
||||
if (!contracts.core) {
|
||||
throw new Error(
|
||||
`Core bridge address not defined for Algorand ${network}`
|
||||
);
|
||||
}
|
||||
|
||||
target_contract = contracts.core;
|
||||
target_contract = coreContract;
|
||||
switch (payload.type) {
|
||||
case "GuardianSetUpgrade":
|
||||
console.log("Submitting new guardian set");
|
||||
|
@ -57,14 +55,12 @@ export async function execute_algorand(
|
|||
break;
|
||||
}
|
||||
case "NFTBridge": {
|
||||
if (!contracts.nft_bridge) {
|
||||
// NOTE: this code can safely be removed once the algorand NFT bridge is
|
||||
// released, but it's fine for it to stay, as the condition will just be
|
||||
// skipped once 'contracts.nft_bridge' is defined
|
||||
const nftContract = contracts.nftBridge.get(network, chain);
|
||||
if (!nftContract) {
|
||||
throw new Error("NFT bridge not supported yet for Algorand");
|
||||
}
|
||||
|
||||
target_contract = contracts.nft_bridge;
|
||||
target_contract = nftContract;
|
||||
switch (payload.type) {
|
||||
case "ContractUpgrade":
|
||||
console.log("Upgrading contract");
|
||||
|
@ -84,13 +80,14 @@ export async function execute_algorand(
|
|||
break;
|
||||
}
|
||||
case "TokenBridge": {
|
||||
if (!contracts.token_bridge) {
|
||||
const tbContract = contracts.tokenBridge.get(network, chain);
|
||||
if (!tbContract) {
|
||||
throw new Error(
|
||||
`Token bridge address not defined for Algorand ${network}`
|
||||
);
|
||||
}
|
||||
|
||||
target_contract = contracts.token_bridge;
|
||||
target_contract = tbContract;
|
||||
switch (payload.type) {
|
||||
case "ContractUpgrade":
|
||||
console.log("Upgrading contract");
|
||||
|
@ -121,7 +118,7 @@ export async function execute_algorand(
|
|||
}
|
||||
|
||||
const target = BigInt(parseInt(target_contract));
|
||||
const CORE_ID = BigInt(parseInt(contracts.core));
|
||||
const CORE_ID = BigInt(parseInt(coreContract));
|
||||
const algodClient = getClient(network, rpc);
|
||||
const algoWallet: Account = mnemonicToSecretKey(key);
|
||||
|
||||
|
@ -140,27 +137,29 @@ export async function execute_algorand(
|
|||
}
|
||||
|
||||
export async function transferAlgorand(
|
||||
dstChain: ChainName,
|
||||
dstChain: Chain,
|
||||
dstAddress: string,
|
||||
tokenAddress: string,
|
||||
amount: string,
|
||||
network: Network,
|
||||
rpc: string
|
||||
) {
|
||||
const { key } = NETWORKS[network].algorand;
|
||||
const { key } = NETWORKS[network].Algorand;
|
||||
if (!key) {
|
||||
throw Error(`No ${network} key defined for Algorand`);
|
||||
}
|
||||
const contracts = CONTRACTS[network].algorand;
|
||||
const client = getClient(network, rpc);
|
||||
const wallet: Account = mnemonicToSecretKey(key);
|
||||
const CORE_ID = BigInt(parseInt(contracts.core));
|
||||
const TOKEN_BRIDGE_ID = BigInt(parseInt(contracts.token_bridge));
|
||||
const recipient = tryNativeToHexString(dstAddress, dstChain);
|
||||
const CORE_ID = BigInt(parseInt(contracts.coreBridge(network, "Algorand")));
|
||||
const TOKEN_BRIDGE_ID = BigInt(
|
||||
parseInt(contracts.tokenBridge(network, "Algorand"))
|
||||
);
|
||||
const recipient = tryNativeToHexString(dstAddress, chainToChainId(dstChain));
|
||||
if (!recipient) {
|
||||
throw new Error("Failed to convert recipient address");
|
||||
}
|
||||
const assetId = tokenAddress === "native" ? BigInt(0) : BigInt(tokenAddress);
|
||||
|
||||
const txs = await transferFromAlgorand(
|
||||
client,
|
||||
TOKEN_BRIDGE_ID,
|
||||
|
@ -169,7 +168,7 @@ export async function transferAlgorand(
|
|||
assetId,
|
||||
BigInt(amount),
|
||||
recipient,
|
||||
dstChain,
|
||||
toChainId(dstChain),
|
||||
BigInt(0)
|
||||
);
|
||||
const result = await signSendAndConfirmAlgorand(client, txs, wallet);
|
||||
|
@ -182,7 +181,7 @@ function getClient(network: Network, rpc: string) {
|
|||
algodServer: rpc,
|
||||
algodPort: "",
|
||||
};
|
||||
if (network === "DEVNET") {
|
||||
if (network === "Devnet") {
|
||||
ALGORAND_HOST.algodToken =
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
||||
ALGORAND_HOST.algodPort = "4001";
|
||||
|
|
|
@ -1,22 +1,21 @@
|
|||
import {
|
||||
CONTRACTS,
|
||||
ChainId,
|
||||
ChainName,
|
||||
assertChain,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import { transferFromAptos } from "@certusone/wormhole-sdk/lib/esm/token_bridge/transfer";
|
||||
import { AptosAccount, AptosClient, BCS, TxnBuilderTypes, Types } from "aptos";
|
||||
import { ethers } from "ethers";
|
||||
import { sha3_256 } from "js-sha3";
|
||||
import { NETWORKS } from "./consts";
|
||||
import { Network } from "./utils";
|
||||
import { Payload, impossible } from "./vaa";
|
||||
import { CHAINS, ensureHexPrefix } from "@certusone/wormhole-sdk";
|
||||
import { TokenBridgeState } from "@certusone/wormhole-sdk/lib/esm/aptos/types";
|
||||
import { generateSignAndSubmitEntryFunction } from "@certusone/wormhole-sdk/lib/esm/utils";
|
||||
import {
|
||||
generateSignAndSubmitEntryFunction,
|
||||
tryNativeToUint8Array,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils";
|
||||
Chain,
|
||||
ChainId,
|
||||
Network,
|
||||
assertChainId,
|
||||
contracts,
|
||||
toChainId,
|
||||
} from "@wormhole-foundation/sdk-base";
|
||||
import { tryNativeToUint8Array } from "./sdk/array";
|
||||
|
||||
export async function execute_aptos(
|
||||
payload: Payload,
|
||||
|
@ -25,7 +24,7 @@ export async function execute_aptos(
|
|||
contract: string | undefined,
|
||||
rpc: string | undefined
|
||||
) {
|
||||
const chain = "aptos";
|
||||
const chain: Chain = "Aptos";
|
||||
|
||||
// turn VAA bytes into BCS format. That is, add a length prefix
|
||||
const serializer = new BCS.Serializer();
|
||||
|
@ -34,7 +33,7 @@ export async function execute_aptos(
|
|||
|
||||
switch (payload.module) {
|
||||
case "Core": {
|
||||
contract = contract ?? CONTRACTS[network][chain]["core"];
|
||||
contract = contract ?? contracts.coreBridge.get(network, chain);
|
||||
if (contract === undefined) {
|
||||
throw Error("core bridge contract is undefined");
|
||||
}
|
||||
|
@ -71,7 +70,7 @@ export async function execute_aptos(
|
|||
break;
|
||||
}
|
||||
case "NFTBridge": {
|
||||
contract = contract ?? CONTRACTS[network][chain]["nft_bridge"];
|
||||
contract = contract ?? contracts.nftBridge.get(network, chain);
|
||||
if (contract === undefined) {
|
||||
throw Error("nft bridge contract is undefined");
|
||||
}
|
||||
|
@ -120,7 +119,7 @@ export async function execute_aptos(
|
|||
break;
|
||||
}
|
||||
case "TokenBridge": {
|
||||
contract = contract ?? CONTRACTS[network][chain]["token_bridge"];
|
||||
contract = contract ?? contracts.tokenBridge.get(network, chain);
|
||||
if (contract === undefined) {
|
||||
throw Error("token bridge contract is undefined");
|
||||
}
|
||||
|
@ -180,7 +179,7 @@ export async function execute_aptos(
|
|||
// offline:
|
||||
const tokenAddress = payload.tokenAddress;
|
||||
const tokenChain = payload.tokenChain;
|
||||
assertChain(tokenChain);
|
||||
assertChainId(tokenChain);
|
||||
let wrappedContract = deriveWrappedAssetAddress(
|
||||
hex(contract),
|
||||
tokenChain,
|
||||
|
@ -208,7 +207,7 @@ export async function execute_aptos(
|
|||
// TODO: only handles wrapped assets for now
|
||||
const tokenAddress = payload.tokenAddress;
|
||||
const tokenChain = payload.tokenChain;
|
||||
assertChain(tokenChain);
|
||||
assertChainId(tokenChain);
|
||||
let wrappedContract = deriveWrappedAssetAddress(
|
||||
hex(contract),
|
||||
tokenChain,
|
||||
|
@ -243,22 +242,22 @@ export async function execute_aptos(
|
|||
}
|
||||
|
||||
export async function transferAptos(
|
||||
dstChain: ChainName,
|
||||
dstChain: Chain,
|
||||
dstAddress: string,
|
||||
tokenAddress: string,
|
||||
amount: string,
|
||||
network: Network,
|
||||
rpc: string
|
||||
) {
|
||||
const { key } = NETWORKS[network].aptos;
|
||||
const { key } = NETWORKS[network].Aptos;
|
||||
if (!key) {
|
||||
throw new Error("No key for aptos");
|
||||
}
|
||||
rpc = rpc ?? NETWORKS[network].aptos.rpc;
|
||||
rpc = rpc ?? NETWORKS[network].Aptos.rpc;
|
||||
if (!rpc) {
|
||||
throw new Error("No rpc for aptos");
|
||||
}
|
||||
const { token_bridge } = CONTRACTS[network].aptos;
|
||||
const token_bridge = contracts.tokenBridge.get(network, "Aptos");
|
||||
if (!token_bridge) {
|
||||
throw new Error("token bridge contract is undefined");
|
||||
}
|
||||
|
@ -268,8 +267,8 @@ export async function transferAptos(
|
|||
token_bridge,
|
||||
tokenAddress === "native" ? "0x1::aptos_coin::AptosCoin" : tokenAddress,
|
||||
amount,
|
||||
dstChain,
|
||||
tryNativeToUint8Array(dstAddress, dstChain)
|
||||
toChainId(dstChain),
|
||||
tryNativeToUint8Array(dstAddress, toChainId(dstChain))
|
||||
);
|
||||
const tx = (await generateSignAndSubmitEntryFunction(
|
||||
client,
|
||||
|
@ -321,14 +320,14 @@ export function deriveResourceAccount(
|
|||
}
|
||||
|
||||
export async function callEntryFunc(
|
||||
network: "MAINNET" | "TESTNET" | "DEVNET",
|
||||
network: Network,
|
||||
rpc: string | undefined,
|
||||
module: string,
|
||||
func: string,
|
||||
ty_args: BCS.Seq<TxnBuilderTypes.TypeTag>,
|
||||
args: BCS.Seq<BCS.Bytes>
|
||||
): Promise<string> {
|
||||
let key: string | undefined = NETWORKS[network]["aptos"].key;
|
||||
let key: string | undefined = NETWORKS[network]["Aptos"].key;
|
||||
if (key === undefined) {
|
||||
throw new Error("No key for aptos");
|
||||
}
|
||||
|
@ -338,7 +337,7 @@ export async function callEntryFunc(
|
|||
if (typeof rpc != "undefined") {
|
||||
client = new AptosClient(rpc);
|
||||
} else {
|
||||
client = new AptosClient(NETWORKS[network]["aptos"].rpc);
|
||||
client = new AptosClient(NETWORKS[network]["Aptos"].rpc);
|
||||
}
|
||||
const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
|
||||
client.getAccount(accountFrom.address()),
|
||||
|
@ -388,14 +387,13 @@ export async function queryRegistrationsAptos(
|
|||
network: Network,
|
||||
module: "Core" | "NFTBridge" | "TokenBridge"
|
||||
): Promise<Object> {
|
||||
const n = NETWORKS[network]["aptos"];
|
||||
const n = NETWORKS[network]["Aptos"];
|
||||
const client = new AptosClient(n.rpc);
|
||||
const contracts = CONTRACTS[network]["aptos"];
|
||||
let stateObjectId: string | undefined;
|
||||
|
||||
switch (module) {
|
||||
case "TokenBridge":
|
||||
stateObjectId = contracts.token_bridge;
|
||||
stateObjectId = contracts.tokenBridge.get(network, "Aptos");
|
||||
if (stateObjectId === undefined) {
|
||||
throw Error(`Unknown token bridge contract on ${network} for Aptos`);
|
||||
}
|
||||
|
|
|
@ -10,25 +10,26 @@ import {
|
|||
getOriginalAssetXpla,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/token_bridge/getOriginalAsset";
|
||||
import { getOriginalAssetInjective } from "@certusone/wormhole-sdk/lib/esm/token_bridge/injective";
|
||||
import {
|
||||
ChainId,
|
||||
ChainName,
|
||||
coalesceChainName,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import { CONTRACTS } from "../../consts";
|
||||
import { Network } from "../../utils";
|
||||
import { impossible } from "../../vaa";
|
||||
import { getOriginalAssetSei } from "../sei/sdk";
|
||||
import { getProviderForChain } from "./provider";
|
||||
import {
|
||||
Chain,
|
||||
ChainId,
|
||||
Network,
|
||||
contracts,
|
||||
toChain,
|
||||
} from "@wormhole-foundation/sdk-base";
|
||||
import { toChainId } from "@wormhole-foundation/sdk";
|
||||
|
||||
export const getOriginalAsset = async (
|
||||
chain: ChainId | ChainName,
|
||||
chain: ChainId | Chain,
|
||||
network: Network,
|
||||
assetAddress: string,
|
||||
rpc?: string
|
||||
): Promise<WormholeWrappedInfo> => {
|
||||
const chainName = coalesceChainName(chain);
|
||||
const tokenBridgeAddress = CONTRACTS[network][chainName].token_bridge;
|
||||
const chainName = toChain(chain);
|
||||
const tokenBridgeAddress = contracts.tokenBridge.get(network, chainName);
|
||||
if (!tokenBridgeAddress) {
|
||||
throw new Error(
|
||||
`Token bridge address not defined for ${chainName} ${network}`
|
||||
|
@ -36,69 +37,66 @@ export const getOriginalAsset = async (
|
|||
}
|
||||
|
||||
switch (chainName) {
|
||||
case "unset":
|
||||
throw new Error("Chain not set");
|
||||
case "solana": {
|
||||
case "Solana": {
|
||||
const provider = getProviderForChain(chainName, network, { rpc });
|
||||
return getOriginalAssetSolana(provider, tokenBridgeAddress, assetAddress);
|
||||
}
|
||||
case "acala":
|
||||
case "arbitrum":
|
||||
case "aurora":
|
||||
case "avalanche":
|
||||
case "base":
|
||||
case "bsc":
|
||||
case "celo":
|
||||
case "ethereum":
|
||||
case "fantom":
|
||||
case "gnosis":
|
||||
case "karura":
|
||||
case "klaytn":
|
||||
case "moonbeam":
|
||||
case "neon":
|
||||
case "oasis":
|
||||
case "optimism":
|
||||
case "polygon":
|
||||
// case "rootstock":
|
||||
case "scroll":
|
||||
case "mantle":
|
||||
case "blast":
|
||||
case "xlayer":
|
||||
case "linea":
|
||||
case "berachain":
|
||||
case "seievm":
|
||||
case "sepolia":
|
||||
case "arbitrum_sepolia":
|
||||
case "base_sepolia":
|
||||
case "optimism_sepolia":
|
||||
case "polygon_sepolia":
|
||||
case "holesky": {
|
||||
case "Acala":
|
||||
case "Arbitrum":
|
||||
case "Aurora":
|
||||
case "Avalanche":
|
||||
case "Base":
|
||||
case "Bsc":
|
||||
case "Celo":
|
||||
case "Ethereum":
|
||||
case "Fantom":
|
||||
case "Gnosis":
|
||||
case "Karura":
|
||||
case "Klaytn":
|
||||
case "Moonbeam":
|
||||
case "Neon":
|
||||
case "Oasis":
|
||||
case "Optimism":
|
||||
case "Polygon":
|
||||
case "Scroll":
|
||||
case "Mantle":
|
||||
case "Blast":
|
||||
case "Xlayer":
|
||||
case "Linea":
|
||||
case "Berachain":
|
||||
case "Seievm":
|
||||
case "Sepolia":
|
||||
case "ArbitrumSepolia":
|
||||
case "BaseSepolia":
|
||||
case "OptimismSepolia":
|
||||
case "PolygonSepolia":
|
||||
case "Holesky": {
|
||||
const provider = getProviderForChain(chainName, network, { rpc });
|
||||
return getOriginalAssetEth(
|
||||
tokenBridgeAddress,
|
||||
provider,
|
||||
assetAddress,
|
||||
chain
|
||||
toChainId(chain)
|
||||
);
|
||||
}
|
||||
case "terra":
|
||||
case "terra2": {
|
||||
case "Terra":
|
||||
case "Terra2": {
|
||||
const provider = getProviderForChain(chainName, network, { rpc });
|
||||
return getOriginalAssetTerra(provider, assetAddress);
|
||||
}
|
||||
case "injective": {
|
||||
case "Injective": {
|
||||
const provider = getProviderForChain(chainName, network, { rpc });
|
||||
return getOriginalAssetInjective(assetAddress, provider);
|
||||
}
|
||||
case "sei": {
|
||||
case "Sei": {
|
||||
const provider = await getProviderForChain(chainName, network, { rpc });
|
||||
return getOriginalAssetSei(assetAddress, provider);
|
||||
}
|
||||
case "xpla": {
|
||||
case "Xpla": {
|
||||
const provider = getProviderForChain(chainName, network, { rpc });
|
||||
return getOriginalAssetXpla(provider, assetAddress);
|
||||
}
|
||||
case "algorand": {
|
||||
case "Algorand": {
|
||||
const provider = getProviderForChain(chainName, network, { rpc });
|
||||
return getOriginalAssetAlgorand(
|
||||
provider,
|
||||
|
@ -106,32 +104,32 @@ export const getOriginalAsset = async (
|
|||
BigInt(assetAddress)
|
||||
);
|
||||
}
|
||||
case "near": {
|
||||
case "Near": {
|
||||
const provider = await getProviderForChain(chainName, network, { rpc });
|
||||
return getOriginalAssetNear(provider, tokenBridgeAddress, assetAddress);
|
||||
}
|
||||
case "aptos": {
|
||||
case "Aptos": {
|
||||
const provider = getProviderForChain(chainName, network, { rpc });
|
||||
return getOriginalAssetAptos(provider, tokenBridgeAddress, assetAddress);
|
||||
}
|
||||
case "sui": {
|
||||
case "Sui": {
|
||||
const provider = getProviderForChain(chainName, network, { rpc });
|
||||
return getOriginalAssetSui(provider, tokenBridgeAddress, assetAddress);
|
||||
}
|
||||
case "btc":
|
||||
case "osmosis":
|
||||
case "pythnet":
|
||||
case "wormchain":
|
||||
case "cosmoshub":
|
||||
case "evmos":
|
||||
case "kujira":
|
||||
case "neutron":
|
||||
case "celestia":
|
||||
case "stargaze":
|
||||
case "seda":
|
||||
case "dymension":
|
||||
case "provenance":
|
||||
case "rootstock":
|
||||
case "Btc":
|
||||
case "Osmosis":
|
||||
case "Pythnet":
|
||||
case "Wormchain":
|
||||
case "Cosmoshub":
|
||||
case "Evmos":
|
||||
case "Kujira":
|
||||
case "Neutron":
|
||||
case "Celestia":
|
||||
case "Stargaze":
|
||||
case "Seda":
|
||||
case "Dymension":
|
||||
case "Provenance":
|
||||
case "Rootstock":
|
||||
throw new Error(`${chainName} not supported`);
|
||||
default:
|
||||
impossible(chainName);
|
||||
|
|
|
@ -9,31 +9,32 @@ import {
|
|||
getForeignAssetXpla,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/token_bridge/getForeignAsset";
|
||||
import { getForeignAssetInjective } from "@certusone/wormhole-sdk/lib/esm/token_bridge/injective";
|
||||
import { tryNativeToUint8Array } from "@certusone/wormhole-sdk/lib/esm/utils/array";
|
||||
import {
|
||||
ChainId,
|
||||
ChainName,
|
||||
coalesceChainName,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import { CONTRACTS } from "../../consts";
|
||||
import { Network } from "../../utils";
|
||||
import { impossible } from "../../vaa";
|
||||
import { getForeignAssetSei } from "../sei/sdk";
|
||||
import { getProviderForChain } from "./provider";
|
||||
import {
|
||||
Chain,
|
||||
ChainId,
|
||||
Network,
|
||||
contracts,
|
||||
toChain,
|
||||
toChainId,
|
||||
} from "@wormhole-foundation/sdk-base";
|
||||
import { tryNativeToUint8Array } from "../../sdk/array";
|
||||
|
||||
export const getWrappedAssetAddress = async (
|
||||
chain: ChainId | ChainName,
|
||||
chain: ChainId | Chain,
|
||||
network: Network,
|
||||
originChain: ChainId | ChainName,
|
||||
originChain: ChainId | Chain,
|
||||
originAddress: string,
|
||||
rpc?: string
|
||||
): Promise<string | null> => {
|
||||
const chainName = coalesceChainName(chain);
|
||||
const chainName = toChain(chain);
|
||||
const originAddressUint8Array = tryNativeToUint8Array(
|
||||
originAddress,
|
||||
originChain
|
||||
);
|
||||
const tokenBridgeAddress = CONTRACTS[network][chainName].token_bridge;
|
||||
const tokenBridgeAddress = contracts.tokenBridge.get(network, chainName);
|
||||
if (!tokenBridgeAddress) {
|
||||
throw new Error(
|
||||
`Token bridge address not defined for ${chainName} ${network}`
|
||||
|
@ -41,143 +42,141 @@ export const getWrappedAssetAddress = async (
|
|||
}
|
||||
|
||||
switch (chainName) {
|
||||
case "unset":
|
||||
throw new Error("Chain not set");
|
||||
case "solana": {
|
||||
case "Solana": {
|
||||
const provider = getProviderForChain(chainName, network, { rpc });
|
||||
return getForeignAssetSolana(
|
||||
provider,
|
||||
tokenBridgeAddress,
|
||||
originChain,
|
||||
toChainId(originChain),
|
||||
originAddressUint8Array
|
||||
);
|
||||
}
|
||||
case "acala":
|
||||
case "arbitrum":
|
||||
case "aurora":
|
||||
case "avalanche":
|
||||
case "base":
|
||||
case "bsc":
|
||||
case "celo":
|
||||
case "ethereum":
|
||||
case "fantom":
|
||||
case "gnosis":
|
||||
case "karura":
|
||||
case "klaytn":
|
||||
case "moonbeam":
|
||||
case "neon":
|
||||
case "oasis":
|
||||
case "optimism":
|
||||
case "polygon":
|
||||
// case "rootstock":
|
||||
case "scroll":
|
||||
case "mantle":
|
||||
case "blast":
|
||||
case "xlayer":
|
||||
case "linea":
|
||||
case "berachain":
|
||||
case "seievm":
|
||||
case "sepolia":
|
||||
case "arbitrum_sepolia":
|
||||
case "base_sepolia":
|
||||
case "optimism_sepolia":
|
||||
case "polygon_sepolia":
|
||||
case "holesky": {
|
||||
case "Acala":
|
||||
case "Arbitrum":
|
||||
case "Aurora":
|
||||
case "Avalanche":
|
||||
case "Base":
|
||||
case "Bsc":
|
||||
case "Celo":
|
||||
case "Ethereum":
|
||||
case "Fantom":
|
||||
case "Gnosis":
|
||||
case "Karura":
|
||||
case "Klaytn":
|
||||
case "Moonbeam":
|
||||
case "Neon":
|
||||
case "Oasis":
|
||||
case "Optimism":
|
||||
case "Polygon":
|
||||
// case "Rootstock":
|
||||
case "Scroll":
|
||||
case "Mantle":
|
||||
case "Blast":
|
||||
case "Xlayer":
|
||||
case "Linea":
|
||||
case "Berachain":
|
||||
case "Seievm":
|
||||
case "Sepolia":
|
||||
case "ArbitrumSepolia":
|
||||
case "BaseSepolia":
|
||||
case "OptimismSepolia":
|
||||
case "PolygonSepolia":
|
||||
case "Holesky": {
|
||||
const provider = getProviderForChain(chainName, network, { rpc });
|
||||
return getForeignAssetEth(
|
||||
tokenBridgeAddress,
|
||||
provider,
|
||||
originChain,
|
||||
toChainId(originChain),
|
||||
originAddressUint8Array
|
||||
);
|
||||
}
|
||||
case "terra":
|
||||
case "terra2": {
|
||||
case "Terra":
|
||||
case "Terra2": {
|
||||
const provider = getProviderForChain(chainName, network, { rpc });
|
||||
return getForeignAssetTerra(
|
||||
tokenBridgeAddress,
|
||||
provider,
|
||||
originChain,
|
||||
toChainId(originChain),
|
||||
originAddressUint8Array
|
||||
);
|
||||
}
|
||||
case "injective": {
|
||||
case "Injective": {
|
||||
const provider = getProviderForChain(chainName, network, { rpc });
|
||||
return getForeignAssetInjective(
|
||||
tokenBridgeAddress,
|
||||
provider,
|
||||
originChain,
|
||||
toChainId(originChain),
|
||||
originAddressUint8Array
|
||||
);
|
||||
}
|
||||
case "sei": {
|
||||
case "Sei": {
|
||||
const provider = await getProviderForChain(chainName, network, { rpc });
|
||||
return getForeignAssetSei(
|
||||
tokenBridgeAddress,
|
||||
provider,
|
||||
originChain,
|
||||
toChainId(originChain),
|
||||
originAddressUint8Array
|
||||
);
|
||||
}
|
||||
case "xpla": {
|
||||
case "Xpla": {
|
||||
const provider = getProviderForChain(chainName, network, { rpc });
|
||||
return getForeignAssetXpla(
|
||||
tokenBridgeAddress,
|
||||
provider,
|
||||
originChain,
|
||||
toChainId(originChain),
|
||||
originAddressUint8Array
|
||||
);
|
||||
}
|
||||
case "algorand": {
|
||||
case "Algorand": {
|
||||
const provider = getProviderForChain(chainName, network, { rpc });
|
||||
return getForeignAssetAlgorand(
|
||||
provider,
|
||||
BigInt(tokenBridgeAddress),
|
||||
originChain,
|
||||
toChainId(originChain),
|
||||
originAddress
|
||||
).then((x) => x?.toString() ?? null);
|
||||
}
|
||||
case "near": {
|
||||
case "Near": {
|
||||
const provider = await getProviderForChain(chainName, network, { rpc });
|
||||
return getForeignAssetNear(
|
||||
provider,
|
||||
tokenBridgeAddress,
|
||||
originChain,
|
||||
toChainId(originChain),
|
||||
originAddress
|
||||
);
|
||||
}
|
||||
case "aptos": {
|
||||
case "Aptos": {
|
||||
const provider = getProviderForChain(chainName, network, { rpc });
|
||||
return getForeignAssetAptos(
|
||||
provider,
|
||||
tokenBridgeAddress,
|
||||
originChain,
|
||||
toChainId(originChain),
|
||||
originAddress
|
||||
);
|
||||
}
|
||||
case "sui": {
|
||||
case "Sui": {
|
||||
const provider = getProviderForChain(chainName, network, { rpc });
|
||||
return getForeignAssetSui(
|
||||
provider,
|
||||
tokenBridgeAddress,
|
||||
originChain,
|
||||
toChainId(originChain),
|
||||
originAddressUint8Array
|
||||
);
|
||||
}
|
||||
case "btc":
|
||||
case "osmosis":
|
||||
case "pythnet":
|
||||
case "wormchain":
|
||||
case "cosmoshub":
|
||||
case "evmos":
|
||||
case "kujira":
|
||||
case "neutron":
|
||||
case "celestia":
|
||||
case "rootstock":
|
||||
case "stargaze":
|
||||
case "seda":
|
||||
case "dymension":
|
||||
case "provenance":
|
||||
case "Btc":
|
||||
case "Osmosis":
|
||||
case "Pythnet":
|
||||
case "Wormchain":
|
||||
case "Cosmoshub":
|
||||
case "Evmos":
|
||||
case "Kujira":
|
||||
case "Neutron":
|
||||
case "Celestia":
|
||||
case "Rootstock":
|
||||
case "Stargaze":
|
||||
case "Seda":
|
||||
case "Dymension":
|
||||
case "Provenance":
|
||||
throw new Error(`${chainName} not supported`);
|
||||
default:
|
||||
impossible(chainName);
|
||||
|
|
|
@ -1,20 +1,3 @@
|
|||
import {
|
||||
CHAIN_ID_ALGORAND,
|
||||
CHAIN_ID_APTOS,
|
||||
CHAIN_ID_INJECTIVE,
|
||||
CHAIN_ID_NEAR,
|
||||
CHAIN_ID_SEI,
|
||||
CHAIN_ID_SOLANA,
|
||||
CHAIN_ID_SUI,
|
||||
CHAIN_ID_TERRA,
|
||||
CHAIN_ID_TERRA2,
|
||||
CHAIN_ID_XPLA,
|
||||
ChainId,
|
||||
ChainName,
|
||||
EVMChainId,
|
||||
EVMChainName,
|
||||
coalesceChainName,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import { CosmWasmClient } from "@cosmjs/cosmwasm-stargate";
|
||||
import {
|
||||
Network as InjectiveNetwork,
|
||||
|
@ -32,104 +15,103 @@ import { ethers } from "ethers";
|
|||
import { connect } from "near-api-js";
|
||||
import { Provider as NearProvider } from "near-api-js/lib/providers";
|
||||
import { NETWORKS } from "../../consts";
|
||||
import { Network } from "../../utils";
|
||||
import { impossible } from "../../vaa";
|
||||
import {
|
||||
Chain,
|
||||
Network,
|
||||
PlatformToChains,
|
||||
} from "@wormhole-foundation/sdk-base";
|
||||
|
||||
export type ChainProvider<T extends ChainId | ChainName> = T extends
|
||||
| "algorand"
|
||||
| typeof CHAIN_ID_ALGORAND
|
||||
export type ChainProvider<T extends Chain> = T extends "Algorand"
|
||||
? Algodv2
|
||||
: T extends "aptos" | typeof CHAIN_ID_APTOS
|
||||
: T extends "Aptos"
|
||||
? AptosClient
|
||||
: T extends EVMChainName | EVMChainId
|
||||
: T extends PlatformToChains<"Evm">
|
||||
? ethers.providers.JsonRpcProvider
|
||||
: T extends "injective" | typeof CHAIN_ID_INJECTIVE
|
||||
: T extends "Injective"
|
||||
? ChainGrpcWasmApi
|
||||
: T extends "near" | typeof CHAIN_ID_NEAR
|
||||
: T extends "Near"
|
||||
? Promise<NearProvider>
|
||||
: T extends
|
||||
| "terra"
|
||||
| "terra2"
|
||||
| typeof CHAIN_ID_TERRA
|
||||
| typeof CHAIN_ID_TERRA2
|
||||
: T extends "Terra" | "Terra2"
|
||||
? TerraLCDClient
|
||||
: T extends "sei" | typeof CHAIN_ID_SEI
|
||||
: T extends "Sei"
|
||||
? Promise<CosmWasmClient>
|
||||
: T extends "solana" | typeof CHAIN_ID_SOLANA
|
||||
: T extends "Solana"
|
||||
? SolanaConnection
|
||||
: T extends "sui" | typeof CHAIN_ID_SUI
|
||||
: T extends "Sui"
|
||||
? JsonRpcProvider
|
||||
: T extends "xpla" | typeof CHAIN_ID_XPLA
|
||||
: T extends "Xpla"
|
||||
? XplaLCDClient
|
||||
: never;
|
||||
|
||||
export const getProviderForChain = <T extends ChainId | ChainName>(
|
||||
export const getProviderForChain = <T extends Chain>(
|
||||
chain: T,
|
||||
network: Network,
|
||||
options?: { rpc?: string; [opt: string]: any }
|
||||
): ChainProvider<T> => {
|
||||
const chainName = coalesceChainName(chain);
|
||||
const rpc = options?.rpc ?? NETWORKS[network][chainName].rpc;
|
||||
const rpc = options?.rpc ?? NETWORKS[network][chain].rpc;
|
||||
if (!rpc) {
|
||||
throw new Error(`No ${network} rpc defined for ${chainName}`);
|
||||
throw new Error(`No ${network} rpc defined for ${chain}`);
|
||||
}
|
||||
|
||||
switch (chainName) {
|
||||
case "unset":
|
||||
throw new Error("Chain not set");
|
||||
case "solana":
|
||||
switch (chain) {
|
||||
case "Solana":
|
||||
return new SolanaConnection(rpc, "confirmed") as ChainProvider<T>;
|
||||
case "acala":
|
||||
case "arbitrum":
|
||||
case "aurora":
|
||||
case "avalanche":
|
||||
case "base":
|
||||
case "bsc":
|
||||
case "celo":
|
||||
case "ethereum":
|
||||
case "fantom":
|
||||
case "gnosis":
|
||||
case "karura":
|
||||
case "klaytn":
|
||||
case "moonbeam":
|
||||
case "neon":
|
||||
case "oasis":
|
||||
case "optimism":
|
||||
case "polygon":
|
||||
// case "rootstock":
|
||||
case "scroll":
|
||||
case "mantle":
|
||||
case "blast":
|
||||
case "xlayer":
|
||||
case "linea":
|
||||
case "berachain":
|
||||
case "seievm":
|
||||
case "sepolia":
|
||||
case "arbitrum_sepolia":
|
||||
case "base_sepolia":
|
||||
case "optimism_sepolia":
|
||||
case "polygon_sepolia":
|
||||
case "holesky":
|
||||
case "Acala":
|
||||
case "Arbitrum":
|
||||
case "Aurora":
|
||||
case "Avalanche":
|
||||
case "Base":
|
||||
case "Bsc":
|
||||
case "Celo":
|
||||
case "Ethereum":
|
||||
case "Fantom":
|
||||
case "Gnosis":
|
||||
case "Karura":
|
||||
case "Klaytn":
|
||||
case "Moonbeam":
|
||||
case "Neon":
|
||||
case "Oasis":
|
||||
case "Optimism":
|
||||
case "Polygon":
|
||||
// case "Rootstock":
|
||||
case "Scroll":
|
||||
case "Mantle":
|
||||
case "Blast":
|
||||
case "Xlayer":
|
||||
case "Linea":
|
||||
case "Berachain":
|
||||
case "Seievm":
|
||||
case "Sepolia":
|
||||
case "ArbitrumSepolia":
|
||||
case "BaseSepolia":
|
||||
case "OptimismSepolia":
|
||||
case "PolygonSepolia":
|
||||
case "Holesky":
|
||||
return new ethers.providers.JsonRpcProvider(rpc) as ChainProvider<T>;
|
||||
case "terra":
|
||||
case "terra2":
|
||||
case "Terra":
|
||||
case "Terra2":
|
||||
const chain_id =
|
||||
chain === "Terra"
|
||||
? NETWORKS[network].Terra.chain_id
|
||||
: NETWORKS[network].Terra2.chain_id;
|
||||
return new TerraLCDClient({
|
||||
URL: rpc,
|
||||
chainID: NETWORKS[network][chainName].chain_id,
|
||||
isClassic: chainName === "terra",
|
||||
chainID: chain_id,
|
||||
isClassic: chain === "Terra",
|
||||
}) as ChainProvider<T>;
|
||||
case "injective": {
|
||||
case "Injective": {
|
||||
const endpoints = getNetworkEndpoints(
|
||||
network === "MAINNET"
|
||||
network === "Mainnet"
|
||||
? InjectiveNetwork.MainnetK8s
|
||||
: InjectiveNetwork.TestnetK8s
|
||||
);
|
||||
return new ChainGrpcWasmApi(endpoints.grpc) as ChainProvider<T>;
|
||||
}
|
||||
case "sei":
|
||||
case "Sei":
|
||||
return getCosmWasmClient(rpc) as ChainProvider<T>;
|
||||
case "xpla": {
|
||||
const chainId = NETWORKS[network].xpla.chain_id;
|
||||
case "Xpla": {
|
||||
const chainId = NETWORKS[network].Xpla.chain_id;
|
||||
if (!chainId) {
|
||||
throw new Error(`No ${network} chain ID defined for XPLA.`);
|
||||
}
|
||||
|
@ -139,7 +121,7 @@ export const getProviderForChain = <T extends ChainId | ChainName>(
|
|||
chainID: chainId,
|
||||
}) as ChainProvider<T>;
|
||||
}
|
||||
case "algorand": {
|
||||
case "Algorand": {
|
||||
const { token, port } = {
|
||||
...{
|
||||
token:
|
||||
|
@ -150,34 +132,34 @@ export const getProviderForChain = <T extends ChainId | ChainName>(
|
|||
};
|
||||
return new Algodv2(token, rpc, port) as ChainProvider<T>;
|
||||
}
|
||||
case "near":
|
||||
case "Near":
|
||||
return connect({
|
||||
networkId: NETWORKS[network].near.networkId,
|
||||
networkId: NETWORKS[network].Near.networkId,
|
||||
nodeUrl: rpc,
|
||||
headers: {},
|
||||
}).then(({ connection }) => connection.provider) as ChainProvider<T>;
|
||||
case "aptos":
|
||||
case "Aptos":
|
||||
return new AptosClient(rpc) as ChainProvider<T>;
|
||||
case "sui":
|
||||
case "Sui":
|
||||
return new JsonRpcProvider(
|
||||
new SuiConnection({ fullnode: rpc })
|
||||
) as ChainProvider<T>;
|
||||
case "btc":
|
||||
case "osmosis":
|
||||
case "pythnet":
|
||||
case "wormchain":
|
||||
case "cosmoshub":
|
||||
case "evmos":
|
||||
case "kujira":
|
||||
case "neutron":
|
||||
case "celestia":
|
||||
case "stargaze":
|
||||
case "seda":
|
||||
case "dymension":
|
||||
case "provenance":
|
||||
case "rootstock":
|
||||
throw new Error(`${chainName} not supported`);
|
||||
case "Btc":
|
||||
case "Osmosis":
|
||||
case "Pythnet":
|
||||
case "Wormchain":
|
||||
case "Cosmoshub":
|
||||
case "Evmos":
|
||||
case "Kujira":
|
||||
case "Neutron":
|
||||
case "Celestia":
|
||||
case "Stargaze":
|
||||
case "Seda":
|
||||
case "Dymension":
|
||||
case "Provenance":
|
||||
case "Rootstock":
|
||||
throw new Error(`${chain} not supported`);
|
||||
default:
|
||||
impossible(chainName);
|
||||
impossible(chain);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,28 +1,22 @@
|
|||
import { getCosmWasmClient } from "@sei-js/core";
|
||||
import {
|
||||
ChainName,
|
||||
CHAINS,
|
||||
CONTRACTS,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import { NETWORKS } from "../../consts/networks";
|
||||
import { Network } from "../../utils";
|
||||
import { Chain, Network, chains, contracts } from "@wormhole-foundation/sdk";
|
||||
|
||||
export async function queryRegistrationsSei(
|
||||
network: Network,
|
||||
module: "Core" | "NFTBridge" | "TokenBridge"
|
||||
): Promise<Object> {
|
||||
const chain = "sei" as ChainName;
|
||||
const chain: Chain = "Sei";
|
||||
const n = NETWORKS[network][chain];
|
||||
const contracts = CONTRACTS[network][chain];
|
||||
|
||||
let target_contract: string | undefined;
|
||||
|
||||
switch (module) {
|
||||
case "TokenBridge":
|
||||
target_contract = contracts.token_bridge;
|
||||
target_contract = contracts.tokenBridge.get(network, chain);
|
||||
break;
|
||||
case "NFTBridge":
|
||||
target_contract = contracts.nft_bridge;
|
||||
target_contract = contracts.nftBridge.get(network, chain);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Invalid module: ${module}`);
|
||||
|
@ -41,14 +35,14 @@ export async function queryRegistrationsSei(
|
|||
|
||||
// Query the bridge registration for all the chains in parallel.
|
||||
const registrations = await Promise.all(
|
||||
Object.entries(CHAINS)
|
||||
.filter(([c_name, _]) => c_name !== chain && c_name !== "unset")
|
||||
.map(async ([c_name, c_id]) => [
|
||||
chains
|
||||
.filter((c_name) => c_name !== chain)
|
||||
.map(async (c_name) => [
|
||||
c_name,
|
||||
await (async () => {
|
||||
let query_msg = {
|
||||
chain_registration: {
|
||||
chain: c_id,
|
||||
chain: c_name,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -5,13 +5,13 @@ import {
|
|||
} from "@certusone/wormhole-sdk/lib/esm/cosmwasm/address";
|
||||
import { WormholeWrappedInfo } from "@certusone/wormhole-sdk/lib/esm/token_bridge/getOriginalAsset";
|
||||
import { hexToUint8Array } from "@certusone/wormhole-sdk/lib/esm/utils/array";
|
||||
import {
|
||||
CHAIN_ID_SEI,
|
||||
ChainId,
|
||||
ChainName,
|
||||
coalesceChainId,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import { CosmWasmClient } from "@cosmjs/cosmwasm-stargate";
|
||||
import {
|
||||
Chain,
|
||||
ChainId,
|
||||
chainToChainId,
|
||||
toChainId,
|
||||
} from "@wormhole-foundation/sdk";
|
||||
import { fromUint8Array } from "js-base64";
|
||||
|
||||
/**
|
||||
|
@ -25,7 +25,7 @@ import { fromUint8Array } from "js-base64";
|
|||
export async function getForeignAssetSei(
|
||||
tokenBridgeAddress: string,
|
||||
cosmwasmClient: CosmWasmClient,
|
||||
originChain: ChainId | ChainName,
|
||||
originChain: ChainId | Chain,
|
||||
originAsset: Uint8Array
|
||||
): Promise<string | null> {
|
||||
try {
|
||||
|
@ -33,7 +33,7 @@ export async function getForeignAssetSei(
|
|||
tokenBridgeAddress,
|
||||
{
|
||||
wrapped_registry: {
|
||||
chain: coalesceChainId(originChain),
|
||||
chain: toChainId(originChain),
|
||||
address: fromUint8Array(originAsset),
|
||||
},
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ export async function getOriginalAssetSei(
|
|||
wrappedAddress: string,
|
||||
client: CosmWasmClient
|
||||
): Promise<WormholeWrappedInfo> {
|
||||
const chainId = CHAIN_ID_SEI;
|
||||
const chainId = chainToChainId("Sei");
|
||||
if (isNativeCosmWasmDenom(chainId, wrappedAddress)) {
|
||||
return {
|
||||
isWrapped: false,
|
||||
|
|
|
@ -5,10 +5,9 @@ import { toUtf8 } from "@cosmjs/encoding";
|
|||
import { MsgExecuteContract } from "cosmjs-types/cosmwasm/wasm/v1/tx";
|
||||
import { getSigningCosmWasmClient } from "@sei-js/core";
|
||||
|
||||
import { CONTRACTS } from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import { NETWORKS } from "../../consts";
|
||||
import { Network } from "../../utils";
|
||||
import { impossible, Payload } from "../../vaa";
|
||||
import { contracts, Network } from "@wormhole-foundation/sdk";
|
||||
|
||||
export const submit = async (
|
||||
payload: Payload,
|
||||
|
@ -16,8 +15,7 @@ export const submit = async (
|
|||
network: Network,
|
||||
rpc?: string
|
||||
) => {
|
||||
const contracts = CONTRACTS[network].sei;
|
||||
const networkInfo = NETWORKS[network].sei;
|
||||
const networkInfo = NETWORKS[network].Sei;
|
||||
rpc = rpc || networkInfo.rpc;
|
||||
const key = networkInfo.key;
|
||||
if (!key) {
|
||||
|
@ -32,12 +30,12 @@ export const submit = async (
|
|||
let execute_msg: object;
|
||||
switch (payload.module) {
|
||||
case "Core": {
|
||||
if (!contracts.core) {
|
||||
const core = contracts.coreBridge.get(network, "Sei");
|
||||
if (!core) {
|
||||
throw new Error(`Core bridge address not defined for Sei ${network}`);
|
||||
}
|
||||
|
||||
target_contract = contracts.core;
|
||||
// sigh...
|
||||
target_contract = core;
|
||||
execute_msg = {
|
||||
submit_v_a_a: {
|
||||
vaa: vaa.toString("base64"),
|
||||
|
@ -59,14 +57,12 @@ export const submit = async (
|
|||
break;
|
||||
}
|
||||
case "NFTBridge": {
|
||||
if (!contracts.nft_bridge) {
|
||||
// NOTE: this code can safely be removed once the sei NFT bridge is
|
||||
// released, but it's fine for it to stay, as the condition will just be
|
||||
// skipped once 'contracts.nft_bridge' is defined
|
||||
const nft = contracts.nftBridge.get(network, "Sei");
|
||||
if (!nft) {
|
||||
throw new Error("NFT bridge not supported yet for Sei");
|
||||
}
|
||||
|
||||
target_contract = contracts.nft_bridge;
|
||||
target_contract = nft;
|
||||
execute_msg = {
|
||||
submit_vaa: {
|
||||
data: vaa.toString("base64"),
|
||||
|
@ -91,11 +87,12 @@ export const submit = async (
|
|||
break;
|
||||
}
|
||||
case "TokenBridge": {
|
||||
if (!contracts.token_bridge) {
|
||||
const tb = contracts.tokenBridge.get(network, "Sei");
|
||||
if (!tb) {
|
||||
throw new Error(`Token bridge address not defined for Sei ${network}`);
|
||||
}
|
||||
|
||||
target_contract = contracts.token_bridge;
|
||||
target_contract = tb;
|
||||
execute_msg = {
|
||||
submit_vaa: {
|
||||
data: vaa.toString("base64"),
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { JsonRpcProvider } from "@mysten/sui.js";
|
||||
import fs from "fs";
|
||||
import { Network } from "../../utils";
|
||||
import { MoveToml } from "./MoveToml";
|
||||
import {
|
||||
buildPackage,
|
||||
|
@ -12,6 +11,7 @@ import {
|
|||
} from "./publish";
|
||||
import { SuiBuildOutput } from "./types";
|
||||
import { getPackageId } from "./utils";
|
||||
import { Network } from "@wormhole-foundation/sdk";
|
||||
|
||||
export const buildCoin = async (
|
||||
provider: JsonRpcProvider,
|
||||
|
@ -93,8 +93,8 @@ const setupCoin = (
|
|||
for (const dependencyPath of paths) {
|
||||
// todo(aki): the 4th param is a hack that makes this work, but doesn't
|
||||
// necessarily make sense. We should probably revisit this later.
|
||||
setupMainToml(dependencyPath, network, false, network !== "DEVNET");
|
||||
if (network === "DEVNET") {
|
||||
setupMainToml(dependencyPath, network, false, network !== "Devnet");
|
||||
if (network === "Devnet") {
|
||||
const dependencyToml = new MoveToml(getDefaultTomlPath(dependencyPath));
|
||||
switch (getPackageNameFromPath(dependencyPath)) {
|
||||
case "wormhole":
|
||||
|
|
|
@ -8,10 +8,10 @@ import {
|
|||
import { execSync } from "child_process";
|
||||
import fs from "fs";
|
||||
import { resolve } from "path";
|
||||
import { Network } from "../../utils";
|
||||
import { MoveToml } from "./MoveToml";
|
||||
import { SuiBuildOutput } from "./types";
|
||||
import { executeTransactionBlock } from "./utils";
|
||||
import { Network } from "@wormhole-foundation/sdk";
|
||||
|
||||
export const buildPackage = (packagePath: string): SuiBuildOutput => {
|
||||
if (!fs.existsSync(packagePath)) {
|
||||
|
@ -76,7 +76,7 @@ export const publishPackage = async (
|
|||
|
||||
// Publish contracts
|
||||
const tx = new TransactionBlock();
|
||||
if (network === "DEVNET") {
|
||||
if (network === "Devnet") {
|
||||
// Avoid Error checking transaction input objects: GasBudgetTooHigh { gas_budget: 50000000000, max_budget: 10000000000 }
|
||||
tx.setGasBudget(10000000000);
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ export const setupMainToml = (
|
|||
// don't have to manually reset them repeatedly during local development.
|
||||
// This is not recursive because we assume that packages are deployed bottom
|
||||
// up.
|
||||
if (!isDependency && network === "DEVNET") {
|
||||
if (!isDependency && network === "Devnet") {
|
||||
resetNetworkToml(packagePath, network);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,25 +1,24 @@
|
|||
import { getObjectFields } from "@certusone/wormhole-sdk/lib/esm/sui";
|
||||
import {
|
||||
CHAIN_ID_TO_NAME,
|
||||
CONTRACTS,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import { NETWORKS } from "../../consts/networks";
|
||||
import { Network } from "../../utils";
|
||||
import { getProvider } from "./utils";
|
||||
import { ChainId } from "@certusone/wormhole-sdk";
|
||||
import {
|
||||
ChainId,
|
||||
Network,
|
||||
chainIdToChain,
|
||||
contracts,
|
||||
} from "@wormhole-foundation/sdk";
|
||||
|
||||
export async function queryRegistrationsSui(
|
||||
network: Network,
|
||||
module: "Core" | "NFTBridge" | "TokenBridge"
|
||||
): Promise<Object> {
|
||||
const n = NETWORKS[network]["sui"];
|
||||
const n = NETWORKS[network]["Sui"];
|
||||
const provider = getProvider(network, n.rpc);
|
||||
const contracts = CONTRACTS[network]["sui"];
|
||||
let state_object_id: string;
|
||||
|
||||
switch (module) {
|
||||
case "TokenBridge":
|
||||
state_object_id = contracts.token_bridge;
|
||||
state_object_id = contracts.tokenBridge(network, "Sui");
|
||||
if (state_object_id === undefined) {
|
||||
throw Error(`Unknown token bridge contract on ${network} for Sui`);
|
||||
}
|
||||
|
@ -49,7 +48,7 @@ export async function queryRegistrationsSui(
|
|||
const emitterAddress: Uint8Array =
|
||||
emitter.data?.content?.fields.value.fields.value.fields.data;
|
||||
const emitterAddrStr = Buffer.from(emitterAddress).toString("hex");
|
||||
results[CHAIN_ID_TO_NAME[chainId]] = emitterAddrStr;
|
||||
results[chainIdToChain(chainId)] = emitterAddrStr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,16 +6,7 @@ import {
|
|||
createWrappedOnSui,
|
||||
createWrappedOnSuiPrepare,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/token_bridge/createWrapped";
|
||||
import { getForeignAssetSui } from "@certusone/wormhole-sdk/lib/esm/token_bridge/getForeignAsset";
|
||||
import {
|
||||
CHAIN_ID_SUI,
|
||||
CHAIN_ID_TO_NAME,
|
||||
CONTRACTS,
|
||||
assertChain,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import { parseAttestMetaVaa } from "@certusone/wormhole-sdk/lib/esm/vaa/tokenBridge";
|
||||
import { SUI_CLOCK_OBJECT_ID, TransactionBlock } from "@mysten/sui.js";
|
||||
import { Network } from "../../utils";
|
||||
import { Payload, impossible } from "../../vaa";
|
||||
import {
|
||||
assertSuccess,
|
||||
|
@ -28,6 +19,15 @@ import {
|
|||
registerChain,
|
||||
setMaxGasBudgetDevnet,
|
||||
} from "./utils";
|
||||
import {
|
||||
Chain,
|
||||
Network,
|
||||
VAA,
|
||||
assertChain,
|
||||
contracts,
|
||||
deserialize,
|
||||
} from "@wormhole-foundation/sdk";
|
||||
import { getForeignAssetSui } from "../../sdk/sui";
|
||||
|
||||
export const submit = async (
|
||||
payload: Payload,
|
||||
|
@ -39,13 +39,13 @@ export const submit = async (
|
|||
const consoleWarnTemp = console.warn;
|
||||
console.warn = () => {};
|
||||
|
||||
const chain = CHAIN_ID_TO_NAME[CHAIN_ID_SUI];
|
||||
const chain: Chain = "Sui";
|
||||
const provider = getProvider(network, rpc);
|
||||
const signer = getSigner(provider, network, privateKey);
|
||||
|
||||
switch (payload.module) {
|
||||
case "Core": {
|
||||
const coreObjectId = CONTRACTS[network][chain].core;
|
||||
const coreObjectId = contracts.coreBridge.get(network, chain);
|
||||
if (!coreObjectId) {
|
||||
throw Error("Core bridge object ID is undefined");
|
||||
}
|
||||
|
@ -103,12 +103,15 @@ export const submit = async (
|
|||
throw new Error("NFT bridge not supported on Sui");
|
||||
}
|
||||
case "TokenBridge": {
|
||||
const coreBridgeStateObjectId = CONTRACTS[network][chain].core;
|
||||
const coreBridgeStateObjectId = contracts.coreBridge.get(network, chain);
|
||||
if (!coreBridgeStateObjectId) {
|
||||
throw Error("Core bridge object ID is undefined");
|
||||
}
|
||||
|
||||
const tokenBridgeStateObjectId = CONTRACTS[network][chain].token_bridge;
|
||||
const tokenBridgeStateObjectId = contracts.tokenBridge.get(
|
||||
network,
|
||||
chain
|
||||
);
|
||||
if (!tokenBridgeStateObjectId) {
|
||||
throw Error("Token bridge object ID is undefined");
|
||||
}
|
||||
|
@ -116,13 +119,19 @@ export const submit = async (
|
|||
switch (payload.type) {
|
||||
case "AttestMeta": {
|
||||
// Test attest VAA: 01000000000100d87023087588d8a482d6082c57f3c93649c9a61a98848fc3a0b271f4041394ff7b28abefc8e5e19b83f45243d073d677e122e41425c2dbae3eb5ae1c7c0ac0ee01000000c056a8000000020000000000000000000000000290fb167208af455bb137780163b7b7a9a10c16000000000000000001020000000000000000000000002d8be6bf0baa74e0a907016679cae9190e80dd0a000212544b4e0000000000000000000000000000000000000000000000000000000000457468657265756d205465737420546f6b656e00000000000000000000000000
|
||||
const { tokenChain, tokenAddress } = parseAttestMetaVaa(vaa);
|
||||
const parsedAttest: VAA<"TokenBridge:AttestMeta"> = deserialize(
|
||||
"TokenBridge:AttestMeta",
|
||||
vaa
|
||||
);
|
||||
const tokenChain = parsedAttest.payload.token.chain;
|
||||
assertChain(tokenChain);
|
||||
const tokenAddress = parsedAttest.payload.token.address;
|
||||
const decimals = parsedAttest.payload.decimals;
|
||||
const coinType = await getForeignAssetSui(
|
||||
provider,
|
||||
tokenBridgeStateObjectId,
|
||||
tokenChain,
|
||||
tokenAddress
|
||||
tokenAddress.toUint8Array()
|
||||
);
|
||||
if (coinType) {
|
||||
// Coin already exists, so we update it
|
||||
|
@ -135,7 +144,7 @@ export const submit = async (
|
|||
provider,
|
||||
coreBridgeStateObjectId,
|
||||
tokenBridgeStateObjectId,
|
||||
parseAttestMetaVaa(vaa).decimals,
|
||||
decimals,
|
||||
await signer.getAddress()
|
||||
);
|
||||
setMaxGasBudgetDevnet(network, prepareTx);
|
||||
|
@ -153,7 +162,7 @@ export const submit = async (
|
|||
console.log(` Published to ${coinPackageId}`);
|
||||
console.log(` Type ${getWrappedCoinType(coinPackageId)}`);
|
||||
|
||||
if (!rpc && network !== "DEVNET") {
|
||||
if (!rpc && network !== "Devnet") {
|
||||
// Wait for wrapped asset creation to be propagated to other
|
||||
// nodes in case this complete registration call is load balanced
|
||||
// to another node.
|
||||
|
|
|
@ -6,24 +6,26 @@ import {
|
|||
setMaxGasBudgetDevnet,
|
||||
} from "./utils";
|
||||
import {
|
||||
CONTRACTS,
|
||||
ChainName,
|
||||
Chain,
|
||||
Network,
|
||||
tryNativeToUint8Array,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils";
|
||||
chainToChainId,
|
||||
contracts,
|
||||
} from "@wormhole-foundation/sdk-base";
|
||||
import { tryNativeToUint8Array } from "../../sdk/array";
|
||||
|
||||
export async function transferSui(
|
||||
dstChain: ChainName,
|
||||
dstChain: Chain,
|
||||
dstAddress: string,
|
||||
tokenAddress: string,
|
||||
amount: string,
|
||||
network: Network,
|
||||
rpc: string
|
||||
) {
|
||||
const { core, token_bridge } = CONTRACTS[network]["sui"];
|
||||
const core = contracts.coreBridge(network, "Sui");
|
||||
if (!core) {
|
||||
throw Error("Core bridge object ID is undefined");
|
||||
}
|
||||
const token_bridge = contracts.tokenBridge.get(network, "Sui");
|
||||
if (!token_bridge) {
|
||||
throw new Error("Token bridge object ID is undefined");
|
||||
}
|
||||
|
@ -44,8 +46,8 @@ export async function transferSui(
|
|||
coins,
|
||||
coinType,
|
||||
BigInt(amount),
|
||||
dstChain,
|
||||
tryNativeToUint8Array(dstAddress, dstChain)
|
||||
chainToChainId(dstChain),
|
||||
tryNativeToUint8Array(dstAddress, chainToChainId(dstChain))
|
||||
);
|
||||
setMaxGasBudgetDevnet(network, tx);
|
||||
const result = await executeTransactionBlock(signer, tx);
|
||||
|
|
|
@ -13,9 +13,10 @@ import {
|
|||
} from "@mysten/sui.js";
|
||||
import { DynamicFieldPage } from "@mysten/sui.js/dist/types/dynamic_fields";
|
||||
import { NETWORKS } from "../../consts";
|
||||
import { Network } from "../../utils";
|
||||
import { Payload, VAA, parse, serialiseVAA } from "../../vaa";
|
||||
import { SuiRpcValidationError } from "./error";
|
||||
import { Network } from "@wormhole-foundation/sdk";
|
||||
import { isValidSuiAddress } from "../../sdk/sui";
|
||||
|
||||
const UPGRADE_CAP_TYPE = "0x2::package::UpgradeCap";
|
||||
|
||||
|
@ -207,7 +208,7 @@ export const getProvider = (
|
|||
throw new Error("Must provide network or RPC to initialize provider");
|
||||
}
|
||||
|
||||
rpc = rpc || NETWORKS[network!].sui.rpc;
|
||||
rpc = rpc || NETWORKS[network!].Sui.rpc;
|
||||
if (!rpc) {
|
||||
throw new Error(`No default RPC found for Sui ${network}`);
|
||||
}
|
||||
|
@ -235,7 +236,7 @@ export const getSigner = (
|
|||
customPrivateKey?: string
|
||||
): RawSigner => {
|
||||
const privateKey: string | undefined =
|
||||
customPrivateKey || NETWORKS[network].sui.key;
|
||||
customPrivateKey || NETWORKS[network].Sui.key;
|
||||
if (!privateKey) {
|
||||
throw new Error(`No private key found for Sui ${network}`);
|
||||
}
|
||||
|
@ -323,9 +324,6 @@ export const isSuiPublishEvent = <
|
|||
event: T
|
||||
): event is K => event?.type === "published";
|
||||
|
||||
export const isValidSuiAddress = (objectId: string): boolean =>
|
||||
/^(0x)?[0-9a-f]{1,64}$/.test(objectId);
|
||||
|
||||
// todo(aki): this needs to correctly handle types such as
|
||||
// 0x2::dynamic_field::Field<0x3c6d386861470e6f9cb35f3c91f69e6c1f1737bd5d217ca06a15f582e1dc1ce3::state::MigrationControl, bool>
|
||||
export const normalizeSuiType = (type: string): string => {
|
||||
|
@ -345,7 +343,7 @@ export const registerChain = async (
|
|||
tokenBridgeStateObjectId: string,
|
||||
transactionBlock?: TransactionBlock
|
||||
): Promise<TransactionBlock> => {
|
||||
if (network === "DEVNET") {
|
||||
if (network === "Devnet") {
|
||||
// Modify the VAA to only have 1 guardian signature
|
||||
// TODO: remove this when we can deploy the devnet core contract
|
||||
// deterministically with multiple guardians in the initial guardian set
|
||||
|
@ -418,7 +416,7 @@ export const setMaxGasBudgetDevnet = (
|
|||
network: Network,
|
||||
tx: TransactionBlock
|
||||
) => {
|
||||
if (network === "DEVNET") {
|
||||
if (network === "Devnet") {
|
||||
// Avoid Error checking transaction input objects: GasBudgetTooHigh { gas_budget: 50000000000, max_budget: 10000000000 }
|
||||
tx.setGasBudget(10000000000);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,10 +1,3 @@
|
|||
import { APTOS_DEPLOYER_ADDRESS_DEVNET } from "@certusone/wormhole-sdk";
|
||||
import {
|
||||
assertChain,
|
||||
CHAIN_ID_APTOS,
|
||||
coalesceChainId,
|
||||
CONTRACTS,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import { BCS, FaucetClient } from "aptos";
|
||||
import { spawnSync } from "child_process";
|
||||
import fs from "fs";
|
||||
|
@ -25,13 +18,23 @@ import {
|
|||
RPC_OPTIONS,
|
||||
} from "../consts";
|
||||
import { runCommand, VALIDATOR_OPTIONS } from "../startValidator";
|
||||
import { assertNetwork, checkBinary, evm_address, hex } from "../utils";
|
||||
import { checkBinary, evm_address, getNetwork, hex } from "../utils";
|
||||
import {
|
||||
assertChain,
|
||||
chainToChainId,
|
||||
contracts,
|
||||
toChain,
|
||||
toChainId,
|
||||
} from "@wormhole-foundation/sdk-base";
|
||||
|
||||
const APTOS_NODE_URL = "http://0.0.0.0:8080/v1";
|
||||
const APTOS_FAUCET_URL = "http://0.0.0.0:8081";
|
||||
const README_URL =
|
||||
"https://github.com/wormhole-foundation/wormhole/blob/main/aptos/README.md";
|
||||
|
||||
export const APTOS_DEPLOYER_ADDRESS_DEVNET =
|
||||
"277fa055b6a73c42c0662d5236c65c864ccbf2d4abd21f174a30c8b786eab84b";
|
||||
|
||||
interface Package {
|
||||
meta_file: string;
|
||||
mv_files: string[];
|
||||
|
@ -56,12 +59,11 @@ export const builder = (y: typeof yargs) =>
|
|||
(yargs) =>
|
||||
yargs.option("network", NETWORK_OPTIONS).option("rpc", RPC_OPTIONS),
|
||||
async (argv) => {
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const network = getNetwork(argv.network);
|
||||
const contract_address = evm_address(
|
||||
CONTRACTS[network].aptos.token_bridge
|
||||
contracts.tokenBridge(network, "Aptos")
|
||||
);
|
||||
const rpc = argv.rpc ?? NETWORKS[network].aptos.rpc;
|
||||
const rpc = argv.rpc ?? NETWORKS[network].Aptos.rpc;
|
||||
await callEntryFunc(
|
||||
network,
|
||||
rpc,
|
||||
|
@ -82,7 +84,7 @@ export const builder = (y: typeof yargs) =>
|
|||
.option("chain-id", {
|
||||
describe: "Chain id",
|
||||
type: "number",
|
||||
default: CHAIN_ID_APTOS,
|
||||
default: chainToChainId("Aptos"),
|
||||
demandOption: false,
|
||||
})
|
||||
.option("governance-chain-id", {
|
||||
|
@ -104,10 +106,11 @@ export const builder = (y: typeof yargs) =>
|
|||
type: "string",
|
||||
}),
|
||||
async (argv) => {
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const network = getNetwork(argv.network);
|
||||
|
||||
const contract_address = evm_address(CONTRACTS[network].aptos.core);
|
||||
const contract_address = evm_address(
|
||||
contracts.coreBridge(network, "Aptos")
|
||||
);
|
||||
const guardian_addresses = argv["guardian-address"]
|
||||
.split(",")
|
||||
.map((address) => evm_address(address).substring(24));
|
||||
|
@ -127,7 +130,7 @@ export const builder = (y: typeof yargs) =>
|
|||
BCS.bcsSerializeBytes(Buffer.from(governance_address, "hex")),
|
||||
guardians_serializer.getBytes(),
|
||||
];
|
||||
const rpc = argv.rpc ?? NETWORKS[network].aptos.rpc;
|
||||
const rpc = argv.rpc ?? NETWORKS[network].Aptos.rpc;
|
||||
await callEntryFunc(
|
||||
network,
|
||||
rpc,
|
||||
|
@ -152,12 +155,11 @@ export const builder = (y: typeof yargs) =>
|
|||
.option("rpc", RPC_OPTIONS)
|
||||
.option("named-addresses", NAMED_ADDRESSES_OPTIONS),
|
||||
async (argv) => {
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const network = getNetwork(argv.network);
|
||||
checkBinary("aptos", README_URL);
|
||||
const p = buildPackage(argv["package-dir"], argv["named-addresses"]);
|
||||
const b = serializePackage(p);
|
||||
const rpc = argv.rpc ?? NETWORKS[network].aptos.rpc;
|
||||
const rpc = argv.rpc ?? NETWORKS[network].Aptos.rpc;
|
||||
await callEntryFunc(
|
||||
network,
|
||||
rpc,
|
||||
|
@ -188,21 +190,18 @@ export const builder = (y: typeof yargs) =>
|
|||
.option("rpc", RPC_OPTIONS)
|
||||
.option("named-addresses", NAMED_ADDRESSES_OPTIONS),
|
||||
async (argv) => {
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const network = getNetwork(argv.network);
|
||||
checkBinary("aptos", README_URL);
|
||||
const p = buildPackage(argv["package-dir"], argv["named-addresses"]);
|
||||
const b = serializePackage(p);
|
||||
const seed = Buffer.from(argv["seed"], "ascii");
|
||||
|
||||
// TODO(csongor): use deployer address from sdk (when it's there)
|
||||
let module_name =
|
||||
"0x277fa055b6a73c42c0662d5236c65c864ccbf2d4abd21f174a30c8b786eab84b::deployer";
|
||||
if (network == "TESTNET" || network == "MAINNET") {
|
||||
let module_name = APTOS_DEPLOYER_ADDRESS_DEVNET + "::deployer";
|
||||
if (network == "Testnet" || network == "Mainnet") {
|
||||
module_name =
|
||||
"0x0108bc32f7de18a5f6e1e7d6ee7aff9f5fc858d0d87ac0da94dd8d2a5d267d6b::deployer";
|
||||
}
|
||||
const rpc = argv.rpc ?? NETWORKS[network].aptos.rpc;
|
||||
const rpc = argv.rpc ?? NETWORKS[network].Aptos.rpc;
|
||||
await callEntryFunc(
|
||||
network,
|
||||
rpc,
|
||||
|
@ -226,13 +225,10 @@ export const builder = (y: typeof yargs) =>
|
|||
})
|
||||
.option("network", NETWORK_OPTIONS),
|
||||
async (argv) => {
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const rpc = NETWORKS[network].aptos.rpc;
|
||||
// TODO(csongor): use sdk address
|
||||
let module_name =
|
||||
"0x277fa055b6a73c42c0662d5236c65c864ccbf2d4abd21f174a30c8b786eab84b::sender";
|
||||
if (network == "TESTNET" || network == "MAINNET") {
|
||||
const network = getNetwork(argv.network);
|
||||
const rpc = NETWORKS[network].Aptos.rpc;
|
||||
let module_name = APTOS_DEPLOYER_ADDRESS_DEVNET + "::sender";
|
||||
if (network == "Testnet" || network == "Mainnet") {
|
||||
module_name =
|
||||
"0x0108bc32f7de18a5f6e1e7d6ee7aff9f5fc858d0d87ac0da94dd8d2a5d267d6b::sender";
|
||||
}
|
||||
|
@ -287,13 +283,12 @@ export const builder = (y: typeof yargs) =>
|
|||
})
|
||||
.option("network", NETWORK_OPTIONS),
|
||||
async (argv) => {
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
let address = CONTRACTS[network].aptos.token_bridge;
|
||||
const network = getNetwork(argv.network);
|
||||
let address: string = contracts.tokenBridge(network, "Aptos");
|
||||
if (address.startsWith("0x")) address = address.substring(2);
|
||||
const token_bridge_address = Buffer.from(address, "hex");
|
||||
assertChain(argv.chain);
|
||||
const chain = coalesceChainId(argv.chain);
|
||||
assertChain(toChain(argv.chain));
|
||||
const chain = toChainId(argv.chain);
|
||||
const origin_address = Buffer.from(
|
||||
evm_address(argv["origin-address"]),
|
||||
"hex"
|
||||
|
@ -343,12 +338,11 @@ export const builder = (y: typeof yargs) =>
|
|||
.option("rpc", RPC_OPTIONS)
|
||||
.option("named-addresses", NAMED_ADDRESSES_OPTIONS),
|
||||
async (argv) => {
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const network = getNetwork(argv.network);
|
||||
checkBinary("aptos", README_URL);
|
||||
const p = buildPackage(argv["package-dir"], argv["named-addresses"]);
|
||||
const b = serializePackage(p);
|
||||
const rpc = argv.rpc ?? NETWORKS[network].aptos.rpc;
|
||||
const rpc = argv.rpc ?? NETWORKS[network].Aptos.rpc;
|
||||
// TODO(csongor): use deployer address from sdk (when it's there)
|
||||
const hash = await callEntryFunc(
|
||||
network,
|
||||
|
@ -378,10 +372,9 @@ export const builder = (y: typeof yargs) =>
|
|||
.option("network", NETWORK_OPTIONS)
|
||||
.option("rpc", RPC_OPTIONS),
|
||||
async (argv) => {
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const network = getNetwork(argv.network);
|
||||
checkBinary("aptos", README_URL);
|
||||
const rpc = argv.rpc ?? NETWORKS[network].aptos.rpc;
|
||||
const rpc = argv.rpc ?? NETWORKS[network].Aptos.rpc;
|
||||
// TODO(csongor): use deployer address from sdk (when it's there)
|
||||
const hash = await callEntryFunc(
|
||||
network,
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
import yargs from "yargs";
|
||||
import { chains } from "@wormhole-foundation/sdk";
|
||||
|
||||
export const command = "chains";
|
||||
export const desc = "Print the list of supported chains";
|
||||
export const builder = (y: typeof yargs) => {
|
||||
// No positional parameters needed
|
||||
return y;
|
||||
};
|
||||
export const handler = () => {
|
||||
console.log(chains);
|
||||
};
|
|
@ -17,14 +17,14 @@
|
|||
//
|
||||
|
||||
import { Implementation__factory } from "@certusone/wormhole-sdk/lib/esm/ethers-contracts";
|
||||
import { CONTRACTS } from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import { Other } from "@certusone/wormhole-sdk/lib/esm/vaa";
|
||||
import axios from "axios";
|
||||
import { ethers } from "ethers";
|
||||
import yargs from "yargs";
|
||||
import { NETWORK_OPTIONS, NETWORKS } from "../consts";
|
||||
import { assertNetwork, Network } from "../utils";
|
||||
import { parse, Payload, serialiseVAA, sign, Signature, VAA } from "../vaa";
|
||||
import { contracts, Network } from "@wormhole-foundation/sdk-base";
|
||||
import { getNetwork } from "../utils";
|
||||
|
||||
export const command = "edit-vaa";
|
||||
export const desc = "Edits or generates a VAA";
|
||||
|
@ -102,8 +102,7 @@ export const builder = (y: typeof yargs) =>
|
|||
export const handler = async (
|
||||
argv: Awaited<ReturnType<typeof builder>["argv"]>
|
||||
) => {
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const network = getNetwork(argv.network);
|
||||
|
||||
let numSigs = 0;
|
||||
if (argv.signatures) {
|
||||
|
@ -235,8 +234,8 @@ const getGuardianSet = async (
|
|||
network: Network,
|
||||
guardianSetIndex: number
|
||||
): Promise<string[]> => {
|
||||
let n = NETWORKS[network].ethereum;
|
||||
let contract_address = CONTRACTS[network].ethereum.core;
|
||||
let n = NETWORKS[network].Ethereum;
|
||||
let contract_address = contracts.coreBridge(network, "Ethereum");
|
||||
if (contract_address === undefined) {
|
||||
throw Error(`Unknown core contract on ${network} for ethereum`);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,3 @@
|
|||
import {
|
||||
assertChain,
|
||||
assertEVMChain,
|
||||
ChainName,
|
||||
CHAINS,
|
||||
CONTRACTS,
|
||||
isEVMChain,
|
||||
toChainName,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import { ethers } from "ethers";
|
||||
import { homedir } from "os";
|
||||
import yargs from "yargs";
|
||||
|
@ -18,7 +9,13 @@ import {
|
|||
setStorageAt,
|
||||
} from "../evm";
|
||||
import { runCommand, VALIDATOR_OPTIONS } from "../startValidator";
|
||||
import { assertNetwork, evm_address } from "../utils";
|
||||
import {
|
||||
assertEVMChain,
|
||||
chainToChain,
|
||||
evm_address,
|
||||
getNetwork,
|
||||
} from "../utils";
|
||||
import { contracts, platformToChains } from "@wormhole-foundation/sdk-base";
|
||||
|
||||
export const command = "evm";
|
||||
export const desc = "EVM utilities";
|
||||
|
@ -81,12 +78,7 @@ export const builder = function (y: typeof yargs) {
|
|||
}
|
||||
)
|
||||
.command("chains", "Return all EVM chains", async (_) => {
|
||||
console.log(
|
||||
Object.values(CHAINS)
|
||||
.map((id) => toChainName(id))
|
||||
.filter((name) => isEVMChain(name))
|
||||
.join(" ")
|
||||
);
|
||||
console.log(...platformToChains("Evm"));
|
||||
})
|
||||
.command(
|
||||
"info",
|
||||
|
@ -95,8 +87,9 @@ export const builder = function (y: typeof yargs) {
|
|||
yargs
|
||||
.option("chain", {
|
||||
alias: "c",
|
||||
describe: "Chain to query",
|
||||
choices: Object.keys(CHAINS) as ChainName[],
|
||||
describe:
|
||||
"Chain to query. To see a list of supported chains, run `worm evm chains`",
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
} as const)
|
||||
.option("module", {
|
||||
|
@ -120,11 +113,9 @@ export const builder = function (y: typeof yargs) {
|
|||
demandOption: false,
|
||||
}),
|
||||
async (argv) => {
|
||||
const chain = argv.chain;
|
||||
assertChain(chain);
|
||||
const chain = chainToChain(argv.chain);
|
||||
assertEVMChain(chain);
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const network = getNetwork(argv.network);
|
||||
const module = argv.module;
|
||||
const rpc = argv.rpc ?? NETWORKS[network][chain].rpc;
|
||||
if (argv["implementation-only"]) {
|
||||
|
@ -163,7 +154,7 @@ export const builder = function (y: typeof yargs) {
|
|||
alias: "a",
|
||||
describe: "Core contract address",
|
||||
type: "string",
|
||||
default: CONTRACTS.MAINNET.ethereum.core,
|
||||
default: contracts.coreBridge("Mainnet", "Ethereum"),
|
||||
})
|
||||
.option("guardian-address", {
|
||||
alias: "g",
|
||||
|
@ -180,7 +171,7 @@ export const builder = function (y: typeof yargs) {
|
|||
}),
|
||||
async (argv) => {
|
||||
const guardian_addresses = argv["guardian-address"].split(",");
|
||||
let rpc = argv.rpc ?? NETWORKS.DEVNET.ethereum.rpc;
|
||||
let rpc = argv.rpc ?? NETWORKS.Devnet.Ethereum.rpc;
|
||||
await hijack_evm(
|
||||
rpc,
|
||||
argv["core-contract-address"],
|
||||
|
|
|
@ -1,21 +1,11 @@
|
|||
import { tryNativeToHexString } from "@certusone/wormhole-sdk/lib/esm/utils/array";
|
||||
import {
|
||||
assertChain,
|
||||
ChainName,
|
||||
CHAINS,
|
||||
isCosmWasmChain,
|
||||
isEVMChain,
|
||||
toChainId,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import { fromBech32, toHex } from "@cosmjs/encoding";
|
||||
import base58 from "bs58";
|
||||
import { sha3_256 } from "js-sha3";
|
||||
import yargs from "yargs";
|
||||
import { GOVERNANCE_CHAIN, GOVERNANCE_EMITTER } from "../consts";
|
||||
import { evm_address } from "../utils";
|
||||
import { chainToChain, evm_address } from "../utils";
|
||||
import {
|
||||
ContractUpgrade,
|
||||
impossible,
|
||||
Payload,
|
||||
PortalRegisterChain,
|
||||
RecoverChainId,
|
||||
|
@ -25,6 +15,11 @@ import {
|
|||
VAA,
|
||||
WormholeRelayerSetDefaultDeliveryProvider,
|
||||
} from "../vaa";
|
||||
import {
|
||||
Chain,
|
||||
chainToPlatform,
|
||||
toChainId,
|
||||
} from "@wormhole-foundation/sdk-base";
|
||||
|
||||
function makeVAA(
|
||||
emitterChain: number,
|
||||
|
@ -67,8 +62,9 @@ export const builder = function (y: typeof yargs) {
|
|||
yargs
|
||||
.option("chain", {
|
||||
alias: "c",
|
||||
describe: "Chain to register",
|
||||
choices: Object.keys(CHAINS) as ChainName[],
|
||||
describe:
|
||||
"Chain to register. To see a list of supported chains, run `worm chains`",
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
} as const)
|
||||
.option("contract-address", {
|
||||
|
@ -85,13 +81,13 @@ export const builder = function (y: typeof yargs) {
|
|||
} as const),
|
||||
(argv) => {
|
||||
const module = argv["module"];
|
||||
assertChain(argv.chain);
|
||||
const chain = chainToChain(argv.chain);
|
||||
const payload: PortalRegisterChain<typeof module> = {
|
||||
module,
|
||||
type: "RegisterChain",
|
||||
chain: 0,
|
||||
emitterChain: toChainId(argv.chain),
|
||||
emitterAddress: parseAddress(argv.chain, argv["contract-address"]),
|
||||
emitterChain: toChainId(chain),
|
||||
emitterAddress: parseAddress(chain, argv["contract-address"]),
|
||||
};
|
||||
const vaa = makeVAA(
|
||||
GOVERNANCE_CHAIN,
|
||||
|
@ -110,8 +106,9 @@ export const builder = function (y: typeof yargs) {
|
|||
yargs
|
||||
.option("chain", {
|
||||
alias: "c",
|
||||
describe: "Chain to upgrade",
|
||||
choices: Object.keys(CHAINS) as ChainName[],
|
||||
describe:
|
||||
"Chain to upgrade. To see a list of supported chains, run `worm chains`",
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
} as const)
|
||||
.option("contract-address", {
|
||||
|
@ -127,13 +124,13 @@ export const builder = function (y: typeof yargs) {
|
|||
demandOption: true,
|
||||
} as const),
|
||||
(argv) => {
|
||||
assertChain(argv.chain);
|
||||
const chain = chainToChain(argv.chain);
|
||||
const module = argv["module"];
|
||||
const payload: ContractUpgrade = {
|
||||
module,
|
||||
type: "ContractUpgrade",
|
||||
chain: toChainId(argv.chain),
|
||||
address: parseCodeAddress(argv.chain, argv["contract-address"]),
|
||||
chain: toChainId(chain),
|
||||
address: parseCodeAddress(chain, argv["contract-address"]),
|
||||
};
|
||||
const vaa = makeVAA(
|
||||
GOVERNANCE_CHAIN,
|
||||
|
@ -151,8 +148,9 @@ export const builder = function (y: typeof yargs) {
|
|||
yargs
|
||||
.option("emitter-chain", {
|
||||
alias: "e",
|
||||
describe: "Emitter chain of the VAA",
|
||||
choices: Object.keys(CHAINS) as ChainName[],
|
||||
describe:
|
||||
"Emitter chain of the VAA. To see a list of supported chains, run `worm chains`",
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
} as const)
|
||||
.option("emitter-address", {
|
||||
|
@ -163,8 +161,9 @@ export const builder = function (y: typeof yargs) {
|
|||
})
|
||||
.option("chain", {
|
||||
alias: "c",
|
||||
describe: "Token's chain",
|
||||
choices: Object.keys(CHAINS) as ChainName[],
|
||||
describe:
|
||||
"Token's chain. To see a list of supported chains, run `worm chains`",
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
} as const)
|
||||
.option("token-address", {
|
||||
|
@ -192,15 +191,14 @@ export const builder = function (y: typeof yargs) {
|
|||
demandOption: true,
|
||||
}),
|
||||
(argv) => {
|
||||
const emitter_chain = argv["emitter-chain"];
|
||||
assertChain(argv.chain);
|
||||
assertChain(emitter_chain);
|
||||
const emitter_chain = chainToChain(argv["emitter-chain"]);
|
||||
const chain = chainToChain(argv.chain);
|
||||
const payload: TokenBridgeAttestMeta = {
|
||||
module: "TokenBridge",
|
||||
type: "AttestMeta",
|
||||
chain: 0,
|
||||
tokenAddress: parseAddress(argv.chain, argv["token-address"]),
|
||||
tokenChain: toChainId(argv.chain),
|
||||
tokenAddress: parseAddress(chain, argv["token-address"]),
|
||||
tokenChain: toChainId(chain),
|
||||
decimals: argv["decimals"],
|
||||
symbol: argv["symbol"],
|
||||
name: argv["name"],
|
||||
|
@ -262,8 +260,9 @@ export const builder = function (y: typeof yargs) {
|
|||
return yargs
|
||||
.option("chain", {
|
||||
alias: "c",
|
||||
describe: "Chain of Wormhole Relayer contract",
|
||||
choices: Object.keys(CHAINS),
|
||||
describe:
|
||||
"Chain of Wormhole Relayer contract. To see a list of supported chains, run `worm chains`",
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
} as const)
|
||||
.option("delivery-provider-address", {
|
||||
|
@ -274,13 +273,13 @@ export const builder = function (y: typeof yargs) {
|
|||
});
|
||||
},
|
||||
(argv) => {
|
||||
assertChain(argv.chain);
|
||||
const chain = chainToChain(argv.chain);
|
||||
const payload: WormholeRelayerSetDefaultDeliveryProvider = {
|
||||
module: "WormholeRelayer",
|
||||
type: "SetDefaultDeliveryProvider",
|
||||
chain: toChainId(argv["chain"]),
|
||||
chain: toChainId(chain),
|
||||
relayProviderAddress: parseAddress(
|
||||
argv["chain"],
|
||||
chain,
|
||||
argv["delivery-provider-address"]
|
||||
),
|
||||
};
|
||||
|
@ -297,45 +296,43 @@ export const builder = function (y: typeof yargs) {
|
|||
};
|
||||
export const handler = () => {};
|
||||
|
||||
function parseAddress(chain: ChainName, address: string): string {
|
||||
if (chain === "unset") {
|
||||
throw Error("Chain unset");
|
||||
} else if (isEVMChain(chain)) {
|
||||
function parseAddress(chain: Chain, address: string): string {
|
||||
if (chainToPlatform(chain) === "Evm") {
|
||||
return "0x" + evm_address(address);
|
||||
} else if (isCosmWasmChain(chain)) {
|
||||
} else if (chainToPlatform(chain) === "Cosmwasm") {
|
||||
return "0x" + toHex(fromBech32(address).data).padStart(64, "0");
|
||||
} else if (chain === "solana" || chain === "pythnet") {
|
||||
} else if (chain === "Solana" || chain === "Pythnet") {
|
||||
return "0x" + toHex(base58.decode(address)).padStart(64, "0");
|
||||
} else if (chain === "algorand") {
|
||||
} else if (chain === "Algorand") {
|
||||
// TODO: is there a better native format for algorand?
|
||||
return "0x" + evm_address(address);
|
||||
} else if (chain === "near") {
|
||||
} else if (chain === "Near") {
|
||||
return "0x" + evm_address(address);
|
||||
} else if (chain === "sui") {
|
||||
} else if (chain === "Sui") {
|
||||
return "0x" + evm_address(address);
|
||||
} else if (chain === "aptos") {
|
||||
} else if (chain === "Aptos") {
|
||||
if (/^(0x)?[0-9a-fA-F]+$/.test(address)) {
|
||||
return "0x" + evm_address(address);
|
||||
}
|
||||
|
||||
return sha3_256(Buffer.from(address)); // address is hash of fully qualified type
|
||||
} else if (chain === "btc") {
|
||||
} else if (chain === "Btc") {
|
||||
throw Error("btc is not supported yet");
|
||||
} else if (chain === "cosmoshub") {
|
||||
} else if (chain === "Cosmoshub") {
|
||||
throw Error("cosmoshub is not supported yet");
|
||||
} else if (chain === "evmos") {
|
||||
} else if (chain === "Evmos") {
|
||||
throw Error("evmos is not supported yet");
|
||||
} else if (chain === "kujira") {
|
||||
} else if (chain === "Kujira") {
|
||||
throw Error("kujira is not supported yet");
|
||||
} else if (chain === "rootstock") {
|
||||
} else if (chain === "Rootstock") {
|
||||
throw Error("rootstock is not supported yet");
|
||||
} else {
|
||||
impossible(chain);
|
||||
throw Error(`Unsupported chain: ${chain}`);
|
||||
}
|
||||
}
|
||||
|
||||
function parseCodeAddress(chain: ChainName, address: string): string {
|
||||
if (isCosmWasmChain(chain)) {
|
||||
function parseCodeAddress(chain: Chain, address: string): string {
|
||||
if (chainToPlatform(chain) === "Cosmwasm") {
|
||||
return "0x" + parseInt(address, 10).toString(16).padStart(64, "0");
|
||||
} else {
|
||||
return parseAddress(chain, address);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// https://github.com/yargs/yargs/blob/main/docs/advanced.md#example-command-hierarchy-using-indexmjs
|
||||
import * as aptos from "./aptos";
|
||||
import * as chains from "./chains";
|
||||
import * as editVaa from "./editVaa";
|
||||
import * as evm from "./evm";
|
||||
import * as generate from "./generate";
|
||||
|
@ -17,6 +18,7 @@ import * as status from "./status";
|
|||
// Documentation about command hierarchy can be found here: https://github.com/yargs/yargs/blob/main/docs/advanced.md#example-command-hierarchy-using-indexmjs
|
||||
export const CLI_COMMAND_MODULES = [
|
||||
aptos,
|
||||
chains,
|
||||
editVaa,
|
||||
evm,
|
||||
generate,
|
||||
|
|
|
@ -1,21 +1,19 @@
|
|||
import {
|
||||
assertChain,
|
||||
coalesceChainId,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import yargs from "yargs";
|
||||
import { CHAIN_ID_OR_NAME_CHOICES } from "../../consts";
|
||||
import { chainToChain } from "../../utils";
|
||||
import { chainToChainId } from "@wormhole-foundation/sdk";
|
||||
|
||||
export const command = "chain-id <chain>";
|
||||
export const desc =
|
||||
"Print the wormhole chain ID integer associated with the specified chain name";
|
||||
export const builder = (y: typeof yargs) => {
|
||||
return y.positional("chain", {
|
||||
describe: "Chain to query",
|
||||
choices: CHAIN_ID_OR_NAME_CHOICES,
|
||||
describe:
|
||||
"Chain to query. To see a list of supported chains, run `worm chains`",
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
} as const);
|
||||
};
|
||||
export const handler = (argv: Awaited<ReturnType<typeof builder>["argv"]>) => {
|
||||
assertChain(argv.chain);
|
||||
console.log(coalesceChainId(argv.chain));
|
||||
const inputChain = chainToChain(argv.chain);
|
||||
console.log(chainToChainId(inputChain));
|
||||
};
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
import {
|
||||
CHAINS,
|
||||
ChainName,
|
||||
assertChain,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import { relayer } from "@certusone/wormhole-sdk";
|
||||
import yargs from "yargs";
|
||||
import { CONTRACTS } from "../../consts";
|
||||
import { assertNetwork } from "../../utils";
|
||||
import { impossible } from "../../vaa";
|
||||
import { contracts } from "@wormhole-foundation/sdk-base";
|
||||
import { chainToChain, getNetwork } from "../../utils";
|
||||
|
||||
export const command = "contract <network> <chain> <module>";
|
||||
export const desc = "Print contract address";
|
||||
|
@ -19,8 +13,9 @@ export const builder = (y: typeof yargs) =>
|
|||
demandOption: true,
|
||||
} as const)
|
||||
.positional("chain", {
|
||||
describe: "Chain to query",
|
||||
choices: Object.keys(CHAINS) as ChainName[],
|
||||
describe:
|
||||
"Chain to query. To see a list of supported chains, run `worm chains`",
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
} as const)
|
||||
.positional("module", {
|
||||
|
@ -31,30 +26,27 @@ export const builder = (y: typeof yargs) =>
|
|||
export const handler = async (
|
||||
argv: Awaited<ReturnType<typeof builder>["argv"]>
|
||||
) => {
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const chain = argv.chain;
|
||||
assertChain(chain);
|
||||
const network = getNetwork(argv.network);
|
||||
const chain = chainToChain(argv.chain);
|
||||
const module = argv["module"];
|
||||
|
||||
let addr: string | undefined;
|
||||
switch (module) {
|
||||
case "Core":
|
||||
addr = CONTRACTS[network][chain].core;
|
||||
addr = contracts.coreBridge.get(network, chain);
|
||||
break;
|
||||
case "NFTBridge":
|
||||
const addresses = CONTRACTS[network][chain];
|
||||
if (!("nft_bridge" in addresses)) {
|
||||
addr = contracts.nftBridge.get(network, chain);
|
||||
if (!addr) {
|
||||
throw new Error(`NFTBridge not deployed on ${chain}`);
|
||||
}
|
||||
|
||||
addr = addresses.nft_bridge;
|
||||
break;
|
||||
case "TokenBridge":
|
||||
addr = CONTRACTS[network][chain].token_bridge;
|
||||
addr = contracts.tokenBridge.get(network, chain);
|
||||
break;
|
||||
case "WormholeRelayer":
|
||||
addr = relayer.RELAYER_CONTRACTS[network][chain]?.wormholeRelayerAddress;
|
||||
addr = contracts.relayer.get(network, chain);
|
||||
break;
|
||||
default:
|
||||
impossible(module);
|
||||
|
|
|
@ -1,19 +1,15 @@
|
|||
import {
|
||||
CHAINS,
|
||||
ChainName,
|
||||
assertChain,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import yargs from "yargs";
|
||||
import { getEmitterAddress } from "../../emitter";
|
||||
import { chainToChain } from "../../utils";
|
||||
|
||||
export const command = "emitter <chain> <address>";
|
||||
export const desc = "Print address in emitter address format";
|
||||
export const builder = (y: typeof yargs) =>
|
||||
y
|
||||
.positional("chain", {
|
||||
describe: "Chain to query",
|
||||
describe:
|
||||
"Chain to query. To see a list of supported chains, run `worm chains`",
|
||||
type: "string",
|
||||
choices: Object.keys(CHAINS) as ChainName[],
|
||||
demandOption: true,
|
||||
} as const)
|
||||
.positional("address", {
|
||||
|
@ -24,6 +20,5 @@ export const builder = (y: typeof yargs) =>
|
|||
export const handler = async (
|
||||
argv: Awaited<ReturnType<typeof builder>["argv"]>
|
||||
) => {
|
||||
assertChain(argv.chain);
|
||||
console.log(await getEmitterAddress(argv.chain, argv.address));
|
||||
console.log(await getEmitterAddress(chainToChain(argv.chain), argv.address));
|
||||
};
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
import { tryUint8ArrayToNative } from "@certusone/wormhole-sdk/lib/esm/utils";
|
||||
import yargs from "yargs";
|
||||
import { getOriginalAsset } from "../../chains/generic";
|
||||
import { CHAIN_ID_OR_NAME_CHOICES, RPC_OPTIONS } from "../../consts";
|
||||
import { assertNetwork } from "../../utils";
|
||||
import { RPC_OPTIONS } from "../../consts";
|
||||
import { getNetwork, chainToChain } from "../../utils";
|
||||
import { tryUint8ArrayToNative } from "../../sdk/array";
|
||||
import { toChain } from "@wormhole-foundation/sdk-base";
|
||||
|
||||
export const command = "origin <chain> <address>";
|
||||
export const desc = `Print the origin chain and address of the asset that corresponds to the given chain and address.`;
|
||||
export const builder = (y: typeof yargs) =>
|
||||
y
|
||||
.positional("chain", {
|
||||
describe: "Chain that wrapped asset came from",
|
||||
choices: CHAIN_ID_OR_NAME_CHOICES,
|
||||
describe:
|
||||
"Chain that wrapped asset came from. To see a list of supported chains, run `worm chains`",
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
} as const)
|
||||
.positional("address", {
|
||||
|
@ -32,12 +34,15 @@ export const handler = async (
|
|||
const consoleWarnTemp = console.warn;
|
||||
console.warn = () => {};
|
||||
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const res = await getOriginalAsset(argv.chain, network, argv.address);
|
||||
const network = getNetwork(argv.network);
|
||||
const res = await getOriginalAsset(
|
||||
chainToChain(argv.chain),
|
||||
network,
|
||||
argv.address
|
||||
);
|
||||
console.log({
|
||||
...res,
|
||||
assetAddress: tryUint8ArrayToNative(res.assetAddress, res.chainId),
|
||||
assetAddress: tryUint8ArrayToNative(res.assetAddress, toChain(res.chainId)),
|
||||
});
|
||||
|
||||
console.warn = consoleWarnTemp;
|
||||
|
|
|
@ -3,16 +3,16 @@
|
|||
// is defined in the consts.ts file in the SDK (to verify that all chains // are properly registered.)
|
||||
|
||||
import yargs from "yargs";
|
||||
import {
|
||||
assertChain,
|
||||
ChainName,
|
||||
CHAINS,
|
||||
Contracts,
|
||||
CONTRACTS,
|
||||
isEVMChain,
|
||||
isTerraChain,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import { getEmitterAddress } from "../../emitter";
|
||||
import {
|
||||
Network,
|
||||
chainToPlatform,
|
||||
chains,
|
||||
contracts,
|
||||
toChain,
|
||||
} from "@wormhole-foundation/sdk-base";
|
||||
import { chainToChain, getNetwork } from "../../utils";
|
||||
import { Chain } from "@wormhole-foundation/sdk";
|
||||
|
||||
export const command = "registrations <network> <chain> <module>";
|
||||
export const desc = "Print chain registrations";
|
||||
|
@ -24,8 +24,9 @@ export const builder = (y: typeof yargs) => {
|
|||
demandOption: true,
|
||||
} as const)
|
||||
.positional("chain", {
|
||||
describe: "Chain to query",
|
||||
choices: Object.keys(CHAINS) as ChainName[],
|
||||
describe:
|
||||
"Chain to query. To see a list of supported chains, run `worm chains`",
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
} as const)
|
||||
.positional("module", {
|
||||
|
@ -45,43 +46,39 @@ export const builder = (y: typeof yargs) => {
|
|||
export const handler = async (
|
||||
argv: Awaited<ReturnType<typeof builder>["argv"]>
|
||||
) => {
|
||||
assertChain(argv.chain);
|
||||
const chain = argv.chain;
|
||||
const network = argv.network.toUpperCase();
|
||||
if (network !== "MAINNET" && network !== "TESTNET" && network !== "DEVNET") {
|
||||
throw Error(`Unknown network: ${network}`);
|
||||
}
|
||||
const chain = chainToChain(argv.chain);
|
||||
const network = getNetwork(argv.network);
|
||||
const module = argv.module;
|
||||
if (module !== "TokenBridge" && module !== "NFTBridge") {
|
||||
throw Error(`Module must be TokenBridge or NFTBridge`);
|
||||
}
|
||||
let results: object;
|
||||
if (chain === "solana") {
|
||||
if (chain === "Solana") {
|
||||
const solana = require("../../solana");
|
||||
results = await solana.queryRegistrationsSolana(network, module);
|
||||
} else if (isEVMChain(chain)) {
|
||||
} else if (chainToPlatform(chain) === "Evm") {
|
||||
const evm = require("../../evm");
|
||||
results = await evm.queryRegistrationsEvm(network, chain, module);
|
||||
} else if (isTerraChain(chain) || chain === "xpla") {
|
||||
} else if (chain === "Terra" || chain === "Terra2" || chain === "Xpla") {
|
||||
const terra = require("../../terra");
|
||||
results = await terra.queryRegistrationsTerra(network, chain, module);
|
||||
} else if (chain === "injective") {
|
||||
} else if (chain === "Injective") {
|
||||
const injective = require("../../injective");
|
||||
results = await injective.queryRegistrationsInjective(network, module);
|
||||
} else if (chain === "sei") {
|
||||
} else if (chain === "Sei") {
|
||||
const sei = require("../../chains/sei/registrations");
|
||||
results = await sei.queryRegistrationsSei(network, module);
|
||||
} else if (chain === "sui") {
|
||||
} else if (chain === "Sui") {
|
||||
const sui = require("../../chains/sui/registrations");
|
||||
results = await sui.queryRegistrationsSui(network, module);
|
||||
} else if (chain === "aptos") {
|
||||
} else if (chain === "Aptos") {
|
||||
const aptos = require("../../aptos");
|
||||
results = await aptos.queryRegistrationsAptos(network, module);
|
||||
} else {
|
||||
throw Error(`Command not supported for chain ${chain}`);
|
||||
}
|
||||
if (argv["verify"]) {
|
||||
verifyRegistrations(network, chain as string, module, results);
|
||||
verifyRegistrations(network, chain, module, results);
|
||||
} else {
|
||||
console.log(results);
|
||||
}
|
||||
|
@ -89,8 +86,8 @@ export const handler = async (
|
|||
|
||||
// verifyRegistrations takes the results returned above and verifies them against the expected values in the consts file.
|
||||
async function verifyRegistrations(
|
||||
network: "MAINNET" | "TESTNET" | "DEVNET",
|
||||
chain: string,
|
||||
network: Network,
|
||||
chain: Chain,
|
||||
module: "NFTBridge" | "TokenBridge",
|
||||
input: Object
|
||||
) {
|
||||
|
@ -104,25 +101,21 @@ async function verifyRegistrations(
|
|||
|
||||
// Loop over the chains and make sure everything is in our input, and the values match.
|
||||
const results: { [key: string]: string } = {};
|
||||
for (const chainStr in CHAINS) {
|
||||
const thisChain = chainStr as ChainName;
|
||||
if (thisChain === "unset" || thisChain === chain) {
|
||||
for (const chainStr of chains) {
|
||||
const thisChain = toChain(chainStr);
|
||||
if (thisChain === chain) {
|
||||
continue;
|
||||
}
|
||||
const contracts: Contracts = CONTRACTS[network][thisChain];
|
||||
|
||||
let expectedAddr: string | undefined;
|
||||
if (module === "TokenBridge") {
|
||||
expectedAddr = contracts.token_bridge;
|
||||
expectedAddr = contracts.tokenBridge.get(network, thisChain);
|
||||
} else {
|
||||
expectedAddr = contracts.nft_bridge;
|
||||
expectedAddr = contracts.nftBridge.get(network, thisChain);
|
||||
}
|
||||
|
||||
if (expectedAddr !== undefined) {
|
||||
expectedAddr = await getEmitterAddress(
|
||||
thisChain as ChainName,
|
||||
expectedAddr
|
||||
);
|
||||
expectedAddr = await getEmitterAddress(thisChain, expectedAddr);
|
||||
if (!expectedAddr.startsWith("0x")) {
|
||||
expectedAddr = "0x" + expectedAddr;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
import {
|
||||
CHAINS,
|
||||
ChainName,
|
||||
assertChain,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import yargs from "yargs";
|
||||
import { NETWORKS } from "../../consts";
|
||||
import { assertNetwork } from "../../utils";
|
||||
import { chainToChain, getNetwork } from "../../utils";
|
||||
|
||||
export const command = "rpc <network> <chain>";
|
||||
export const desc = "Print RPC address";
|
||||
|
@ -17,15 +12,14 @@ export const builder = (y: typeof yargs) =>
|
|||
demandOption: true,
|
||||
} as const)
|
||||
.positional("chain", {
|
||||
describe: "Chain to query",
|
||||
choices: Object.keys(CHAINS) as ChainName[],
|
||||
describe:
|
||||
"Chain to query. To see a list of supported chains, run `worm chains`",
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
} as const);
|
||||
export const handler = async (
|
||||
argv: Awaited<ReturnType<typeof builder>["argv"]>
|
||||
) => {
|
||||
assertChain(argv.chain);
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
console.log(NETWORKS[network][argv.chain].rpc);
|
||||
const network = getNetwork(argv.network);
|
||||
console.log(NETWORKS[network][chainToChain(argv.chain)].rpc);
|
||||
};
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { assertChain } from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import yargs from "yargs";
|
||||
import { getWrappedAssetAddress } from "../../chains/generic/getWrappedAssetAddress";
|
||||
import { CHAIN_ID_OR_NAME_CHOICES, RPC_OPTIONS } from "../../consts";
|
||||
import { assertNetwork } from "../../utils";
|
||||
import { RPC_OPTIONS } from "../../consts";
|
||||
import { chainToChain, getNetwork } from "../../utils";
|
||||
|
||||
export const command = "wrapped <origin-chain> <origin-address> <target-chain>";
|
||||
export const desc =
|
||||
|
@ -10,8 +9,9 @@ export const desc =
|
|||
export const builder = (y: typeof yargs) =>
|
||||
y
|
||||
.positional("origin-chain", {
|
||||
describe: "Chain that wrapped asset came from",
|
||||
choices: CHAIN_ID_OR_NAME_CHOICES,
|
||||
describe:
|
||||
"Chain that wrapped asset came from. To see a list of supported chains, run `worm chains`",
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
} as const)
|
||||
.positional("origin-address", {
|
||||
|
@ -20,8 +20,9 @@ export const builder = (y: typeof yargs) =>
|
|||
demandOption: true,
|
||||
})
|
||||
.positional("target-chain", {
|
||||
describe: "Chain to query for wrapped asset address",
|
||||
choices: CHAIN_ID_OR_NAME_CHOICES,
|
||||
describe:
|
||||
"Chain to query for wrapped asset address. To see a list of supported chains, run `worm chains`",
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
} as const)
|
||||
.option("network", {
|
||||
|
@ -42,14 +43,10 @@ export const handler = async (
|
|||
const consoleWarnTemp = console.warn;
|
||||
console.warn = () => {};
|
||||
|
||||
const originChain = argv["origin-chain"];
|
||||
const originChain = chainToChain(argv["origin-chain"]);
|
||||
const originAddress = argv["origin-address"];
|
||||
const targetChain = argv["target-chain"];
|
||||
const network = argv.network.toUpperCase();
|
||||
|
||||
assertChain(originChain);
|
||||
assertChain(targetChain);
|
||||
assertNetwork(network);
|
||||
const targetChain = chainToChain(argv["target-chain"]);
|
||||
const network = getNetwork(argv.network);
|
||||
|
||||
console.log(
|
||||
await getWrappedAssetAddress(
|
||||
|
|
|
@ -4,8 +4,9 @@ import { Account, KeyPair, connect } from "near-api-js";
|
|||
import { InMemoryKeyStore } from "near-api-js/lib/key_stores";
|
||||
import { parseSeedPhrase } from "near-seed-phrase";
|
||||
import yargs from "yargs";
|
||||
import { CONTRACTS, NETWORKS, NETWORK_OPTIONS, RPC_OPTIONS } from "../consts";
|
||||
import { assertNetwork } from "../utils";
|
||||
import { NETWORKS, NETWORK_OPTIONS, RPC_OPTIONS } from "../consts";
|
||||
import { contracts } from "@wormhole-foundation/sdk-base";
|
||||
import { getNetwork } from "../utils";
|
||||
|
||||
// Near utilities
|
||||
export const command = "near";
|
||||
|
@ -55,14 +56,12 @@ export const builder = function (y: typeof yargs) {
|
|||
demandOption: true,
|
||||
}),
|
||||
async (argv) => {
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const contracts = CONTRACTS[network].near;
|
||||
const network = getNetwork(argv.network);
|
||||
const {
|
||||
rpc: defaultRpc,
|
||||
key: defaultKey,
|
||||
networkId,
|
||||
} = NETWORKS[network].near;
|
||||
} = NETWORKS[network].Near;
|
||||
|
||||
const key =
|
||||
argv.key ??
|
||||
|
@ -80,12 +79,12 @@ export const builder = function (y: typeof yargs) {
|
|||
let target = argv.target;
|
||||
if (!argv.target && argv.module) {
|
||||
if (argv.module === "Core") {
|
||||
target = contracts.core;
|
||||
target = contracts.coreBridge(network, "Near");
|
||||
console.log("Setting target to core");
|
||||
}
|
||||
|
||||
if (argv.module === "TokenBridge") {
|
||||
target = contracts.token_bridge;
|
||||
target = contracts.tokenBridge(network, "Near");
|
||||
console.log("Setting target to token_bridge");
|
||||
}
|
||||
}
|
||||
|
@ -125,14 +124,12 @@ export const builder = function (y: typeof yargs) {
|
|||
demandOption: true,
|
||||
}),
|
||||
async (argv) => {
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const contracts = CONTRACTS[network].near;
|
||||
const network = getNetwork(argv.network);
|
||||
const {
|
||||
rpc: defaultRpc,
|
||||
key: defaultKey,
|
||||
networkId,
|
||||
} = NETWORKS[network].near;
|
||||
} = NETWORKS[network].Near;
|
||||
|
||||
const key =
|
||||
argv.key ??
|
||||
|
@ -150,12 +147,12 @@ export const builder = function (y: typeof yargs) {
|
|||
let target = argv.target;
|
||||
if (!argv.target && argv.module) {
|
||||
if (argv.module === "Core") {
|
||||
target = contracts.core;
|
||||
target = contracts.coreBridge(network, "Near");
|
||||
console.log("Setting target to core");
|
||||
}
|
||||
|
||||
if (argv.module === "TokenBridge") {
|
||||
target = contracts.token_bridge;
|
||||
target = contracts.tokenBridge(network, "Near");
|
||||
console.log("Setting target to token_bridge");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import {
|
||||
CHAINS,
|
||||
ChainName,
|
||||
assertChain,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import { relayer, Network } from "@certusone/wormhole-sdk";
|
||||
import yargs, { string } from "yargs";
|
||||
import { CONTRACTS, NETWORKS } from "../consts";
|
||||
import { assertNetwork } from "../utils";
|
||||
import { impossible } from "../vaa";
|
||||
import yargs from "yargs";
|
||||
import { ethers } from "ethers";
|
||||
import { NETWORKS } from "../consts";
|
||||
import { chainToChain, getNetwork } from "../utils";
|
||||
import {
|
||||
Chain,
|
||||
assertChain,
|
||||
chainToChainId,
|
||||
contracts,
|
||||
} from "@wormhole-foundation/sdk-base";
|
||||
import { ChainName, relayer, toChainName } from "@certusone/wormhole-sdk";
|
||||
|
||||
export const command = "status <network> <chain> <tx>";
|
||||
export const desc =
|
||||
|
@ -21,8 +21,9 @@ export const builder = (y: typeof yargs) =>
|
|||
demandOption: true,
|
||||
} as const)
|
||||
.positional("chain", {
|
||||
describe: "Source chain",
|
||||
choices: Object.keys(CHAINS) as ChainName[],
|
||||
describe:
|
||||
"Source chain. To see a list of supported chains, run `worm chains`",
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
} as const)
|
||||
.positional("tx", {
|
||||
|
@ -33,31 +34,34 @@ export const builder = (y: typeof yargs) =>
|
|||
export const handler = async (
|
||||
argv: Awaited<ReturnType<typeof builder>["argv"]>
|
||||
) => {
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const chain = argv.chain;
|
||||
const network = getNetwork(argv.network);
|
||||
const chain = chainToChain(argv.chain);
|
||||
assertChain(chain);
|
||||
|
||||
const addr =
|
||||
relayer.RELAYER_CONTRACTS[network][chain]?.wormholeRelayerAddress;
|
||||
const addr = contracts.relayer.get(network, chain);
|
||||
if (!addr) {
|
||||
throw new Error(`Wormhole Relayer not deployed on ${chain} in ${network}`);
|
||||
}
|
||||
|
||||
const sourceRPC = NETWORKS[network as Network][chain as ChainName].rpc;
|
||||
const sourceRPC = NETWORKS[network][chain].rpc;
|
||||
const sourceChainProvider = new ethers.providers.JsonRpcProvider(sourceRPC);
|
||||
const targetChainProviders = new Map<ChainName, ethers.providers.Provider>();
|
||||
for (const key in NETWORKS[network]) {
|
||||
targetChainProviders.set(
|
||||
key as ChainName,
|
||||
new ethers.providers.JsonRpcProvider(
|
||||
NETWORKS[network as Network][key as ChainName].rpc
|
||||
)
|
||||
toChainName(chainToChainId(key as Chain)),
|
||||
new ethers.providers.JsonRpcProvider(NETWORKS[network][key as Chain].rpc)
|
||||
);
|
||||
}
|
||||
|
||||
const info = await relayer.getWormholeRelayerInfo(chain, argv.tx, {
|
||||
environment: network,
|
||||
// TODO: Convert this over to sdkv2
|
||||
const v1ChainName = toChainName(chainToChainId(chain));
|
||||
const info = await relayer.getWormholeRelayerInfo(v1ChainName, argv.tx, {
|
||||
environment:
|
||||
network === "Devnet"
|
||||
? "DEVNET"
|
||||
: network === "Testnet"
|
||||
? "TESTNET"
|
||||
: "MAINNET",
|
||||
sourceChainProvider,
|
||||
targetChainProviders,
|
||||
});
|
||||
|
|
|
@ -1,15 +1,3 @@
|
|||
import {
|
||||
assertChain,
|
||||
ChainId,
|
||||
ChainName,
|
||||
CHAINS,
|
||||
coalesceChainName,
|
||||
Contracts,
|
||||
CONTRACTS,
|
||||
isEVMChain,
|
||||
isTerraChain,
|
||||
toChainName,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import yargs from "yargs";
|
||||
import { execute_algorand } from "../algorand";
|
||||
import { execute_aptos } from "../aptos";
|
||||
|
@ -21,11 +9,22 @@ import { execute_injective } from "../injective";
|
|||
import { execute_near } from "../near";
|
||||
import { execute_solana } from "../solana";
|
||||
import { execute_terra } from "../terra";
|
||||
import { assertNetwork } from "../utils";
|
||||
import { assertKnownPayload, impossible, parse, Payload, VAA } from "../vaa";
|
||||
import { assertKnownPayload, parse, Payload, VAA } from "../vaa";
|
||||
import { execute_xpla } from "../xpla";
|
||||
import { NETWORKS } from "../consts";
|
||||
import { Network } from "../utils";
|
||||
import { chainToChain, getNetwork } from "../utils";
|
||||
import {
|
||||
Chain,
|
||||
Network,
|
||||
PlatformToChains,
|
||||
assertChain,
|
||||
assertChainId,
|
||||
chainIdToChain,
|
||||
chainToPlatform,
|
||||
chains,
|
||||
contracts,
|
||||
toChain,
|
||||
} from "@wormhole-foundation/sdk";
|
||||
|
||||
export const command = "submit <vaa>";
|
||||
export const desc = "Execute a VAA";
|
||||
|
@ -38,8 +37,9 @@ export const builder = (y: typeof yargs) =>
|
|||
})
|
||||
.option("chain", {
|
||||
alias: "c",
|
||||
describe: "chain name",
|
||||
choices: Object.keys(CHAINS) as ChainName[],
|
||||
describe:
|
||||
"chain name. To see a list of supported chains, run `worm chains`",
|
||||
type: "string",
|
||||
demandOption: false,
|
||||
} as const)
|
||||
.option("network", NETWORK_OPTIONS)
|
||||
|
@ -72,8 +72,7 @@ export const handler = async (
|
|||
assertKnownPayload(parsed_vaa);
|
||||
console.log(parsed_vaa.payload);
|
||||
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const network = getNetwork(argv.network);
|
||||
|
||||
if (argv["all-chains"]) {
|
||||
if (argv.rpc) {
|
||||
|
@ -104,22 +103,34 @@ export const handler = async (
|
|||
// get VAA chain
|
||||
const vaa_chain_id =
|
||||
"chain" in parsed_vaa.payload ? parsed_vaa.payload.chain : 0;
|
||||
assertChain(vaa_chain_id);
|
||||
const vaa_chain = toChainName(vaa_chain_id);
|
||||
|
||||
// if vaa_chain_id is 0, it means the chain is not specified in the VAA.
|
||||
// We don't have a notion of an unsupported chain, so we don't want to just assert.
|
||||
let vaa_chain;
|
||||
if (vaa_chain_id !== 0) {
|
||||
assertChainId(vaa_chain_id);
|
||||
vaa_chain = chainIdToChain(vaa_chain_id);
|
||||
}
|
||||
|
||||
// get chain from command line arg
|
||||
const cli_chain = argv.chain;
|
||||
const cli_chain = argv.chain ? chainToChain(argv.chain) : argv.chain;
|
||||
|
||||
let chain: ChainName;
|
||||
let chain: Chain;
|
||||
if (cli_chain !== undefined) {
|
||||
assertChain(cli_chain);
|
||||
if (vaa_chain !== "unset" && cli_chain !== vaa_chain) {
|
||||
if (vaa_chain && cli_chain !== vaa_chain) {
|
||||
throw Error(
|
||||
`Specified target chain (${cli_chain}) does not match VAA target chain (${vaa_chain})`
|
||||
);
|
||||
}
|
||||
chain = coalesceChainName(cli_chain);
|
||||
chain = toChain(cli_chain);
|
||||
} else {
|
||||
if (!vaa_chain) {
|
||||
throw Error(
|
||||
`VAA does not specify a target chain and one was not provided, please specify one with --chain or -c`
|
||||
);
|
||||
}
|
||||
assertChain(vaa_chain);
|
||||
chain = vaa_chain;
|
||||
}
|
||||
|
||||
|
@ -139,75 +150,43 @@ async function executeSubmit(
|
|||
parsedVaa: VAA<Payload>,
|
||||
buf: Buffer,
|
||||
network: Network,
|
||||
chain: ChainName,
|
||||
chain: Chain,
|
||||
rpc: string | undefined,
|
||||
contractAddress: string | undefined
|
||||
) {
|
||||
if (chain === "unset") {
|
||||
throw Error(
|
||||
"This VAA does not specify the target chain, please provide it by hand using the '--chain' flag."
|
||||
);
|
||||
} else if (isEVMChain(chain)) {
|
||||
if (chainToPlatform(chain) === "Evm") {
|
||||
await execute_evm(
|
||||
parsedVaa.payload,
|
||||
buf,
|
||||
network,
|
||||
chain,
|
||||
chain as PlatformToChains<"Evm">,
|
||||
contractAddress,
|
||||
rpc
|
||||
);
|
||||
} else if (isTerraChain(chain)) {
|
||||
} else if (chain === "Terra" || chain === "Terra2") {
|
||||
await execute_terra(parsedVaa.payload, buf, network, chain);
|
||||
} else if (chain === "solana" || chain === "pythnet") {
|
||||
} else if (chain === "Solana" || chain === "Pythnet") {
|
||||
await execute_solana(parsedVaa, buf, network, chain);
|
||||
} else if (chain === "algorand") {
|
||||
} else if (chain === "Algorand") {
|
||||
await execute_algorand(
|
||||
parsedVaa.payload,
|
||||
new Uint8Array(Buffer.from(vaaHex, "hex")),
|
||||
network
|
||||
);
|
||||
} else if (chain === "near") {
|
||||
} else if (chain === "Near") {
|
||||
await execute_near(parsedVaa.payload, vaaHex, network);
|
||||
} else if (chain === "injective") {
|
||||
} else if (chain === "Injective") {
|
||||
await execute_injective(parsedVaa.payload, buf, network);
|
||||
} else if (chain === "xpla") {
|
||||
} else if (chain === "Xpla") {
|
||||
await execute_xpla(parsedVaa.payload, buf, network);
|
||||
} else if (chain === "sei") {
|
||||
} else if (chain === "Sei") {
|
||||
await submitSei(parsedVaa.payload, buf, network, rpc);
|
||||
} else if (chain === "osmosis") {
|
||||
throw Error("OSMOSIS is not supported yet");
|
||||
} else if (chain === "sui") {
|
||||
} else if (chain === "Sui") {
|
||||
await submitSui(parsedVaa.payload, buf, network, rpc);
|
||||
} else if (chain === "aptos") {
|
||||
} else if (chain === "Aptos") {
|
||||
await execute_aptos(parsedVaa.payload, buf, network, contractAddress, rpc);
|
||||
} else if (chain === "wormchain") {
|
||||
throw Error("Wormchain is not supported yet");
|
||||
} else if (chain === "btc") {
|
||||
throw Error("btc is not supported yet");
|
||||
} else if (chain === "cosmoshub") {
|
||||
throw Error("Cosmoshub is not supported yet");
|
||||
} else if (chain === "evmos") {
|
||||
throw Error("Evmos is not supported yet");
|
||||
} else if (chain === "kujira") {
|
||||
throw Error("kujira is not supported yet");
|
||||
} else if (chain === "neutron") {
|
||||
throw Error("neutron is not supported yet");
|
||||
} else if (chain === "celestia") {
|
||||
throw Error("celestia is not supported yet");
|
||||
} else if (chain === "stargaze") {
|
||||
throw Error("stargaze is not supported yet");
|
||||
} else if (chain === "seda") {
|
||||
throw Error("seda is not supported yet");
|
||||
} else if (chain === "dymension") {
|
||||
throw Error("dymension is not supported yet");
|
||||
} else if (chain === "provenance") {
|
||||
throw Error("provenance is not supported yet");
|
||||
} else if (chain === "rootstock") {
|
||||
throw Error("rootstock is not supported yet");
|
||||
} else {
|
||||
// If you get a type error here, hover over `chain`'s type and it tells you
|
||||
// which cases are not handled
|
||||
impossible(chain);
|
||||
throw new Error(`Unsupported chain: ${chain}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,24 +196,19 @@ async function submitToAll(
|
|||
buf: Buffer,
|
||||
network: Network
|
||||
) {
|
||||
let skip_chain: ChainName = "unset";
|
||||
let skip_chain: Chain;
|
||||
if (parsedVaa.payload.type === "RegisterChain") {
|
||||
skip_chain = toChainName(parsedVaa.payload.emitterChain as ChainId);
|
||||
skip_chain = toChain(parsedVaa.payload.emitterChain);
|
||||
} else if (parsedVaa.payload.type === "AttestMeta") {
|
||||
skip_chain = toChainName(parsedVaa.payload.tokenChain as ChainId);
|
||||
skip_chain = toChain(parsedVaa.payload.tokenChain);
|
||||
} else {
|
||||
throw Error(
|
||||
`Invalid VAA payload type (${parsedVaa.payload.type}), only "RegisterChain" and "AttestMeta" are supported with --all-chains`
|
||||
);
|
||||
}
|
||||
|
||||
for (const chainStr in CHAINS) {
|
||||
let chain = chainStr as ChainName;
|
||||
if (chain === "unset") {
|
||||
continue;
|
||||
}
|
||||
for (const chain of chains) {
|
||||
const n = NETWORKS[network][chain];
|
||||
const contracts: Contracts = CONTRACTS[network][chain];
|
||||
if (chain == skip_chain) {
|
||||
console.log(`Skipping ${chain} because it's the origin chain`);
|
||||
continue;
|
||||
|
@ -243,15 +217,11 @@ async function submitToAll(
|
|||
console.log(`Skipping ${chain} because the rpc is not defined`);
|
||||
continue;
|
||||
}
|
||||
if (!contracts) {
|
||||
console.log(
|
||||
`Skipping ${chain} because the contract entry is not defined`
|
||||
);
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
(parsedVaa.payload.module === "TokenBridge" && !contracts.token_bridge) ||
|
||||
(parsedVaa.payload.module === "NFTBridge" && !contracts.nft_bridge)
|
||||
(parsedVaa.payload.module === "TokenBridge" &&
|
||||
!contracts.tokenBridge.get(network, chain)) ||
|
||||
(parsedVaa.payload.module === "NFTBridge" &&
|
||||
!contracts.nftBridge.get(network, chain))
|
||||
) {
|
||||
console.log(`Skipping ${chain} because the contract is not defined`);
|
||||
continue;
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
import path from "path";
|
||||
import yargs from "yargs";
|
||||
import { buildCoin, getProvider } from "../../chains/sui";
|
||||
import {
|
||||
CONTRACTS,
|
||||
NETWORKS,
|
||||
NETWORK_OPTIONS,
|
||||
RPC_OPTIONS,
|
||||
} from "../../consts";
|
||||
import { assertNetwork, checkBinary } from "../../utils";
|
||||
import { NETWORKS, NETWORK_OPTIONS, RPC_OPTIONS } from "../../consts";
|
||||
import { checkBinary, getNetwork } from "../../utils";
|
||||
import { YargsAddCommandsFn } from "../Yargs";
|
||||
import { contracts } from "@wormhole-foundation/sdk";
|
||||
|
||||
const README_URL =
|
||||
"https://github.com/wormhole-foundation/wormhole/blob/main/sui/README.md";
|
||||
|
@ -58,17 +54,16 @@ export const addBuildCommands: YargsAddCommandsFn = (y: typeof yargs) =>
|
|||
async (argv) => {
|
||||
checkBinary("sui", README_URL);
|
||||
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const network = getNetwork(argv.network);
|
||||
const decimals = argv["decimals"];
|
||||
const version = argv["version-struct"];
|
||||
const packagePath =
|
||||
argv["package-path"] ??
|
||||
path.resolve(__dirname, "../../../../../sui/examples");
|
||||
const coreBridgeStateObjectId =
|
||||
argv["wormhole-state"] ?? CONTRACTS[network].sui.core;
|
||||
argv["wormhole-state"] ?? contracts.coreBridge(network, "Sui");
|
||||
const tokenBridgeStateObjectId =
|
||||
argv["token-bridge-state"] ?? CONTRACTS[network].sui.token_bridge;
|
||||
argv["token-bridge-state"] ?? contracts.tokenBridge(network, "Sui");
|
||||
|
||||
if (!coreBridgeStateObjectId) {
|
||||
throw new Error(
|
||||
|
@ -84,7 +79,7 @@ export const addBuildCommands: YargsAddCommandsFn = (y: typeof yargs) =>
|
|||
|
||||
const provider = getProvider(
|
||||
network,
|
||||
argv.rpc ?? NETWORKS[network].sui.rpc
|
||||
argv.rpc ?? NETWORKS[network].Sui.rpc
|
||||
);
|
||||
const build = await buildCoin(
|
||||
provider,
|
||||
|
|
|
@ -17,8 +17,9 @@ import {
|
|||
PRIVATE_KEY_OPTIONS,
|
||||
RPC_OPTIONS,
|
||||
} from "../../consts";
|
||||
import { Network, assertNetwork, checkBinary } from "../../utils";
|
||||
import { checkBinary, getNetwork } from "../../utils";
|
||||
import { YargsAddCommandsFn } from "../Yargs";
|
||||
import { Network } from "@wormhole-foundation/sdk";
|
||||
|
||||
const README_URL =
|
||||
"https://github.com/wormhole-foundation/wormhole/blob/main/sui/README.md";
|
||||
|
@ -42,8 +43,7 @@ export const addDeployCommands: YargsAddCommandsFn = (y: typeof yargs) =>
|
|||
checkBinary("sui", README_URL);
|
||||
|
||||
const packageDir = argv["package-dir"];
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const network = getNetwork(argv.network);
|
||||
const debug = argv.debug ?? false;
|
||||
const privateKey = argv["private-key"];
|
||||
const rpc = argv.rpc;
|
||||
|
@ -66,7 +66,7 @@ export const deploy = async (
|
|||
rpc?: string,
|
||||
privateKey?: string
|
||||
): Promise<SuiTransactionBlockResponse> => {
|
||||
rpc = rpc ?? NETWORKS[network].sui.rpc;
|
||||
rpc = rpc ?? NETWORKS[network].Sui.rpc;
|
||||
const provider = getProvider(network, rpc);
|
||||
const signer = getSigner(provider, network, privateKey);
|
||||
|
||||
|
|
|
@ -22,8 +22,9 @@ import {
|
|||
PRIVATE_KEY_OPTIONS,
|
||||
RPC_OPTIONS,
|
||||
} from "../../consts";
|
||||
import { Network, assertNetwork } from "../../utils";
|
||||
import { YargsAddCommandsFn } from "../Yargs";
|
||||
import { getNetwork } from "../../utils";
|
||||
import { Network } from "@wormhole-foundation/sdk";
|
||||
|
||||
export const addInitCommands: YargsAddCommandsFn = (y: typeof yargs) =>
|
||||
y
|
||||
|
@ -48,8 +49,7 @@ export const addInitCommands: YargsAddCommandsFn = (y: typeof yargs) =>
|
|||
.option("private-key", PRIVATE_KEY_OPTIONS)
|
||||
.option("rpc", RPC_OPTIONS),
|
||||
async (argv) => {
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const network = getNetwork(argv.network);
|
||||
const packageId = argv["package-id"];
|
||||
const wormholeStateObjectId = argv["wormhole-state"];
|
||||
const privateKey = argv["private-key"];
|
||||
|
@ -108,14 +108,13 @@ export const addInitCommands: YargsAddCommandsFn = (y: typeof yargs) =>
|
|||
.option("private-key", PRIVATE_KEY_OPTIONS)
|
||||
.option("rpc", RPC_OPTIONS),
|
||||
async (argv) => {
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const network = getNetwork(argv.network);
|
||||
const packageId = argv["package-id"];
|
||||
const wormholeStateObjectId = argv["wormhole-state"];
|
||||
const governanceChainId = argv["governance-chain-id"];
|
||||
const governanceContract = argv["governance-address"];
|
||||
const privateKey = argv["private-key"];
|
||||
const rpc = argv.rpc ?? NETWORKS[network].sui.rpc;
|
||||
const rpc = argv.rpc ?? NETWORKS[network].Sui.rpc;
|
||||
|
||||
const res = await initTokenBridge(
|
||||
network,
|
||||
|
@ -180,8 +179,7 @@ export const addInitCommands: YargsAddCommandsFn = (y: typeof yargs) =>
|
|||
.option("private-key", PRIVATE_KEY_OPTIONS)
|
||||
.option("rpc", RPC_OPTIONS),
|
||||
async (argv) => {
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const network = getNetwork(argv.network);
|
||||
const packageId = argv["package-id"];
|
||||
const initialGuardian = argv["initial-guardian"];
|
||||
const debug = argv.debug ?? false;
|
||||
|
@ -222,7 +220,7 @@ export const initExampleApp = async (
|
|||
rpc?: string,
|
||||
privateKey?: string
|
||||
): Promise<SuiTransactionBlockResponse> => {
|
||||
rpc = rpc ?? NETWORKS[network].sui.rpc;
|
||||
rpc = rpc ?? NETWORKS[network].Sui.rpc;
|
||||
const provider = getProvider(network, rpc);
|
||||
const signer = getSigner(provider, network, privateKey);
|
||||
|
||||
|
@ -244,7 +242,7 @@ export const initTokenBridge = async (
|
|||
rpc?: string,
|
||||
privateKey?: string
|
||||
): Promise<SuiTransactionBlockResponse> => {
|
||||
rpc = rpc ?? NETWORKS[network].sui.rpc;
|
||||
rpc = rpc ?? NETWORKS[network].Sui.rpc;
|
||||
const provider = getProvider(network, rpc);
|
||||
const signer = getSigner(provider, network, privateKey);
|
||||
const owner = await signer.getAddress();
|
||||
|
@ -307,7 +305,7 @@ export const initWormhole = async (
|
|||
rpc?: string,
|
||||
privateKey?: string
|
||||
): Promise<SuiTransactionBlockResponse> => {
|
||||
rpc = rpc ?? NETWORKS[network].sui.rpc;
|
||||
rpc = rpc ?? NETWORKS[network].Sui.rpc;
|
||||
const provider = getProvider(network, rpc);
|
||||
const signer = getSigner(provider, network, privateKey);
|
||||
const owner = await signer.getAddress();
|
||||
|
|
|
@ -13,8 +13,8 @@ import {
|
|||
setMaxGasBudgetDevnet,
|
||||
} from "../../chains/sui";
|
||||
import { NETWORK_OPTIONS, NETWORKS, RPC_OPTIONS } from "../../consts";
|
||||
import { assertNetwork } from "../../utils";
|
||||
import { YargsAddCommandsFn } from "../Yargs";
|
||||
import { getNetwork } from "../../utils";
|
||||
|
||||
export const addPublishMessageCommands: YargsAddCommandsFn = (
|
||||
y: typeof yargs
|
||||
|
@ -57,14 +57,13 @@ export const addPublishMessageCommands: YargsAddCommandsFn = (
|
|||
})
|
||||
.option("rpc", RPC_OPTIONS),
|
||||
async (argv) => {
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const network = getNetwork(argv.network);
|
||||
const packageId = argv["package-id"];
|
||||
const stateObjectId = argv.state;
|
||||
const wormholeStateObjectId = argv["wormhole-state"];
|
||||
const message = argv.message;
|
||||
const privateKey = argv["private-key"];
|
||||
const rpc = argv.rpc ?? NETWORKS[network].sui.rpc;
|
||||
const rpc = argv.rpc ?? NETWORKS[network].Sui.rpc;
|
||||
|
||||
const provider = getProvider(network, rpc);
|
||||
const signer = getSigner(provider, network, privateKey);
|
||||
|
|
|
@ -1,8 +1,3 @@
|
|||
import {
|
||||
ChainId,
|
||||
ChainName,
|
||||
coalesceChainName,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import { parseTokenBridgeRegisterChainVaa } from "@certusone/wormhole-sdk/lib/esm/vaa/tokenBridge";
|
||||
import {
|
||||
JsonRpcProvider,
|
||||
|
@ -36,6 +31,7 @@ import {
|
|||
import { YargsAddCommandsFn } from "../Yargs";
|
||||
import { deploy } from "./deploy";
|
||||
import { initExampleApp, initTokenBridge, initWormhole } from "./init";
|
||||
import { Chain, chainIdToChain, toChainId } from "@wormhole-foundation/sdk";
|
||||
|
||||
export const addSetupCommands: YargsAddCommandsFn = (y: typeof yargs) =>
|
||||
y.command(
|
||||
|
@ -51,9 +47,9 @@ export const addSetupCommands: YargsAddCommandsFn = (y: typeof yargs) =>
|
|||
})
|
||||
.option("rpc", RPC_OPTIONS),
|
||||
async (argv) => {
|
||||
const network = "DEVNET";
|
||||
const network = "Devnet";
|
||||
const privateKey = argv["private-key"];
|
||||
const rpc = argv.rpc ?? NETWORKS[network].sui.rpc;
|
||||
const rpc = argv.rpc ?? NETWORKS[network].Sui.rpc;
|
||||
|
||||
// Deploy core bridge
|
||||
console.log("[1/4] Deploying core bridge...");
|
||||
|
@ -200,15 +196,15 @@ export const addSetupCommands: YargsAddCommandsFn = (y: typeof yargs) =>
|
|||
dotenv.config({ path: envPath });
|
||||
|
||||
const tx = new TransactionBlock();
|
||||
setMaxGasBudgetDevnet("DEVNET", tx);
|
||||
const registrations: { chain: ChainName; module: string }[] = [];
|
||||
setMaxGasBudgetDevnet("Devnet", tx);
|
||||
const registrations: { chain: Chain; module: string }[] = [];
|
||||
for (const key in process.env) {
|
||||
if (/^REGISTER_(.+)_TOKEN_BRIDGE_VAA$/.test(key)) {
|
||||
// Get VAA info
|
||||
const vaa = Buffer.from(String(process.env[key]), "hex");
|
||||
const { foreignChain, module } =
|
||||
parseTokenBridgeRegisterChainVaa(vaa);
|
||||
const chain = coalesceChainName(foreignChain as ChainId);
|
||||
const chain = chainIdToChain(toChainId(foreignChain));
|
||||
registrations.push({ chain, module });
|
||||
|
||||
// Register
|
||||
|
|
|
@ -2,8 +2,8 @@ import { PaginatedObjectsResponse } from "@mysten/sui.js";
|
|||
import yargs from "yargs";
|
||||
import { getPackageId, getProvider } from "../../chains/sui";
|
||||
import { NETWORKS, NETWORK_OPTIONS, RPC_OPTIONS } from "../../consts";
|
||||
import { assertNetwork } from "../../utils";
|
||||
import { YargsAddCommandsFn } from "../Yargs";
|
||||
import { getNetwork } from "../../utils";
|
||||
|
||||
export const addUtilsCommands: YargsAddCommandsFn = (y: typeof yargs) =>
|
||||
y
|
||||
|
@ -20,9 +20,8 @@ export const addUtilsCommands: YargsAddCommandsFn = (y: typeof yargs) =>
|
|||
.option("network", NETWORK_OPTIONS)
|
||||
.option("rpc", RPC_OPTIONS),
|
||||
async (argv) => {
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const rpc = argv.rpc ?? NETWORKS[network].sui.rpc;
|
||||
const network = getNetwork(argv.network);
|
||||
const rpc = argv.rpc ?? NETWORKS[network].Sui.rpc;
|
||||
const owner = argv.owner;
|
||||
|
||||
const provider = getProvider(network, rpc);
|
||||
|
@ -61,9 +60,8 @@ export const addUtilsCommands: YargsAddCommandsFn = (y: typeof yargs) =>
|
|||
.option("network", NETWORK_OPTIONS)
|
||||
.option("rpc", RPC_OPTIONS),
|
||||
async (argv) => {
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const rpc = argv.rpc ?? NETWORKS[network].sui.rpc;
|
||||
const network = getNetwork(argv.network);
|
||||
const rpc = argv.rpc ?? NETWORKS[network].Sui.rpc;
|
||||
const provider = getProvider(network, rpc);
|
||||
console.log(await getPackageId(provider, argv["state-object-id"]));
|
||||
}
|
||||
|
@ -89,9 +87,8 @@ export const addUtilsCommands: YargsAddCommandsFn = (y: typeof yargs) =>
|
|||
} as const)
|
||||
.option("rpc", RPC_OPTIONS),
|
||||
async (argv) => {
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const rpc = argv.rpc ?? NETWORKS[network].sui.rpc;
|
||||
const network = getNetwork(argv.network);
|
||||
const rpc = argv.rpc ?? NETWORKS[network].Sui.rpc;
|
||||
const provider = getProvider(network, rpc);
|
||||
console.log(
|
||||
JSON.stringify(
|
||||
|
|
|
@ -1,13 +1,6 @@
|
|||
import {
|
||||
isCosmWasmChain,
|
||||
isEVMChain,
|
||||
isTerraChain,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import yargs from "yargs";
|
||||
import { impossible } from "../vaa";
|
||||
import { transferEVM } from "../evm";
|
||||
import { CHAIN_NAME_CHOICES, NETWORK_OPTIONS, NETWORKS } from "../consts";
|
||||
import { assertNetwork } from "../utils";
|
||||
import { NETWORK_OPTIONS, NETWORKS } from "../consts";
|
||||
import { transferTerra } from "../terra";
|
||||
import { transferInjective } from "../injective";
|
||||
import { transferXpla } from "../xpla";
|
||||
|
@ -16,19 +9,28 @@ import { transferAlgorand } from "../algorand";
|
|||
import { transferNear } from "../near";
|
||||
import { transferSui } from "../chains/sui/transfer";
|
||||
import { transferAptos } from "../aptos";
|
||||
import {
|
||||
Chain,
|
||||
PlatformToChains,
|
||||
chainToPlatform,
|
||||
toChain,
|
||||
} from "@wormhole-foundation/sdk-base";
|
||||
import { chainToChain, getNetwork } from "../utils";
|
||||
|
||||
export const command = "transfer";
|
||||
export const desc = "Transfer a token";
|
||||
export const builder = (y: typeof yargs) =>
|
||||
y
|
||||
.option("src-chain", {
|
||||
describe: "source chain",
|
||||
choices: CHAIN_NAME_CHOICES,
|
||||
describe:
|
||||
"source chain. To see a list of supported chains, run `worm chains`",
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
})
|
||||
.option("dst-chain", {
|
||||
describe: "destination chain",
|
||||
choices: CHAIN_NAME_CHOICES,
|
||||
describe:
|
||||
"destination chain. To see a list of supported chains, run `worm chains`",
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
})
|
||||
.option("dst-addr", {
|
||||
|
@ -58,16 +60,10 @@ export const builder = (y: typeof yargs) =>
|
|||
export const handler = async (
|
||||
argv: Awaited<ReturnType<typeof builder>["argv"]>
|
||||
) => {
|
||||
const srcChain = argv["src-chain"];
|
||||
const dstChain = argv["dst-chain"];
|
||||
if (srcChain === "unset") {
|
||||
throw new Error("source chain is unset");
|
||||
}
|
||||
if (dstChain === "unset") {
|
||||
throw new Error("destination chain is unset");
|
||||
}
|
||||
const srcChain: Chain = chainToChain(argv["src-chain"]);
|
||||
const dstChain: Chain = chainToChain(argv["dst-chain"]);
|
||||
// TODO: support transfers to sei
|
||||
if (dstChain === "sei") {
|
||||
if (dstChain === "Sei") {
|
||||
throw new Error("transfer to sei currently unsupported");
|
||||
}
|
||||
if (srcChain === dstChain) {
|
||||
|
@ -78,19 +74,18 @@ export const handler = async (
|
|||
throw new Error("amount must be greater than 0");
|
||||
}
|
||||
const tokenAddr = argv["token-addr"];
|
||||
if (tokenAddr === "native" && isCosmWasmChain(srcChain)) {
|
||||
if (tokenAddr === "native" && chainToPlatform(srcChain) === "Cosmwasm") {
|
||||
throw new Error(`token-addr must be specified for ${srcChain}`);
|
||||
}
|
||||
const dstAddr = argv["dst-addr"];
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const rpc = argv.rpc ?? NETWORKS[network][srcChain].rpc;
|
||||
const network = getNetwork(argv.network);
|
||||
const rpc = argv.rpc ?? NETWORKS[network][toChain(srcChain)].rpc;
|
||||
if (!rpc) {
|
||||
throw new Error(`No ${network} rpc defined for ${srcChain}`);
|
||||
}
|
||||
if (isEVMChain(srcChain)) {
|
||||
if (chainToPlatform(srcChain) === "Evm") {
|
||||
await transferEVM(
|
||||
srcChain,
|
||||
srcChain as PlatformToChains<"Evm">,
|
||||
dstChain,
|
||||
dstAddr,
|
||||
tokenAddr,
|
||||
|
@ -98,7 +93,7 @@ export const handler = async (
|
|||
network,
|
||||
rpc
|
||||
);
|
||||
} else if (isTerraChain(srcChain)) {
|
||||
} else if (srcChain === "Terra" || srcChain === "Terra2") {
|
||||
await transferTerra(
|
||||
srcChain,
|
||||
dstChain,
|
||||
|
@ -108,7 +103,7 @@ export const handler = async (
|
|||
network,
|
||||
rpc
|
||||
);
|
||||
} else if (srcChain === "solana" || srcChain === "pythnet") {
|
||||
} else if (srcChain === "Solana" || srcChain === "Pythnet") {
|
||||
await transferSolana(
|
||||
srcChain,
|
||||
dstChain,
|
||||
|
@ -118,49 +113,19 @@ export const handler = async (
|
|||
network,
|
||||
rpc
|
||||
);
|
||||
} else if (srcChain === "algorand") {
|
||||
} else if (srcChain === "Algorand") {
|
||||
await transferAlgorand(dstChain, dstAddr, tokenAddr, amount, network, rpc);
|
||||
} else if (srcChain === "near") {
|
||||
} else if (srcChain === "Near") {
|
||||
await transferNear(dstChain, dstAddr, tokenAddr, amount, network, rpc);
|
||||
} else if (srcChain === "injective") {
|
||||
} else if (srcChain === "Injective") {
|
||||
await transferInjective(dstChain, dstAddr, tokenAddr, amount, network, rpc);
|
||||
} else if (srcChain === "xpla") {
|
||||
} else if (srcChain === "Xpla") {
|
||||
await transferXpla(dstChain, dstAddr, tokenAddr, amount, network, rpc);
|
||||
} else if (srcChain === "sei") {
|
||||
throw new Error("sei is not supported yet");
|
||||
} else if (srcChain === "osmosis") {
|
||||
throw Error("OSMOSIS is not supported yet");
|
||||
} else if (srcChain === "sui") {
|
||||
} else if (srcChain === "Sui") {
|
||||
await transferSui(dstChain, dstAddr, tokenAddr, amount, network, rpc);
|
||||
} else if (srcChain === "aptos") {
|
||||
} else if (srcChain === "Aptos") {
|
||||
await transferAptos(dstChain, dstAddr, tokenAddr, amount, network, rpc);
|
||||
} else if (srcChain === "wormchain") {
|
||||
throw Error("Wormchain is not supported yet");
|
||||
} else if (srcChain === "btc") {
|
||||
throw Error("btc is not supported yet");
|
||||
} else if (srcChain === "cosmoshub") {
|
||||
throw Error("cosmoshub is not supported yet");
|
||||
} else if (srcChain === "evmos") {
|
||||
throw Error("evmos is not supported yet");
|
||||
} else if (srcChain === "kujira") {
|
||||
throw Error("kujira is not supported yet");
|
||||
} else if (srcChain === "neutron") {
|
||||
throw Error("neutron is not supported yet");
|
||||
} else if (srcChain === "celestia") {
|
||||
throw Error("celestia is not supported yet");
|
||||
} else if (srcChain === "stargaze") {
|
||||
throw Error("stargaze is not supported yet");
|
||||
} else if (srcChain === "seda") {
|
||||
throw Error("seda is not supported yet");
|
||||
} else if (srcChain === "dymension") {
|
||||
throw Error("dymension is not supported yet");
|
||||
} else if (srcChain === "provenance") {
|
||||
throw Error("provenance is not supported yet");
|
||||
} else if (srcChain === "rootstock") {
|
||||
throw Error("rootstock is not supported yet");
|
||||
} else {
|
||||
// If you get a type error here, hover over `chain`'s type and it tells you
|
||||
// which cases are not handled
|
||||
impossible(srcChain);
|
||||
throw new Error(`${srcChain} is not supported yet`);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
// The verify-vaa command invokes the parseAndVerifyVM method on the core contract on Ethereum to verify the specified VAA.
|
||||
|
||||
import { Implementation__factory } from "@certusone/wormhole-sdk/lib/esm/ethers-contracts";
|
||||
import { CONTRACTS } from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import { ethers } from "ethers";
|
||||
import yargs from "yargs";
|
||||
import { NETWORKS, NETWORK_OPTIONS } from "../consts";
|
||||
import { assertNetwork } from "../utils";
|
||||
import { getNetwork } from "../utils";
|
||||
import { contracts } from "@wormhole-foundation/sdk";
|
||||
|
||||
export const command = "verify-vaa";
|
||||
export const desc = "Verifies a VAA by querying the core contract on Ethereum";
|
||||
|
@ -21,17 +21,16 @@ export const builder = (y: typeof yargs) =>
|
|||
export const handler = async (
|
||||
argv: Awaited<ReturnType<typeof builder>["argv"]>
|
||||
) => {
|
||||
const network = argv.network.toUpperCase();
|
||||
assertNetwork(network);
|
||||
const network = getNetwork(argv.network);
|
||||
|
||||
const buf = Buffer.from(String(argv.vaa), "hex");
|
||||
const contract_address = CONTRACTS[network].ethereum.core;
|
||||
const contract_address = contracts.coreBridge(network, "Ethereum");
|
||||
if (!contract_address) {
|
||||
throw Error(`Unknown core contract on ${network} for ethereum`);
|
||||
}
|
||||
|
||||
const provider = new ethers.providers.JsonRpcProvider(
|
||||
NETWORKS[network].ethereum.rpc
|
||||
NETWORKS[network].Ethereum.rpc
|
||||
);
|
||||
const contract = Implementation__factory.connect(contract_address, provider);
|
||||
const result = await contract.parseAndVerifyVM(buf);
|
||||
|
|
|
@ -1,60 +1,6 @@
|
|||
import {
|
||||
CHAIN_ID_SOLANA,
|
||||
CONTRACTS as SDK_CONTRACTS,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import { chainToChainId } from "@wormhole-foundation/sdk-base";
|
||||
|
||||
const OVERRIDES = {
|
||||
MAINNET: {
|
||||
sui: {
|
||||
core: "0xaeab97f96cf9877fee2883315d459552b2b921edc16d7ceac6eab944dd88919c",
|
||||
token_bridge:
|
||||
"0xc57508ee0d4595e5a8728974a4a93a787d38f339757230d441e895422c07aba9",
|
||||
},
|
||||
aptos: {
|
||||
token_bridge:
|
||||
"0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f",
|
||||
core: "0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625",
|
||||
nft_bridge:
|
||||
"0x1bdffae984043833ed7fe223f7af7a3f8902d04129b14f801823e64827da7130",
|
||||
},
|
||||
},
|
||||
TESTNET: {
|
||||
sui: {
|
||||
core: "0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790",
|
||||
token_bridge:
|
||||
"0x6fb10cdb7aa299e9a4308752dadecb049ff55a892de92992a1edbd7912b3d6da",
|
||||
},
|
||||
aptos: {
|
||||
token_bridge:
|
||||
"0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f",
|
||||
core: "0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625",
|
||||
nft_bridge: undefined,
|
||||
},
|
||||
},
|
||||
DEVNET: {
|
||||
sui: {
|
||||
core: "0x12253210c90f89e7a8525e6c52d41309ff5bfb31f43f561b5fe6f50cd72f9668", // wormhole module State object ID
|
||||
token_bridge:
|
||||
"0x830ed228c6f1bcb40003bb49af3277df2cbf933d63a6bcdcb0ba4580a1a7654e", // token_bridge module State object ID
|
||||
},
|
||||
aptos: {
|
||||
token_bridge:
|
||||
"0x84a5f374d29fc77e370014dce4fd6a55b58ad608de8074b0be5571701724da31",
|
||||
core: "0xde0036a9600559e295d5f6802ef6f3f802f510366e0c23912b0655d972166017",
|
||||
nft_bridge:
|
||||
"0x46da3d4c569388af61f951bdd1153f4c875f90c2991f6b2d0a38e2161a40852c",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// TODO(aki): move this to SDK at some point
|
||||
export const CONTRACTS = {
|
||||
MAINNET: { ...SDK_CONTRACTS.MAINNET, ...OVERRIDES.MAINNET },
|
||||
TESTNET: { ...SDK_CONTRACTS.TESTNET, ...OVERRIDES.TESTNET },
|
||||
DEVNET: { ...SDK_CONTRACTS.DEVNET, ...OVERRIDES.DEVNET },
|
||||
};
|
||||
|
||||
export const GOVERNANCE_CHAIN = CHAIN_ID_SOLANA;
|
||||
export const GOVERNANCE_CHAIN = chainToChainId("Solana");
|
||||
export const GOVERNANCE_EMITTER =
|
||||
"0000000000000000000000000000000000000000000000000000000000000004";
|
||||
export const INITIAL_GUARDIAN_DEVNET =
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ChainName } from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import { Chain } from "@wormhole-foundation/sdk-base";
|
||||
import { config } from "dotenv";
|
||||
import { homedir } from "os";
|
||||
|
||||
|
@ -12,785 +12,773 @@ export type Connection = {
|
|||
};
|
||||
|
||||
export type ChainConnections = {
|
||||
[chain in ChainName]: Connection;
|
||||
[chain in Chain]: Connection;
|
||||
};
|
||||
|
||||
const MAINNET = {
|
||||
unset: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
solana: {
|
||||
const Mainnet = {
|
||||
Solana: {
|
||||
rpc: "https://api.mainnet-beta.solana.com",
|
||||
key: getEnvVar("SOLANA_KEY"),
|
||||
},
|
||||
terra: {
|
||||
Terra: {
|
||||
rpc: "https://lcd.terra.dev",
|
||||
chain_id: "columbus-5",
|
||||
key: getEnvVar("TERRA_MNEMONIC"),
|
||||
},
|
||||
ethereum: {
|
||||
Ethereum: {
|
||||
rpc: `https://rpc.ankr.com/eth`,
|
||||
key: getEnvVar("ETH_KEY"),
|
||||
chain_id: 1,
|
||||
},
|
||||
bsc: {
|
||||
Bsc: {
|
||||
rpc: "https://bsc-dataseed.binance.org/",
|
||||
key: getEnvVar("ETH_KEY"),
|
||||
chain_id: 56,
|
||||
},
|
||||
polygon: {
|
||||
Polygon: {
|
||||
rpc: "https://rpc.ankr.com/polygon",
|
||||
key: getEnvVar("ETH_KEY"),
|
||||
chain_id: 137,
|
||||
},
|
||||
avalanche: {
|
||||
Avalanche: {
|
||||
rpc: "https://rpc.ankr.com/avalanche",
|
||||
key: getEnvVar("ETH_KEY"),
|
||||
chain_id: 43114,
|
||||
},
|
||||
algorand: {
|
||||
Algorand: {
|
||||
rpc: "https://mainnet-api.algonode.cloud",
|
||||
key: getEnvVar("ALGORAND_KEY"),
|
||||
},
|
||||
oasis: {
|
||||
Oasis: {
|
||||
rpc: "https://emerald.oasis.dev/",
|
||||
key: getEnvVar("ETH_KEY"),
|
||||
chain_id: 42262,
|
||||
},
|
||||
fantom: {
|
||||
Fantom: {
|
||||
rpc: "https://rpc.ftm.tools/",
|
||||
key: getEnvVar("ETH_KEY"),
|
||||
chain_id: 250,
|
||||
},
|
||||
aurora: {
|
||||
Aurora: {
|
||||
rpc: "https://mainnet.aurora.dev",
|
||||
key: getEnvVar("ETH_KEY"),
|
||||
chain_id: 1313161554,
|
||||
},
|
||||
karura: {
|
||||
Karura: {
|
||||
rpc: "https://eth-rpc-karura.aca-api.network/",
|
||||
key: getEnvVar("ETH_KEY"),
|
||||
chain_id: 686,
|
||||
},
|
||||
acala: {
|
||||
Acala: {
|
||||
rpc: "https://eth-rpc-acala.aca-api.network/",
|
||||
key: getEnvVar("ETH_KEY"),
|
||||
chain_id: 787,
|
||||
},
|
||||
klaytn: {
|
||||
Klaytn: {
|
||||
rpc: "https://public-node-api.klaytnapi.com/v1/cypress",
|
||||
key: getEnvVar("ETH_KEY"),
|
||||
chain_id: 8217,
|
||||
},
|
||||
celo: {
|
||||
Celo: {
|
||||
rpc: "https://forno.celo.org",
|
||||
key: getEnvVar("ETH_KEY"),
|
||||
chain_id: 42220,
|
||||
},
|
||||
near: {
|
||||
Near: {
|
||||
rpc: "https://rpc.mainnet.near.org",
|
||||
key: getEnvVar("NEAR_KEY"),
|
||||
networkId: "mainnet",
|
||||
},
|
||||
injective: {
|
||||
Injective: {
|
||||
rpc: "http://sentry0.injective.network:26657",
|
||||
chain_id: "injective-1",
|
||||
key: getEnvVar("INJECTIVE_KEY"),
|
||||
},
|
||||
osmosis: {
|
||||
Osmosis: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
aptos: {
|
||||
Aptos: {
|
||||
rpc: "https://fullnode.mainnet.aptoslabs.com/v1",
|
||||
key: getEnvVar("APTOS_KEY"),
|
||||
},
|
||||
sui: {
|
||||
Sui: {
|
||||
rpc: "https://fullnode.mainnet.sui.io:443",
|
||||
key: getEnvVar("SUI_KEY"),
|
||||
},
|
||||
pythnet: {
|
||||
Pythnet: {
|
||||
rpc: "http://api.pythnet.pyth.network:8899/",
|
||||
key: getEnvVar("SOLANA_KEY"),
|
||||
},
|
||||
xpla: {
|
||||
Xpla: {
|
||||
rpc: "https://dimension-lcd.xpla.dev",
|
||||
chain_id: "dimension_37-1",
|
||||
key: getEnvVar("XPLA_KEY"),
|
||||
},
|
||||
btc: {
|
||||
Btc: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
wormchain: {
|
||||
Wormchain: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
moonbeam: {
|
||||
Moonbeam: {
|
||||
rpc: "https://rpc.api.moonbeam.network",
|
||||
key: getEnvVar("ETH_KEY"),
|
||||
chain_id: 1284,
|
||||
},
|
||||
neon: {
|
||||
Neon: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
terra2: {
|
||||
Terra2: {
|
||||
rpc: "https://phoenix-lcd.terra.dev",
|
||||
chain_id: "phoenix-1",
|
||||
key: getEnvVar("TERRA_MNEMONIC"),
|
||||
},
|
||||
arbitrum: {
|
||||
Arbitrum: {
|
||||
rpc: "https://arb1.arbitrum.io/rpc",
|
||||
key: getEnvVar("ETH_KEY"),
|
||||
chain_id: 42161,
|
||||
},
|
||||
optimism: {
|
||||
Optimism: {
|
||||
rpc: "https://mainnet.optimism.io",
|
||||
key: getEnvVar("ETH_KEY"),
|
||||
chain_id: 10,
|
||||
},
|
||||
gnosis: {
|
||||
Gnosis: {
|
||||
rpc: "https://rpc.gnosischain.com/",
|
||||
key: getEnvVar("ETH_KEY"),
|
||||
chain_id: 100,
|
||||
},
|
||||
base: {
|
||||
Base: {
|
||||
rpc: "https://mainnet.base.org",
|
||||
key: getEnvVar("ETH_KEY"),
|
||||
chain_id: 8453,
|
||||
},
|
||||
sei: {
|
||||
Sei: {
|
||||
rpc: "https://sei-rpc.polkachu.com/",
|
||||
key: getEnvVar("SEI_KEY"),
|
||||
},
|
||||
rootstock: {
|
||||
Rootstock: {
|
||||
rpc: "https://public-node.rsk.co",
|
||||
key: getEnvVar("ETH_KEY"),
|
||||
chain_id: 30,
|
||||
},
|
||||
scroll: {
|
||||
Scroll: {
|
||||
rpc: "https://rpc.ankr.com/scroll",
|
||||
key: getEnvVar("ETH_KEY"),
|
||||
chain_id: 534352,
|
||||
},
|
||||
mantle: {
|
||||
Mantle: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
blast: {
|
||||
Blast: {
|
||||
rpc: "https://rpc.ankr.com/blast",
|
||||
key: getEnvVar("ETH_KEY"),
|
||||
chain_id: 81457,
|
||||
},
|
||||
xlayer: {
|
||||
Xlayer: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
linea: {
|
||||
Linea: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
berachain: {
|
||||
Berachain: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
seievm: {
|
||||
Seievm: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
sepolia: {
|
||||
Sepolia: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
holesky: {
|
||||
Holesky: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
cosmoshub: {
|
||||
Cosmoshub: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
evmos: {
|
||||
Evmos: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
kujira: {
|
||||
Kujira: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
neutron: {
|
||||
Neutron: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
celestia: {
|
||||
Celestia: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
arbitrum_sepolia: {
|
||||
ArbitrumSepolia: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
base_sepolia: {
|
||||
BaseSepolia: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
optimism_sepolia: {
|
||||
OptimismSepolia: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
polygon_sepolia: {
|
||||
PolygonSepolia: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
stargaze: {
|
||||
Stargaze: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
seda: {
|
||||
Seda: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
dymension: {
|
||||
Dymension: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
provenance: {
|
||||
Provenance: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
};
|
||||
|
||||
const TESTNET = {
|
||||
unset: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
solana: {
|
||||
const Testnet = {
|
||||
Solana: {
|
||||
rpc: "https://api.devnet.solana.com",
|
||||
key: getEnvVar("SOLANA_KEY_TESTNET"),
|
||||
},
|
||||
terra: {
|
||||
Terra: {
|
||||
rpc: "https://bombay-lcd.terra.dev",
|
||||
chain_id: "bombay-12",
|
||||
key: getEnvVar("TERRA_MNEMONIC_TESTNET"),
|
||||
},
|
||||
ethereum: {
|
||||
Ethereum: {
|
||||
rpc: `https://rpc.ankr.com/eth_goerli`,
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 5,
|
||||
},
|
||||
bsc: {
|
||||
Bsc: {
|
||||
rpc: "https://data-seed-prebsc-1-s1.binance.org:8545",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 97,
|
||||
},
|
||||
polygon: {
|
||||
Polygon: {
|
||||
rpc: `https://rpc.ankr.com/polygon_mumbai`,
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 80001,
|
||||
},
|
||||
avalanche: {
|
||||
Avalanche: {
|
||||
rpc: "https://rpc.ankr.com/avalanche_fuji",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 43113,
|
||||
},
|
||||
oasis: {
|
||||
Oasis: {
|
||||
rpc: "https://testnet.emerald.oasis.dev",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 42261,
|
||||
},
|
||||
algorand: {
|
||||
Algorand: {
|
||||
rpc: "https://testnet-api.algonode.cloud",
|
||||
key: getEnvVar("ALGORAND_KEY_TESTNET"),
|
||||
},
|
||||
fantom: {
|
||||
Fantom: {
|
||||
rpc: "https://rpc.testnet.fantom.network",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 4002,
|
||||
},
|
||||
aurora: {
|
||||
Aurora: {
|
||||
rpc: "https://testnet.aurora.dev",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 1313161555,
|
||||
},
|
||||
karura: {
|
||||
Karura: {
|
||||
rpc: "https://eth-rpc-karura-testnet.aca-staging.network",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 596,
|
||||
},
|
||||
acala: {
|
||||
Acala: {
|
||||
rpc: "https://eth-rpc-acala-testnet.aca-staging.network",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 595,
|
||||
},
|
||||
klaytn: {
|
||||
Klaytn: {
|
||||
rpc: "https://api.baobab.klaytn.net:8651",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 1001,
|
||||
},
|
||||
celo: {
|
||||
Celo: {
|
||||
rpc: "https://alfajores-forno.celo-testnet.org",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 44787,
|
||||
},
|
||||
near: {
|
||||
Near: {
|
||||
rpc: "https://rpc.testnet.near.org",
|
||||
key: getEnvVar("NEAR_KEY_TESTNET"),
|
||||
networkId: "testnet",
|
||||
},
|
||||
injective: {
|
||||
Injective: {
|
||||
rpc: "https://k8s.testnet.tm.injective.network:443",
|
||||
chain_id: "injective-888",
|
||||
key: getEnvVar("INJECTIVE_KEY_TESTNET"),
|
||||
},
|
||||
osmosis: {
|
||||
Osmosis: {
|
||||
rpc: undefined,
|
||||
chain_id: "osmo-test-4",
|
||||
key: getEnvVar("OSMOSIS_KEY_TESTNET"),
|
||||
},
|
||||
aptos: {
|
||||
Aptos: {
|
||||
rpc: "https://fullnode.testnet.aptoslabs.com/v1",
|
||||
key: getEnvVar("APTOS_TESTNET"),
|
||||
},
|
||||
sui: {
|
||||
Sui: {
|
||||
rpc: "https://fullnode.testnet.sui.io:443",
|
||||
key: getEnvVar("SUI_KEY_TESTNET"),
|
||||
},
|
||||
pythnet: {
|
||||
Pythnet: {
|
||||
rpc: "https://api.pythtest.pyth.network/",
|
||||
key: getEnvVar("SOLANA_KEY_TESTNET"),
|
||||
},
|
||||
xpla: {
|
||||
Xpla: {
|
||||
rpc: "https://cube-lcd.xpla.dev:443",
|
||||
chain_id: "cube_47-5",
|
||||
key: getEnvVar("XPLA_KEY_TESTNET"),
|
||||
},
|
||||
sei: {
|
||||
Sei: {
|
||||
rpc: "https://rpc.atlantic-2.seinetwork.io",
|
||||
key: getEnvVar("SEI_KEY_TESTNET"),
|
||||
},
|
||||
scroll: {
|
||||
Scroll: {
|
||||
rpc: "https://rpc.ankr.com/scroll_sepolia_testnet",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 534353,
|
||||
},
|
||||
mantle: {
|
||||
Mantle: {
|
||||
rpc: "https://mantle-sepolia.drpc.org",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 5003,
|
||||
},
|
||||
blast: {
|
||||
Blast: {
|
||||
rpc: "https://blast-sepolia.drpc.org",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 168587773,
|
||||
},
|
||||
xlayer: {
|
||||
Xlayer: {
|
||||
rpc: "https://testrpc.xlayer.tech/",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 195,
|
||||
},
|
||||
linea: {
|
||||
Linea: {
|
||||
rpc: "https://rpc.sepolia.linea.build",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 59141,
|
||||
},
|
||||
berachain: {
|
||||
Berachain: {
|
||||
rpc: "https://bartio.rpc.berachain.com/",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 80084,
|
||||
},
|
||||
seievm: {
|
||||
Seievm: {
|
||||
rpc: "https://evm-rpc-arctic-1.sei-apis.com/",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 713715,
|
||||
},
|
||||
sepolia: {
|
||||
Sepolia: {
|
||||
rpc: "https://rpc.ankr.com/eth_sepolia",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 11155111,
|
||||
},
|
||||
holesky: {
|
||||
Holesky: {
|
||||
rpc: "https://rpc.ankr.com/eth_holesky",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 17000,
|
||||
},
|
||||
btc: {
|
||||
Btc: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
wormchain: {
|
||||
Wormchain: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
moonbeam: {
|
||||
Moonbeam: {
|
||||
rpc: "https://rpc.api.moonbase.moonbeam.network",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 1287,
|
||||
},
|
||||
neon: {
|
||||
Neon: {
|
||||
rpc: "https://proxy.devnet.neonlabs.org/solana",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: undefined,
|
||||
},
|
||||
terra2: {
|
||||
Terra2: {
|
||||
rpc: "https://pisco-lcd.terra.dev",
|
||||
chain_id: "pisco-1",
|
||||
key: getEnvVar("TERRA_MNEMONIC_TESTNET"),
|
||||
},
|
||||
arbitrum: {
|
||||
Arbitrum: {
|
||||
rpc: "https://goerli-rollup.arbitrum.io/rpc",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 421613,
|
||||
},
|
||||
optimism: {
|
||||
Optimism: {
|
||||
rpc: "https://goerli.optimism.io",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 420,
|
||||
},
|
||||
gnosis: {
|
||||
Gnosis: {
|
||||
rpc: "https://sokol.poa.network/",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 77,
|
||||
},
|
||||
base: {
|
||||
Base: {
|
||||
rpc: "https://goerli.base.org",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 84531,
|
||||
},
|
||||
rootstock: {
|
||||
Rootstock: {
|
||||
rpc: "https://public-node.testnet.rsk.co",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 31,
|
||||
},
|
||||
cosmoshub: {
|
||||
Cosmoshub: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
evmos: {
|
||||
Evmos: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
kujira: {
|
||||
Kujira: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
neutron: {
|
||||
Neutron: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
celestia: {
|
||||
Celestia: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
arbitrum_sepolia: {
|
||||
ArbitrumSepolia: {
|
||||
rpc: "https://arbitrum-sepolia.publicnode.com",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 421614,
|
||||
},
|
||||
base_sepolia: {
|
||||
BaseSepolia: {
|
||||
rpc: "https://sepolia.base.org",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 84532,
|
||||
},
|
||||
optimism_sepolia: {
|
||||
OptimismSepolia: {
|
||||
rpc: "https://rpc.ankr.com/optimism_sepolia",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 11155420,
|
||||
},
|
||||
polygon_sepolia: {
|
||||
PolygonSepolia: {
|
||||
rpc: "https://rpc-amoy.polygon.technology/",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 80002,
|
||||
},
|
||||
stargaze: {
|
||||
Stargaze: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
seda: {
|
||||
Seda: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
dymension: {
|
||||
Dymension: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
provenance: {
|
||||
Provenance: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
};
|
||||
|
||||
const DEVNET = {
|
||||
unset: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
solana: {
|
||||
const Devnet = {
|
||||
Solana: {
|
||||
rpc: "http://localhost:8899",
|
||||
key: "J2D4pwDred8P9ioyPEZVLPht885AeYpifsFGUyuzVmiKQosAvmZP4EegaKFrSprBC5vVP1xTvu61vYDWsxBNsYx",
|
||||
},
|
||||
terra: {
|
||||
Terra: {
|
||||
rpc: "http://localhost:1317",
|
||||
chain_id: "columbus-5",
|
||||
key: "notice oak worry limit wrap speak medal online prefer cluster roof addict wrist behave treat actual wasp year salad speed social layer crew genius",
|
||||
},
|
||||
ethereum: {
|
||||
Ethereum: {
|
||||
rpc: "http://localhost:8545",
|
||||
key: "0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d",
|
||||
},
|
||||
bsc: {
|
||||
Bsc: {
|
||||
rpc: "http://localhost:8546",
|
||||
key: "0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d",
|
||||
},
|
||||
polygon: {
|
||||
Polygon: {
|
||||
rpc: undefined,
|
||||
key: "0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d",
|
||||
},
|
||||
avalanche: {
|
||||
Avalanche: {
|
||||
rpc: undefined,
|
||||
key: "0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d",
|
||||
},
|
||||
oasis: {
|
||||
Oasis: {
|
||||
rpc: undefined,
|
||||
key: "0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d",
|
||||
},
|
||||
algorand: {
|
||||
Algorand: {
|
||||
rpc: "http://localhost",
|
||||
key: getEnvVar("ALGORAND_KEY_DEVNET"),
|
||||
},
|
||||
fantom: {
|
||||
Fantom: {
|
||||
rpc: undefined,
|
||||
key: "0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d",
|
||||
},
|
||||
aurora: {
|
||||
Aurora: {
|
||||
rpc: undefined,
|
||||
key: "0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d",
|
||||
},
|
||||
karura: {
|
||||
Karura: {
|
||||
rpc: undefined,
|
||||
key: "0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d",
|
||||
},
|
||||
acala: {
|
||||
Acala: {
|
||||
rpc: undefined,
|
||||
key: "0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d",
|
||||
},
|
||||
klaytn: {
|
||||
Klaytn: {
|
||||
rpc: undefined,
|
||||
key: "0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d",
|
||||
},
|
||||
celo: {
|
||||
Celo: {
|
||||
rpc: undefined,
|
||||
key: "0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d",
|
||||
},
|
||||
near: {
|
||||
Near: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
networkId: "sandbox",
|
||||
},
|
||||
injective: {
|
||||
Injective: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
osmosis: {
|
||||
Osmosis: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
pythnet: {
|
||||
Pythnet: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
btc: {
|
||||
Btc: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
xpla: {
|
||||
Xpla: {
|
||||
rpc: undefined,
|
||||
chain_id: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
sei: {
|
||||
Sei: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
scroll: {
|
||||
Scroll: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
mantle: {
|
||||
Mantle: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
blast: {
|
||||
Blast: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
xlayer: {
|
||||
Xlayer: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
linea: {
|
||||
Linea: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
berachain: {
|
||||
Berachain: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
seievm: {
|
||||
Seievm: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
sepolia: {
|
||||
Sepolia: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
holesky: {
|
||||
Holesky: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
wormchain: {
|
||||
Wormchain: {
|
||||
rpc: "http://localhost:1319",
|
||||
chain_id: "wormchain",
|
||||
key: undefined,
|
||||
},
|
||||
aptos: {
|
||||
Aptos: {
|
||||
rpc: "http://0.0.0.0:8080",
|
||||
key: "537c1f91e56891445b491068f519b705f8c0f1a1e66111816dd5d4aa85b8113d",
|
||||
},
|
||||
sui: {
|
||||
Sui: {
|
||||
rpc: "http://0.0.0.0:9000",
|
||||
key: "AGA20wtGcwbcNAG4nwapbQ5wIuXwkYQEWFUoSVAxctHb",
|
||||
},
|
||||
moonbeam: {
|
||||
Moonbeam: {
|
||||
rpc: undefined,
|
||||
key: "0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d",
|
||||
},
|
||||
neon: {
|
||||
Neon: {
|
||||
rpc: undefined,
|
||||
key: "0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d",
|
||||
},
|
||||
terra2: {
|
||||
Terra2: {
|
||||
rpc: "http://localhost:1318",
|
||||
chain_id: "phoenix-1",
|
||||
key: "notice oak worry limit wrap speak medal online prefer cluster roof addict wrist behave treat actual wasp year salad speed social layer crew genius",
|
||||
},
|
||||
arbitrum: {
|
||||
Arbitrum: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
optimism: {
|
||||
Optimism: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
gnosis: {
|
||||
Gnosis: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
base: {
|
||||
Base: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
rootstock: {
|
||||
Rootstock: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
cosmoshub: {
|
||||
Cosmoshub: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
evmos: {
|
||||
Evmos: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
kujira: {
|
||||
Kujira: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
neutron: {
|
||||
Neutron: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
celestia: {
|
||||
Celestia: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
arbitrum_sepolia: {
|
||||
ArbitrumSepolia: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
base_sepolia: {
|
||||
BaseSepolia: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
optimism_sepolia: {
|
||||
OptimismSepolia: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
polygon_sepolia: {
|
||||
PolygonSepolia: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
stargaze: {
|
||||
Stargaze: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
seda: {
|
||||
Seda: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
dymension: {
|
||||
Dymension: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
provenance: {
|
||||
Provenance: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
|
@ -811,18 +799,18 @@ const DEVNET = {
|
|||
*
|
||||
* (Do not delete this declaration!)
|
||||
*/
|
||||
const isTestnetConnections: ChainConnections = TESTNET;
|
||||
const isTestnetConnections: ChainConnections = Testnet;
|
||||
|
||||
/**
|
||||
*
|
||||
* See [[isTestnetContracts]]
|
||||
*/
|
||||
const isMainnetConnections: ChainConnections = MAINNET;
|
||||
const isMainnetConnections: ChainConnections = Mainnet;
|
||||
|
||||
/**
|
||||
*
|
||||
* See [[isTestnetContracts]]
|
||||
*/
|
||||
const isDevnetConnections: ChainConnections = DEVNET;
|
||||
const isDevnetConnections: ChainConnections = Devnet;
|
||||
|
||||
export const NETWORKS = { MAINNET, TESTNET, DEVNET };
|
||||
export const NETWORKS = { Mainnet, Testnet, Devnet };
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import {
|
||||
CHAINS,
|
||||
Chain,
|
||||
ChainId,
|
||||
ChainName,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
chainIds,
|
||||
chains,
|
||||
} from "@wormhole-foundation/sdk-base";
|
||||
|
||||
export const DEBUG_OPTIONS = {
|
||||
alias: "d",
|
||||
|
@ -38,11 +39,9 @@ export const RPC_OPTIONS = {
|
|||
demandOption: false,
|
||||
} as const;
|
||||
|
||||
export const CHAIN_ID_OR_NAME_CHOICES = [
|
||||
...Object.keys(CHAINS),
|
||||
...Object.values(CHAINS),
|
||||
] as (ChainName | ChainId)[];
|
||||
export const CHAIN_ID_OR_NAME_CHOICES = [...chains, ...chainIds] as (
|
||||
| Chain
|
||||
| ChainId
|
||||
)[];
|
||||
|
||||
export const CHAIN_NAME_CHOICES = Object.keys(CHAINS).filter(
|
||||
(c) => c !== "unset"
|
||||
) as ChainName[];
|
||||
export const CHAIN_NAME_CHOICES = [...chains];
|
||||
|
|
|
@ -1,31 +1,35 @@
|
|||
import {
|
||||
Chain,
|
||||
ChainId,
|
||||
ChainName,
|
||||
isCosmWasmChain,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
chainToPlatform,
|
||||
toChain,
|
||||
} from "@wormhole-foundation/sdk-base";
|
||||
import { decodeAddress, getApplicationAddress } from "algosdk";
|
||||
import { uint8ArrayToHex } from "./sdk/array";
|
||||
import { arrayify, sha256, zeroPad } from "ethers/lib/utils";
|
||||
import { bech32 } from "bech32";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
|
||||
import {
|
||||
getEmitterAddressAlgorand,
|
||||
getEmitterAddressEth,
|
||||
getEmitterAddressNear,
|
||||
getEmitterAddressSolana,
|
||||
getEmitterAddressTerra,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/bridge/getEmitterAddress";
|
||||
|
||||
export async function getEmitterAddress(
|
||||
chain: ChainId | ChainName,
|
||||
addr: string
|
||||
) {
|
||||
if (chain === "solana" || chain === "pythnet") {
|
||||
// TODO: Create an isSolanaChain()
|
||||
addr = getEmitterAddressSolana(addr);
|
||||
} else if (isCosmWasmChain(chain)) {
|
||||
addr = await getEmitterAddressTerra(addr);
|
||||
} else if (chain === "algorand") {
|
||||
addr = getEmitterAddressAlgorand(BigInt(addr));
|
||||
} else if (chain === "near") {
|
||||
addr = getEmitterAddressNear(addr);
|
||||
} else if (chain === "aptos") {
|
||||
export async function getEmitterAddress(chain: ChainId | Chain, addr: string) {
|
||||
const localChain = toChain(chain);
|
||||
if (chainToPlatform(localChain) === "Solana") {
|
||||
const seeds = [Buffer.from("emitter")];
|
||||
const programAddr = PublicKey.findProgramAddressSync(
|
||||
seeds,
|
||||
new PublicKey(addr)
|
||||
)[0];
|
||||
addr = programAddr.toBuffer().toString("hex");
|
||||
} else if (chainToPlatform(localChain) === "Cosmwasm") {
|
||||
addr = Buffer.from(
|
||||
zeroPad(bech32.fromWords(bech32.decode(addr).words), 32)
|
||||
).toString("hex");
|
||||
} else if (localChain === "Algorand") {
|
||||
const appAddr: string = getApplicationAddress(BigInt(addr));
|
||||
const decAppAddr: Uint8Array = decodeAddress(appAddr).publicKey;
|
||||
addr = uint8ArrayToHex(decAppAddr);
|
||||
} else if (localChain === "Near") {
|
||||
addr = uint8ArrayToHex(arrayify(sha256(Buffer.from(addr, "utf8"))));
|
||||
} else if (localChain === "Aptos") {
|
||||
// TODO: There should be something in the SDK to do this.
|
||||
if (
|
||||
addr ===
|
||||
|
@ -42,7 +46,7 @@ export async function getEmitterAddress(
|
|||
} else {
|
||||
throw Error(`Unsupported Aptos address: ${addr}`);
|
||||
}
|
||||
} else if (chain === "sui") {
|
||||
} else if (localChain === "Sui") {
|
||||
// TODO: There should be something in the SDK to do this.
|
||||
if (
|
||||
addr ===
|
||||
|
@ -61,7 +65,8 @@ export async function getEmitterAddress(
|
|||
throw Error(`Unsupported Sui address: ${addr}`);
|
||||
}
|
||||
} else {
|
||||
addr = getEmitterAddressEth(addr);
|
||||
// This is the Eth version
|
||||
addr = Buffer.from(zeroPad(arrayify(addr), 32)).toString("hex");
|
||||
}
|
||||
|
||||
return addr;
|
||||
|
|
|
@ -5,20 +5,10 @@ import {
|
|||
NFTBridgeImplementation__factory,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/ethers-contracts";
|
||||
import { WormholeRelayer__factory } from "@certusone/wormhole-sdk/lib/esm/ethers-relayer-contracts";
|
||||
import { getWormholeRelayerAddress } from "@certusone/wormhole-sdk/lib/esm/relayer";
|
||||
import {
|
||||
CHAINS,
|
||||
CONTRACTS,
|
||||
ChainName,
|
||||
Contracts,
|
||||
EVMChainName,
|
||||
toChainId,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import axios from "axios";
|
||||
import { ethers } from "ethers";
|
||||
import { solidityKeccak256 } from "ethers/lib/utils";
|
||||
import { NETWORKS } from "./consts";
|
||||
import { Network } from "./utils";
|
||||
import { Encoding, Payload, encode, impossible, typeWidth } from "./vaa";
|
||||
import {
|
||||
approveEth,
|
||||
|
@ -26,14 +16,22 @@ import {
|
|||
transferFromEth,
|
||||
transferFromEthNative,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/token_bridge/transfer";
|
||||
import { tryNativeToUint8Array } from "@certusone/wormhole-sdk/lib/esm/utils";
|
||||
import {
|
||||
Chain,
|
||||
Network,
|
||||
PlatformToChains,
|
||||
chainToChainId,
|
||||
chains,
|
||||
contracts,
|
||||
} from "@wormhole-foundation/sdk-base";
|
||||
import { tryNativeToUint8Array } from "./sdk/array";
|
||||
|
||||
const _IMPLEMENTATION_SLOT =
|
||||
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";
|
||||
|
||||
export async function query_contract_evm(
|
||||
network: Network,
|
||||
chain: EVMChainName,
|
||||
chain: PlatformToChains<"Evm">,
|
||||
module: "Core" | "NFTBridge" | "TokenBridge",
|
||||
contract_address: string | undefined,
|
||||
_rpc: string | undefined
|
||||
|
@ -44,12 +42,13 @@ export async function query_contract_evm(
|
|||
throw Error(`No ${network} rpc defined for ${chain} (see networks.ts)`);
|
||||
}
|
||||
|
||||
const contracts: Contracts = CONTRACTS[network][chain];
|
||||
const provider = new ethers.providers.JsonRpcProvider(rpc);
|
||||
const result: any = {};
|
||||
switch (module) {
|
||||
case "Core":
|
||||
contract_address = contract_address ? contract_address : contracts.core;
|
||||
contract_address = contract_address
|
||||
? contract_address
|
||||
: contracts.coreBridge.get(network, chain);
|
||||
if (!contract_address) {
|
||||
throw Error(`Unknown core contract on ${network} for ${chain}`);
|
||||
}
|
||||
|
@ -105,7 +104,7 @@ export async function query_contract_evm(
|
|||
case "TokenBridge":
|
||||
contract_address = contract_address
|
||||
? contract_address
|
||||
: contracts.token_bridge;
|
||||
: contracts.tokenBridge.get(network, chain);
|
||||
if (contract_address === undefined) {
|
||||
throw Error(`Unknown token bridge contract on ${network} for ${chain}`);
|
||||
}
|
||||
|
@ -115,11 +114,11 @@ export async function query_contract_evm(
|
|||
);
|
||||
result.address = contract_address;
|
||||
const registrationsPromise = Promise.all(
|
||||
Object.entries(CHAINS)
|
||||
.filter(([c_name, _]) => c_name !== chain && c_name !== "unset")
|
||||
.map(async ([c_name, c_id]) => [
|
||||
chains
|
||||
.filter((c_name) => c_name !== chain)
|
||||
.map(async (c_name) => [
|
||||
c_name,
|
||||
await tb.bridgeContracts(c_id),
|
||||
await tb.bridgeContracts(chainToChainId(c_name)),
|
||||
])
|
||||
);
|
||||
const [
|
||||
|
@ -167,7 +166,7 @@ export async function query_contract_evm(
|
|||
case "NFTBridge":
|
||||
contract_address = contract_address
|
||||
? contract_address
|
||||
: contracts.nft_bridge;
|
||||
: contracts.nftBridge.get(network, chain);
|
||||
if (contract_address === undefined) {
|
||||
throw Error(`Unknown nft bridge contract on ${network} for ${chain}`);
|
||||
}
|
||||
|
@ -177,11 +176,11 @@ export async function query_contract_evm(
|
|||
);
|
||||
result.address = contract_address;
|
||||
const registrationsPromiseNb = Promise.all(
|
||||
Object.entries(CHAINS)
|
||||
.filter(([c_name, _]) => c_name !== chain && c_name !== "unset")
|
||||
.map(async ([c_name, c_id]) => [
|
||||
chains
|
||||
.filter(([c_name, _]) => c_name !== chain)
|
||||
.map(async (c_name) => [
|
||||
c_name,
|
||||
await nb.bridgeContracts(c_id),
|
||||
await nb.bridgeContracts(chainToChainId(c_name)),
|
||||
])
|
||||
);
|
||||
const [
|
||||
|
@ -232,7 +231,7 @@ export async function query_contract_evm(
|
|||
|
||||
export async function getImplementation(
|
||||
network: Network,
|
||||
chain: EVMChainName,
|
||||
chain: PlatformToChains<"Evm">,
|
||||
module: "Core" | "NFTBridge" | "TokenBridge",
|
||||
contract_address: string | undefined,
|
||||
_rpc: string | undefined
|
||||
|
@ -243,20 +242,21 @@ export async function getImplementation(
|
|||
throw Error(`No ${network} rpc defined for ${chain} (see networks.ts)`);
|
||||
}
|
||||
|
||||
const contracts: Contracts = CONTRACTS[network][chain];
|
||||
switch (module) {
|
||||
case "Core":
|
||||
contract_address = contract_address ? contract_address : contracts.core;
|
||||
contract_address = contract_address
|
||||
? contract_address
|
||||
: contracts.coreBridge.get(network, chain);
|
||||
break;
|
||||
case "TokenBridge":
|
||||
contract_address = contract_address
|
||||
? contract_address
|
||||
: contracts.token_bridge;
|
||||
: contracts.tokenBridge.get(network, chain);
|
||||
break;
|
||||
case "NFTBridge":
|
||||
contract_address = contract_address
|
||||
? contract_address
|
||||
: contracts.nft_bridge;
|
||||
: contracts.nftBridge.get(network, chain);
|
||||
break;
|
||||
default:
|
||||
impossible(module);
|
||||
|
@ -271,10 +271,14 @@ export async function getImplementation(
|
|||
)[0];
|
||||
}
|
||||
|
||||
async function getSigner(chain: EVMChainName, key: string, rpc: string) {
|
||||
async function getSigner(
|
||||
chain: PlatformToChains<"Evm">,
|
||||
key: string,
|
||||
rpc: string
|
||||
) {
|
||||
let provider: ethers.providers.JsonRpcProvider;
|
||||
let signer: ethers.Wallet;
|
||||
if (chain === "celo") {
|
||||
if (chain === "Celo") {
|
||||
provider = new celo.CeloProvider(rpc);
|
||||
await provider.ready;
|
||||
signer = new celo.CeloWallet(key, provider);
|
||||
|
@ -286,15 +290,15 @@ async function getSigner(chain: EVMChainName, key: string, rpc: string) {
|
|||
// NOTE: some of these might have only been tested on mainnet. If it fails in
|
||||
// testnet (or devnet), they might require additional guards
|
||||
let overrides: ethers.Overrides = {};
|
||||
if (chain === "karura" || chain == "acala") {
|
||||
if (chain === "Karura" || chain == "Acala") {
|
||||
overrides = await getKaruraGasParams(rpc);
|
||||
} else if (chain === "polygon") {
|
||||
} else if (chain === "Polygon") {
|
||||
const feeData = await provider.getFeeData();
|
||||
overrides = {
|
||||
maxFeePerGas: feeData.maxFeePerGas?.mul(50) || undefined,
|
||||
maxPriorityFeePerGas: feeData.maxPriorityFeePerGas?.mul(50) || undefined,
|
||||
};
|
||||
} else if (chain === "klaytn" || chain === "fantom") {
|
||||
} else if (chain === "Klaytn" || chain === "Fantom") {
|
||||
overrides = { gasPrice: (await signer.getGasPrice()).toString() };
|
||||
}
|
||||
return {
|
||||
|
@ -308,7 +312,7 @@ export async function execute_evm(
|
|||
payload: Payload,
|
||||
vaa: Buffer,
|
||||
network: Network,
|
||||
chain: EVMChainName,
|
||||
chain: PlatformToChains<"Evm">,
|
||||
contract_address: string | undefined,
|
||||
_rpc: string | undefined
|
||||
) {
|
||||
|
@ -323,12 +327,14 @@ export async function execute_evm(
|
|||
}
|
||||
|
||||
const key: string = n.key;
|
||||
const contracts: Contracts = CONTRACTS[network][chain];
|
||||
// const contracts: Contracts = CONTRACTS[network][chain];
|
||||
const { signer, overrides } = await getSigner(chain, key, rpc);
|
||||
|
||||
switch (payload.module) {
|
||||
case "Core": {
|
||||
contract_address = contract_address ? contract_address : contracts.core;
|
||||
contract_address = contract_address
|
||||
? contract_address
|
||||
: contracts.coreBridge.get(network, chain);
|
||||
if (contract_address === undefined) {
|
||||
throw Error(`Unknown core contract on ${network} for ${chain}`);
|
||||
}
|
||||
|
@ -362,7 +368,7 @@ export async function execute_evm(
|
|||
case "NFTBridge": {
|
||||
contract_address = contract_address
|
||||
? contract_address
|
||||
: contracts.nft_bridge;
|
||||
: contracts.nftBridge.get(network, chain);
|
||||
if (contract_address === undefined) {
|
||||
throw Error(`Unknown nft bridge contract on ${network} for ${chain}`);
|
||||
}
|
||||
|
@ -401,7 +407,7 @@ export async function execute_evm(
|
|||
case "TokenBridge": {
|
||||
contract_address = contract_address
|
||||
? contract_address
|
||||
: contracts.token_bridge;
|
||||
: contracts.tokenBridge.get(network, chain);
|
||||
if (contract_address === undefined) {
|
||||
throw Error(`Unknown token bridge contract on ${network} for ${chain}`);
|
||||
}
|
||||
|
@ -451,7 +457,7 @@ export async function execute_evm(
|
|||
case "WormholeRelayer":
|
||||
contract_address = contract_address
|
||||
? contract_address
|
||||
: getWormholeRelayerAddress(chain, network);
|
||||
: contracts.relayer.get(network, chain);
|
||||
if (contract_address === undefined) {
|
||||
throw Error(
|
||||
`Unknown Wormhole Relayer contract on ${network} for ${chain}`
|
||||
|
@ -493,8 +499,8 @@ export async function execute_evm(
|
|||
}
|
||||
|
||||
export async function transferEVM(
|
||||
srcChain: EVMChainName,
|
||||
dstChain: ChainName,
|
||||
srcChain: PlatformToChains<"Evm">,
|
||||
dstChain: Chain,
|
||||
dstAddress: string,
|
||||
tokenAddress: string,
|
||||
amount: string,
|
||||
|
@ -505,7 +511,7 @@ export async function transferEVM(
|
|||
if (!n.key) {
|
||||
throw Error(`No ${network} key defined for ${srcChain} (see networks.ts)`);
|
||||
}
|
||||
const { token_bridge } = CONTRACTS[network][srcChain];
|
||||
const token_bridge = contracts.tokenBridge.get(network, srcChain);
|
||||
if (!token_bridge) {
|
||||
throw Error(`Unknown token bridge contract on ${network} for ${srcChain}`);
|
||||
}
|
||||
|
@ -516,8 +522,8 @@ export async function transferEVM(
|
|||
token_bridge,
|
||||
signer,
|
||||
amount,
|
||||
toChainId(dstChain),
|
||||
tryNativeToUint8Array(dstAddress, dstChain)
|
||||
chainToChainId(dstChain),
|
||||
tryNativeToUint8Array(dstAddress, chainToChainId(dstChain))
|
||||
);
|
||||
} else {
|
||||
const allowance = await getAllowanceEth(token_bridge, tokenAddress, signer);
|
||||
|
@ -529,8 +535,8 @@ export async function transferEVM(
|
|||
signer,
|
||||
tokenAddress,
|
||||
amount,
|
||||
dstChain,
|
||||
tryNativeToUint8Array(dstAddress, dstChain),
|
||||
chainToChainId(dstChain),
|
||||
tryNativeToUint8Array(dstAddress, chainToChainId(dstChain)),
|
||||
undefined,
|
||||
overrides
|
||||
);
|
||||
|
@ -828,11 +834,10 @@ const isUnsupportedError = (e: any): e is { reason: string } =>
|
|||
|
||||
export async function queryRegistrationsEvm(
|
||||
network: Network,
|
||||
chain: EVMChainName,
|
||||
chain: PlatformToChains<"Evm">,
|
||||
module: "Core" | "NFTBridge" | "TokenBridge"
|
||||
): Promise<Object> {
|
||||
const n = NETWORKS[network][chain];
|
||||
const contracts = CONTRACTS[network][chain];
|
||||
|
||||
let targetContract: string | undefined;
|
||||
let contract: any;
|
||||
|
@ -841,7 +846,7 @@ export async function queryRegistrationsEvm(
|
|||
|
||||
switch (module) {
|
||||
case "TokenBridge":
|
||||
targetContract = contracts.token_bridge;
|
||||
targetContract = contracts.tokenBridge.get(network, chain);
|
||||
if (targetContract === undefined) {
|
||||
throw Error(`Unknown token bridge contract on ${network} for ${chain}`);
|
||||
}
|
||||
|
@ -851,7 +856,7 @@ export async function queryRegistrationsEvm(
|
|||
);
|
||||
break;
|
||||
case "NFTBridge":
|
||||
targetContract = contracts.nft_bridge;
|
||||
targetContract = contracts.nftBridge.get(network, chain);
|
||||
if (targetContract === undefined) {
|
||||
throw Error(`Unknown NFT bridge contract on ${network} for ${chain}`);
|
||||
}
|
||||
|
@ -865,9 +870,12 @@ export async function queryRegistrationsEvm(
|
|||
}
|
||||
|
||||
const registrations: string[][] = await Promise.all(
|
||||
Object.entries(CHAINS)
|
||||
.filter(([cname, _]) => cname !== chain && cname !== "unset")
|
||||
.map(async ([cname, cid]) => [cname, await contract.bridgeContracts(cid)])
|
||||
chains
|
||||
.filter((cname) => cname !== chain)
|
||||
.map(async (cname) => [
|
||||
cname,
|
||||
await contract.bridgeContracts(chainToChainId(cname)),
|
||||
])
|
||||
);
|
||||
|
||||
const results: { [key: string]: string } = {};
|
||||
|
|
|
@ -1,8 +1,3 @@
|
|||
import {
|
||||
CHAINS,
|
||||
CONTRACTS,
|
||||
ChainName,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import {
|
||||
getNetworkInfo,
|
||||
Network as InjectiveNetwork,
|
||||
|
@ -19,28 +14,33 @@ import {
|
|||
import { DEFAULT_STD_FEE, getStdFee } from "@injectivelabs/utils";
|
||||
import { fromUint8Array } from "js-base64";
|
||||
import { NETWORKS } from "./consts";
|
||||
import { Network } from "./utils";
|
||||
import { impossible, Payload } from "./vaa";
|
||||
import { transferFromInjective } from "@certusone/wormhole-sdk/lib/esm/token_bridge/injective";
|
||||
import { tryNativeToUint8Array } from "@certusone/wormhole-sdk/lib/esm/utils";
|
||||
import {
|
||||
Chain,
|
||||
chainToChainId,
|
||||
contracts,
|
||||
Network,
|
||||
} from "@wormhole-foundation/sdk-base";
|
||||
import { chains } from "@wormhole-foundation/sdk";
|
||||
import { tryNativeToUint8Array } from "./sdk/array";
|
||||
|
||||
export async function execute_injective(
|
||||
payload: Payload,
|
||||
vaa: Buffer,
|
||||
network: Network
|
||||
) {
|
||||
if (network === "DEVNET") {
|
||||
if (network === "Devnet") {
|
||||
throw new Error("Injective is not supported in DEVNET");
|
||||
}
|
||||
const chain = "injective";
|
||||
const chain = "Injective";
|
||||
let { key } = NETWORKS[network][chain];
|
||||
if (!key) {
|
||||
throw Error(`No ${network} key defined for Injective`);
|
||||
}
|
||||
|
||||
let contracts = CONTRACTS[network][chain];
|
||||
const endPoint =
|
||||
network === "MAINNET"
|
||||
network === "Mainnet"
|
||||
? InjectiveNetwork.MainnetK8s
|
||||
: InjectiveNetwork.TestnetK8s;
|
||||
|
||||
|
@ -55,7 +55,7 @@ export async function execute_injective(
|
|||
|
||||
switch (payload.module) {
|
||||
case "Core": {
|
||||
target_contract = contracts.core;
|
||||
target_contract = contracts.coreBridge(network, "Injective");
|
||||
action = "submit_v_a_a";
|
||||
execute_msg = {
|
||||
vaa: fromUint8Array(vaa),
|
||||
|
@ -76,14 +76,15 @@ export async function execute_injective(
|
|||
break;
|
||||
}
|
||||
case "NFTBridge": {
|
||||
if (!contracts.nft_bridge) {
|
||||
const nftContract = contracts.nftBridge.get(network, "Injective");
|
||||
if (!nftContract) {
|
||||
// NOTE: this code can safely be removed once the injective NFT bridge is
|
||||
// released, but it's fine for it to stay, as the condition will just be
|
||||
// skipped once 'contracts.nft_bridge' is defined
|
||||
throw new Error("NFT bridge not supported yet for injective");
|
||||
}
|
||||
|
||||
target_contract = contracts.nft_bridge;
|
||||
target_contract = nftContract;
|
||||
action = "submit_vaa";
|
||||
execute_msg = {
|
||||
data: fromUint8Array(vaa),
|
||||
|
@ -107,12 +108,12 @@ export async function execute_injective(
|
|||
break;
|
||||
}
|
||||
case "TokenBridge": {
|
||||
console.log("contracts:", contracts);
|
||||
if (!contracts.token_bridge) {
|
||||
const tbContract = contracts.tokenBridge.get(network, "Injective");
|
||||
if (!tbContract) {
|
||||
throw new Error("contracts.token_bridge is undefined");
|
||||
}
|
||||
|
||||
target_contract = contracts.token_bridge;
|
||||
target_contract = tbContract;
|
||||
action = "submit_vaa";
|
||||
execute_msg = {
|
||||
data: fromUint8Array(vaa),
|
||||
|
@ -165,22 +166,22 @@ export async function execute_injective(
|
|||
}
|
||||
|
||||
export async function transferInjective(
|
||||
dstChain: ChainName,
|
||||
dstChain: Chain,
|
||||
dstAddress: string,
|
||||
tokenAddress: string,
|
||||
amount: string,
|
||||
network: Network,
|
||||
rpc: string
|
||||
) {
|
||||
if (network === "DEVNET") {
|
||||
if (network === "Devnet") {
|
||||
throw new Error("Injective is not supported in DEVNET");
|
||||
}
|
||||
const chain = "injective";
|
||||
const chain = "Injective";
|
||||
const { key } = NETWORKS[network][chain];
|
||||
if (!key) {
|
||||
throw Error(`No ${network} key defined for Injective`);
|
||||
}
|
||||
const { token_bridge } = CONTRACTS[network][chain];
|
||||
const token_bridge = contracts.tokenBridge.get(network, "Injective");
|
||||
if (token_bridge == undefined) {
|
||||
throw Error(`Unknown token bridge contract on ${network} for ${chain}`);
|
||||
}
|
||||
|
@ -193,8 +194,8 @@ export async function transferInjective(
|
|||
token_bridge,
|
||||
tokenAddress,
|
||||
amount,
|
||||
dstChain,
|
||||
tryNativeToUint8Array(dstAddress, dstChain)
|
||||
chainToChainId(dstChain),
|
||||
tryNativeToUint8Array(dstAddress, chainToChainId(dstChain))
|
||||
);
|
||||
|
||||
await signAndSendTx(walletPK, network, msgs);
|
||||
|
@ -268,18 +269,17 @@ export async function queryRegistrationsInjective(
|
|||
network: Network,
|
||||
module: "Core" | "NFTBridge" | "TokenBridge"
|
||||
) {
|
||||
const chain = "injective";
|
||||
const chain = "Injective";
|
||||
const n = NETWORKS[network][chain];
|
||||
const contracts = CONTRACTS[network][chain];
|
||||
|
||||
let targetContract: string | undefined;
|
||||
|
||||
switch (module) {
|
||||
case "TokenBridge":
|
||||
targetContract = contracts.token_bridge;
|
||||
targetContract = contracts.tokenBridge.get(network, "Injective");
|
||||
break;
|
||||
case "NFTBridge":
|
||||
targetContract = contracts.nft_bridge;
|
||||
targetContract = contracts.nftBridge.get(network, "Injective");
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Invalid module: ${module}`);
|
||||
|
@ -297,14 +297,14 @@ export async function queryRegistrationsInjective(
|
|||
|
||||
// Query the bridge registration for all the chains in parallel.
|
||||
const registrations: (any | null)[][] = await Promise.all(
|
||||
Object.entries(CHAINS)
|
||||
.filter(([cname, _]) => cname !== chain && cname !== "unset")
|
||||
.map(async ([cname, cid]) => [
|
||||
chains
|
||||
.filter((cname) => cname !== chain)
|
||||
.map(async (cname) => [
|
||||
cname,
|
||||
await (async () => {
|
||||
let query_msg = {
|
||||
chain_registration: {
|
||||
chain: cid,
|
||||
chain: chainToChainId(cname),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
import {
|
||||
ChainName,
|
||||
CONTRACTS,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import BN from "bn.js";
|
||||
import { Account, connect, KeyPair } from "near-api-js";
|
||||
import { InMemoryKeyStore } from "near-api-js/lib/key_stores";
|
||||
import { NETWORKS } from "./consts";
|
||||
import { Network } from "./utils";
|
||||
import { impossible, Payload } from "./vaa";
|
||||
import {
|
||||
transferNearFromNear,
|
||||
transferTokenFromNear,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/token_bridge/transfer";
|
||||
import { tryNativeToUint8Array } from "@certusone/wormhole-sdk/lib/esm/utils";
|
||||
import {
|
||||
Chain,
|
||||
chainToChainId,
|
||||
contracts,
|
||||
Network,
|
||||
} from "@wormhole-foundation/sdk-base";
|
||||
import { tryNativeToUint8Array } from "./sdk/array";
|
||||
|
||||
export function keyPairToImplicitAccount(keyPair: KeyPair): string {
|
||||
return Buffer.from(keyPair.getPublicKey().data).toString("hex");
|
||||
|
@ -23,7 +24,7 @@ export const execute_near = async (
|
|||
vaa: string,
|
||||
network: Network
|
||||
): Promise<void> => {
|
||||
const { rpc, key, networkId } = NETWORKS[network].near;
|
||||
const { rpc, key, networkId } = NETWORKS[network].Near;
|
||||
if (!key) {
|
||||
throw Error(`No ${network} key defined for NEAR`);
|
||||
}
|
||||
|
@ -32,16 +33,15 @@ export const execute_near = async (
|
|||
throw Error(`No ${network} rpc defined for NEAR`);
|
||||
}
|
||||
|
||||
const contracts = CONTRACTS[network].near;
|
||||
let target_contract: string;
|
||||
let numSubmits = 1;
|
||||
switch (payload.module) {
|
||||
case "Core": {
|
||||
if (!contracts.core) {
|
||||
const coreContract = contracts.coreBridge(network, "Near");
|
||||
if (!coreContract) {
|
||||
throw new Error(`Core bridge address not defined for NEAR ${network}`);
|
||||
}
|
||||
|
||||
target_contract = contracts.core;
|
||||
target_contract = coreContract;
|
||||
switch (payload.type) {
|
||||
case "GuardianSetUpgrade":
|
||||
console.log("Submitting new guardian set");
|
||||
|
@ -57,12 +57,13 @@ export const execute_near = async (
|
|||
break;
|
||||
}
|
||||
case "NFTBridge": {
|
||||
if (!contracts.nft_bridge) {
|
||||
const nftContract = contracts.nftBridge.get(network, "Near");
|
||||
if (!nftContract) {
|
||||
throw new Error(`NFT bridge address not defined for NEAR ${network}`);
|
||||
}
|
||||
|
||||
numSubmits = 2;
|
||||
target_contract = contracts.nft_bridge;
|
||||
target_contract = nftContract;
|
||||
switch (payload.type) {
|
||||
case "ContractUpgrade":
|
||||
console.log("Upgrading contract");
|
||||
|
@ -82,12 +83,13 @@ export const execute_near = async (
|
|||
break;
|
||||
}
|
||||
case "TokenBridge": {
|
||||
if (!contracts.token_bridge) {
|
||||
const tbContract = contracts.tokenBridge(network, "Near");
|
||||
if (!tbContract) {
|
||||
throw new Error(`Token bridge address not defined for NEAR ${network}`);
|
||||
}
|
||||
|
||||
numSubmits = 2;
|
||||
target_contract = contracts.token_bridge;
|
||||
target_contract = tbContract;
|
||||
switch (payload.type) {
|
||||
case "ContractUpgrade":
|
||||
console.log("Upgrading contract");
|
||||
|
@ -158,18 +160,19 @@ export const execute_near = async (
|
|||
};
|
||||
|
||||
export async function transferNear(
|
||||
dstChain: ChainName,
|
||||
dstChain: Chain,
|
||||
dstAddress: string,
|
||||
tokenAddress: string,
|
||||
amount: string,
|
||||
network: Network,
|
||||
rpc: string
|
||||
) {
|
||||
const { key, networkId } = NETWORKS[network].near;
|
||||
const { key, networkId } = NETWORKS[network].Near;
|
||||
if (!key) {
|
||||
throw Error(`No ${network} key defined for NEAR`);
|
||||
}
|
||||
const { core, token_bridge } = CONTRACTS[network].near;
|
||||
const core = contracts.coreBridge(network, "Near");
|
||||
const token_bridge = contracts.tokenBridge(network, "Near");
|
||||
if (core === undefined) {
|
||||
throw Error(`Unknown core contract on ${network} for NEAR`);
|
||||
}
|
||||
|
@ -193,8 +196,8 @@ export async function transferNear(
|
|||
core,
|
||||
token_bridge,
|
||||
BigInt(amount),
|
||||
tryNativeToUint8Array(dstAddress, dstChain),
|
||||
dstChain,
|
||||
tryNativeToUint8Array(dstAddress, chainToChainId(dstChain)),
|
||||
chainToChainId(dstChain),
|
||||
BigInt(0)
|
||||
);
|
||||
const result = await nearAccount.functionCall(msg);
|
||||
|
@ -207,8 +210,8 @@ export async function transferNear(
|
|||
token_bridge,
|
||||
tokenAddress,
|
||||
BigInt(amount),
|
||||
tryNativeToUint8Array(dstAddress, dstChain),
|
||||
dstChain,
|
||||
tryNativeToUint8Array(dstAddress, chainToChainId(dstChain)),
|
||||
chainToChainId(dstChain),
|
||||
BigInt(0)
|
||||
);
|
||||
for (const msg of msgs) {
|
||||
|
|
|
@ -0,0 +1,277 @@
|
|||
import { arrayify, zeroPad } from "@ethersproject/bytes";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import {
|
||||
hexValue,
|
||||
hexZeroPad,
|
||||
keccak256,
|
||||
sha256,
|
||||
stripZeros,
|
||||
} from "ethers/lib/utils";
|
||||
import { bech32 } from "bech32";
|
||||
import {
|
||||
Chain,
|
||||
ChainId,
|
||||
chainToChainId,
|
||||
chainToPlatform,
|
||||
toChain,
|
||||
toChainId,
|
||||
} from "@wormhole-foundation/sdk-base";
|
||||
import {
|
||||
PlatformToChains,
|
||||
UniversalAddress,
|
||||
encoding,
|
||||
} from "@wormhole-foundation/sdk";
|
||||
import {
|
||||
chainToNativeDenoms,
|
||||
CosmwasmAddress,
|
||||
} from "@wormhole-foundation/sdk-cosmwasm";
|
||||
import { isValidSuiAddress } from "@mysten/sui.js";
|
||||
import { sha3_256 } from "js-sha3";
|
||||
import {
|
||||
nativeStringToHexAlgorand,
|
||||
uint8ArrayToNativeStringAlgorand,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/algorand";
|
||||
import { isValidSuiType } from "@certusone/wormhole-sdk/lib/esm/sui";
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns true iff the hex string represents a native Terra denom.
|
||||
*
|
||||
* Native assets on terra don't have an associated smart contract address, just
|
||||
* like eth isn't an ERC-20 contract on Ethereum.
|
||||
*
|
||||
* The difference is that the EVM implementations of Portal don't support eth
|
||||
* directly, and instead require swapping to an ERC-20 wrapped eth (WETH)
|
||||
* contract first.
|
||||
*
|
||||
* The Terra implementation instead supports Terra-native denoms without
|
||||
* wrapping to CW-20 token first. As these denoms don't have an address, they
|
||||
* are encoded in the Portal payloads by the setting the first byte to 1. This
|
||||
* encoding is safe, because the first 12 bytes of the 32-byte wormhole address
|
||||
* space are not used on Terra otherwise, as cosmos addresses are 20 bytes wide.
|
||||
*/
|
||||
export const isHexNativeTerra = (h: string): boolean => h.startsWith("01");
|
||||
|
||||
const isLikely20ByteCosmwasm = (h: string): boolean =>
|
||||
h.startsWith("000000000000000000000000");
|
||||
|
||||
export const nativeTerraHexToDenom = (h: string): string =>
|
||||
Buffer.from(stripZeros(hexToUint8Array(h.substr(2)))).toString("ascii");
|
||||
|
||||
export const uint8ArrayToHex = (a: Uint8Array): string =>
|
||||
encoding.hex.encode(a);
|
||||
|
||||
export const hexToUint8Array = (h: string): Uint8Array =>
|
||||
encoding.hex.decode(h);
|
||||
|
||||
export function canonicalAddress(humanAddress: string) {
|
||||
return new Uint8Array(bech32.fromWords(bech32.decode(humanAddress).words));
|
||||
}
|
||||
|
||||
export function humanAddress(
|
||||
hrp: string,
|
||||
canonicalAddress: Uint8Array
|
||||
): string {
|
||||
return CosmwasmAddress.encode(hrp, canonicalAddress);
|
||||
}
|
||||
|
||||
export function buildTokenId(
|
||||
chain: Exclude<PlatformToChains<"Cosmwasm">, "Seda">,
|
||||
address: string
|
||||
) {
|
||||
return (
|
||||
(chainToNativeDenoms("Mainnet", chain) === address ? "01" : "00") +
|
||||
keccak256(Buffer.from(address, "utf-8")).substring(4)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Convert an address in a wormhole's 32-byte array representation into a chain's
|
||||
* native string representation.
|
||||
*
|
||||
* @throws if address is not the right length for the given chain
|
||||
*/
|
||||
|
||||
export const tryUint8ArrayToNative = (
|
||||
a: Uint8Array,
|
||||
chain: ChainId | Chain
|
||||
): string => {
|
||||
const chainName = toChain(chain);
|
||||
if (chainToPlatform(chainName) === "Evm") {
|
||||
// if (isEVMChain(chainId)) {
|
||||
return hexZeroPad(hexValue(a), 20);
|
||||
} else if (chainToPlatform(chainName) === "Solana") {
|
||||
return new PublicKey(a).toString();
|
||||
} else if (chainName === "Terra" || chainName === "Terra2") {
|
||||
const h = uint8ArrayToHex(a);
|
||||
if (isHexNativeTerra(h)) {
|
||||
return nativeTerraHexToDenom(h);
|
||||
} else {
|
||||
if (chainName === "Terra2" && !isLikely20ByteCosmwasm(h)) {
|
||||
// terra 2 has 32 byte addresses for contracts and 20 for wallets
|
||||
return humanAddress("terra", a);
|
||||
}
|
||||
return humanAddress("terra", a.slice(-20));
|
||||
}
|
||||
} else if (chainName === "Injective") {
|
||||
const h = uint8ArrayToHex(a);
|
||||
return humanAddress("inj", isLikely20ByteCosmwasm(h) ? a.slice(-20) : a);
|
||||
} else if (chainName === "Algorand") {
|
||||
return uint8ArrayToNativeStringAlgorand(a);
|
||||
} else if (chainName == "Wormchain") {
|
||||
const h = uint8ArrayToHex(a);
|
||||
return humanAddress(
|
||||
"wormhole",
|
||||
isLikely20ByteCosmwasm(h) ? a.slice(-20) : a
|
||||
);
|
||||
} else if (chainName === "Xpla") {
|
||||
const h = uint8ArrayToHex(a);
|
||||
return humanAddress("xpla", isLikely20ByteCosmwasm(h) ? a.slice(-20) : a);
|
||||
} else if (chainName === "Sei") {
|
||||
const h = uint8ArrayToHex(a);
|
||||
return humanAddress("sei", isLikely20ByteCosmwasm(h) ? a.slice(-20) : a);
|
||||
} else if (chainName === "Near") {
|
||||
throw Error("uint8ArrayToNative: Use tryHexToNativeStringNear instead.");
|
||||
} else if (chainName === "Osmosis") {
|
||||
throw Error("uint8ArrayToNative: Osmosis not supported yet.");
|
||||
} else if (chainName === "Cosmoshub") {
|
||||
throw Error("uint8ArrayToNative: CosmosHub not supported yet.");
|
||||
} else if (chainName === "Evmos") {
|
||||
throw Error("uint8ArrayToNative: Evmos not supported yet.");
|
||||
} else if (chainName === "Kujira") {
|
||||
throw Error("uint8ArrayToNative: Kujira not supported yet.");
|
||||
} else if (chainName === "Neutron") {
|
||||
throw Error("uint8ArrayToNative: Neutron not supported yet.");
|
||||
} else if (chainName === "Celestia") {
|
||||
throw Error("uint8ArrayToNative: Celestia not supported yet.");
|
||||
} else if (chainName === "Stargaze") {
|
||||
throw Error("uint8ArrayToNative: Stargaze not supported yet.");
|
||||
} else if (chainName === "Seda") {
|
||||
throw Error("uint8ArrayToNative: Seda not supported yet.");
|
||||
} else if (chainName === "Dymension") {
|
||||
throw Error("uint8ArrayToNative: Dymension not supported yet.");
|
||||
} else if (chainName === "Provenance") {
|
||||
throw Error("uint8ArrayToNative: Provenance not supported yet.");
|
||||
} else if (chainName === "Sui") {
|
||||
throw Error("uint8ArrayToNative: Sui not supported yet.");
|
||||
} else if (chainName === "Aptos") {
|
||||
throw Error("uint8ArrayToNative: Aptos not supported yet.");
|
||||
} else if (chainName === "Btc") {
|
||||
throw Error("uint8ArrayToNative: Btc not supported");
|
||||
} else {
|
||||
// This case is never reached
|
||||
// const _: never = chainName;
|
||||
throw Error("Don't know how to convert address for chain " + chainName);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Convert an address in a wormhole's 32-byte hex representation into a chain's native
|
||||
* string representation.
|
||||
*
|
||||
* @throws if address is not the right length for the given chain
|
||||
*/
|
||||
export const tryHexToNativeAssetString = (h: string, c: ChainId): string =>
|
||||
c === chainToChainId("Algorand")
|
||||
? // Algorand assets are represented by their asset ids, not an address
|
||||
new UniversalAddress(h).toNative("Algorand").toBigInt().toString()
|
||||
: new UniversalAddress(h).toNative(toChain(c)).toString();
|
||||
|
||||
/**
|
||||
*
|
||||
* Convert an address in a chain's native representation into a 32-byte hex string
|
||||
* understood by wormhole (UniversalAddress).
|
||||
*
|
||||
* @throws if address is a malformed string for the given chain id
|
||||
*/
|
||||
export const tryNativeToHexString = (
|
||||
address: string,
|
||||
chain: ChainId | Chain
|
||||
): string => {
|
||||
const chainName = toChain(chain);
|
||||
if (chainToPlatform(chainName) === "Evm") {
|
||||
return uint8ArrayToHex(zeroPad(arrayify(address), 32));
|
||||
} else if (chainToPlatform(chainName) === "Solana") {
|
||||
return uint8ArrayToHex(zeroPad(new PublicKey(address).toBytes(), 32));
|
||||
} else if (chainName === "Terra") {
|
||||
if (chainToNativeDenoms("Mainnet", chainName) === address) {
|
||||
return (
|
||||
"01" +
|
||||
uint8ArrayToHex(
|
||||
zeroPad(new Uint8Array(Buffer.from(address, "ascii")), 31)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
return uint8ArrayToHex(zeroPad(canonicalAddress(address), 32));
|
||||
}
|
||||
} else if (
|
||||
chainName === "Terra2" ||
|
||||
chainName === "Injective" ||
|
||||
chainName === "Xpla" ||
|
||||
chainName === "Sei"
|
||||
) {
|
||||
return buildTokenId(chainName, address);
|
||||
} else if (chainName === "Algorand") {
|
||||
return nativeStringToHexAlgorand(address);
|
||||
} else if (chainName == "Wormchain") {
|
||||
return uint8ArrayToHex(zeroPad(canonicalAddress(address), 32));
|
||||
} else if (chainName === "Near") {
|
||||
return uint8ArrayToHex(arrayify(sha256(Buffer.from(address))));
|
||||
} else if (chainName === "Sui") {
|
||||
if (!isValidSuiType(address) && isValidSuiAddress(address)) {
|
||||
return uint8ArrayToHex(
|
||||
zeroPad(arrayify(address, { allowMissingPrefix: true }), 32)
|
||||
);
|
||||
}
|
||||
throw Error("nativeToHexString: Sui types not supported yet.");
|
||||
} else if (chainName === "Aptos") {
|
||||
if (isValidAptosType(address)) {
|
||||
return getExternalAddressFromType(address);
|
||||
}
|
||||
|
||||
return uint8ArrayToHex(
|
||||
zeroPad(arrayify(address, { allowMissingPrefix: true }), 32)
|
||||
);
|
||||
} else {
|
||||
// If this case is reached
|
||||
throw Error(`nativeToHexString: ${chainName} not supported yet.`);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Convert an address in a chain's native representation into a 32-byte array
|
||||
* understood by wormhole.
|
||||
*
|
||||
* @throws if address is a malformed string for the given chain id
|
||||
*/
|
||||
export function tryNativeToUint8Array(
|
||||
address: string,
|
||||
chain: ChainId | Chain
|
||||
): Uint8Array {
|
||||
const chainId = toChainId(chain);
|
||||
return hexToUint8Array(tryNativeToHexString(address, chainId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if given string is a valid fully qualified type of moduleAddress::moduleName::structName.
|
||||
* @param str String to test
|
||||
* @returns Whether or not given string is a valid type
|
||||
*/
|
||||
export const isValidAptosType = (str: string): boolean =>
|
||||
/^(0x)?[0-9a-fA-F]+::\w+::\w+$/.test(str);
|
||||
|
||||
/**
|
||||
* Hashes the given type. Because fully qualified types are a concept unique to Aptos, this
|
||||
* output acts as the address on other chains.
|
||||
* @param fullyQualifiedType Fully qualified type on Aptos
|
||||
* @returns External address corresponding to given type
|
||||
*/
|
||||
export const getExternalAddressFromType = (
|
||||
fullyQualifiedType: string
|
||||
): string => {
|
||||
// hash the type so it fits into 32 bytes
|
||||
return sha3_256(fullyQualifiedType);
|
||||
};
|
|
@ -0,0 +1,130 @@
|
|||
import {
|
||||
JsonRpcProvider,
|
||||
SuiObjectResponse,
|
||||
isValidSuiAddress as isValidFullSuiAddress,
|
||||
normalizeSuiAddress,
|
||||
} from "@mysten/sui.js";
|
||||
import { Chain, chainToChainId } from "@wormhole-foundation/sdk";
|
||||
|
||||
export async function getForeignAssetSui(
|
||||
provider: JsonRpcProvider,
|
||||
tokenBridgeStateObjectId: string,
|
||||
originChain: Chain,
|
||||
originAddress: Uint8Array
|
||||
): Promise<string | null> {
|
||||
const originChainId = chainToChainId(originChain);
|
||||
return getTokenCoinType(
|
||||
provider,
|
||||
tokenBridgeStateObjectId,
|
||||
originAddress,
|
||||
originChainId
|
||||
);
|
||||
}
|
||||
|
||||
export const getTokenCoinType = async (
|
||||
provider: JsonRpcProvider,
|
||||
tokenBridgeStateObjectId: string,
|
||||
tokenAddress: Uint8Array,
|
||||
tokenChain: number
|
||||
): Promise<string | null> => {
|
||||
const tokenBridgeStateFields = await getObjectFields(
|
||||
provider,
|
||||
tokenBridgeStateObjectId
|
||||
);
|
||||
if (!tokenBridgeStateFields) {
|
||||
throw new Error("Unable to fetch object fields from token bridge state");
|
||||
}
|
||||
|
||||
const coinTypes = tokenBridgeStateFields?.token_registry?.fields?.coin_types;
|
||||
const coinTypesObjectId = coinTypes?.fields?.id?.id;
|
||||
if (!coinTypesObjectId) {
|
||||
throw new Error("Unable to fetch coin types");
|
||||
}
|
||||
|
||||
const keyType = getTableKeyType(coinTypes?.type);
|
||||
if (!keyType) {
|
||||
throw new Error("Unable to get key type");
|
||||
}
|
||||
|
||||
const response = await provider.getDynamicFieldObject({
|
||||
parentId: coinTypesObjectId,
|
||||
name: {
|
||||
type: keyType,
|
||||
value: {
|
||||
addr: [...tokenAddress],
|
||||
chain: tokenChain,
|
||||
},
|
||||
},
|
||||
});
|
||||
if (response.error) {
|
||||
if (response.error.code === "dynamicFieldNotFound") {
|
||||
return null;
|
||||
}
|
||||
throw new Error(
|
||||
`Unexpected getDynamicFieldObject response ${response.error}`
|
||||
);
|
||||
}
|
||||
const fields = getFieldsFromObjectResponse(response);
|
||||
return fields?.value ? trimSuiType(ensureHexPrefix(fields.value)) : null;
|
||||
};
|
||||
|
||||
export const getObjectFields = async (
|
||||
provider: JsonRpcProvider,
|
||||
objectId: string
|
||||
): Promise<Record<string, any> | null> => {
|
||||
if (!isValidSuiAddress(objectId)) {
|
||||
throw new Error(`Invalid object ID: ${objectId}`);
|
||||
}
|
||||
|
||||
const res = await provider.getObject({
|
||||
id: objectId,
|
||||
options: {
|
||||
showContent: true,
|
||||
},
|
||||
});
|
||||
return getFieldsFromObjectResponse(res);
|
||||
};
|
||||
|
||||
export const getFieldsFromObjectResponse = (object: SuiObjectResponse) => {
|
||||
const content = object.data?.content;
|
||||
return content && content.dataType === "moveObject" ? content.fields : null;
|
||||
};
|
||||
|
||||
export function ensureHexPrefix(x: string): string {
|
||||
return x.substring(0, 2) !== "0x" ? `0x${x}` : x;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method validates any Sui address, even if it's not 32 bytes long, i.e.
|
||||
* "0x2". This differs from Mysten's implementation, which requires that the
|
||||
* given address is 32 bytes long.
|
||||
* @param address Address to check
|
||||
* @returns If given address is a valid Sui address or not
|
||||
*/
|
||||
export const isValidSuiAddress = (address: string): boolean =>
|
||||
isValidFullSuiAddress(normalizeSuiAddress(address));
|
||||
|
||||
export const getTableKeyType = (tableType: string): string | null => {
|
||||
if (!tableType) return null;
|
||||
const match = trimSuiType(tableType).match(/0x2::table::Table<(.*)>/);
|
||||
if (!match) return null;
|
||||
const [keyType] = match[1].split(",");
|
||||
if (!isValidSuiType(keyType)) return null;
|
||||
return keyType;
|
||||
};
|
||||
|
||||
/**
|
||||
* This method removes leading zeroes for types in order to normalize them
|
||||
* since some types returned from the RPC have leading zeroes and others don't.
|
||||
*/
|
||||
export const trimSuiType = (type: string): string =>
|
||||
type.replace(/(0x)(0*)/g, "0x");
|
||||
|
||||
export const isValidSuiType = (type: string): boolean => {
|
||||
const tokens = type.split("::");
|
||||
if (tokens.length !== 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isValidSuiAddress(tokens[0]) && !!tokens[1] && !!tokens[2];
|
||||
};
|
|
@ -16,13 +16,6 @@ import {
|
|||
createUpgradeGuardianSetInstruction,
|
||||
createUpgradeContractInstruction as createWormholeUpgradeContractInstruction,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/solana/wormhole";
|
||||
import {
|
||||
CHAINS,
|
||||
CONTRACTS,
|
||||
ChainName,
|
||||
Network,
|
||||
SolanaChainName,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import * as web3s from "@solana/web3.js";
|
||||
import base58 from "bs58";
|
||||
import { NETWORKS } from "./consts";
|
||||
|
@ -32,19 +25,30 @@ import {
|
|||
transferFromSolana,
|
||||
transferNativeSol,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/token_bridge/transfer";
|
||||
import {
|
||||
hexToUint8Array,
|
||||
tryNativeToUint8Array,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import { getAssociatedTokenAddress } from "@solana/spl-token";
|
||||
import {
|
||||
Chain,
|
||||
Network,
|
||||
PlatformToChains,
|
||||
chainToChainId,
|
||||
chainToPlatform,
|
||||
chains,
|
||||
contracts,
|
||||
platformToChains,
|
||||
} from "@wormhole-foundation/sdk-base";
|
||||
import { hexToUint8Array, tryNativeToUint8Array } from "./sdk/array";
|
||||
|
||||
export async function execute_solana(
|
||||
v: VAA<Payload>,
|
||||
vaa: Buffer,
|
||||
network: "MAINNET" | "TESTNET" | "DEVNET",
|
||||
chain: SolanaChainName
|
||||
network: Network,
|
||||
chain: Chain
|
||||
) {
|
||||
if (chainToPlatform(chain) !== "Solana") {
|
||||
// This "Solana" platform, also, includes Pythnet
|
||||
throw new Error("Invalid chain");
|
||||
}
|
||||
const { rpc, key } = NETWORKS[network][chain];
|
||||
if (!key) {
|
||||
throw Error(`No ${network} key defined for ${chain}`);
|
||||
|
@ -57,22 +61,24 @@ export async function execute_solana(
|
|||
const connection = setupConnection(rpc);
|
||||
const from = web3s.Keypair.fromSecretKey(base58.decode(key));
|
||||
|
||||
const contracts = CONTRACTS[network][chain];
|
||||
if (!contracts.core) {
|
||||
const coreContract = contracts.coreBridge.get(network, chain);
|
||||
if (!coreContract) {
|
||||
throw new Error(`Core bridge address not defined for ${chain} ${network}`);
|
||||
}
|
||||
|
||||
if (!contracts.nft_bridge) {
|
||||
const nftContract = contracts.nftBridge.get(network, chain);
|
||||
if (!nftContract) {
|
||||
throw new Error(`NFT bridge address not defined for ${chain} ${network}`);
|
||||
}
|
||||
|
||||
if (!contracts.token_bridge) {
|
||||
const tbContract = contracts.tokenBridge.get(network, chain);
|
||||
if (!tbContract) {
|
||||
throw new Error(`Token bridge address not defined for ${chain} ${network}`);
|
||||
}
|
||||
|
||||
const bridgeId = new web3s.PublicKey(contracts.core);
|
||||
const tokenBridgeId = new web3s.PublicKey(contracts.token_bridge);
|
||||
const nftBridgeId = new web3s.PublicKey(contracts.nft_bridge);
|
||||
const bridgeId = new web3s.PublicKey(coreContract);
|
||||
const tokenBridgeId = new web3s.PublicKey(tbContract);
|
||||
const nftBridgeId = new web3s.PublicKey(nftContract);
|
||||
|
||||
let ix: web3s.TransactionInstruction;
|
||||
switch (v.payload.module) {
|
||||
|
@ -163,7 +169,7 @@ export async function execute_solana(
|
|||
break;
|
||||
case "Transfer":
|
||||
console.log("Completing transfer");
|
||||
if (payload.tokenChain === CHAINS[chain]) {
|
||||
if (payload.tokenChain === chainToChainId(chain)) {
|
||||
ix = createCompleteTransferNativeInstruction(
|
||||
tokenBridgeId,
|
||||
bridgeId,
|
||||
|
@ -228,14 +234,15 @@ export async function execute_solana(
|
|||
}
|
||||
|
||||
export async function transferSolana(
|
||||
srcChain: SolanaChainName,
|
||||
dstChain: ChainName,
|
||||
srcChain: PlatformToChains<"Solana">,
|
||||
dstChain: Chain,
|
||||
dstAddress: string,
|
||||
tokenAddress: string,
|
||||
amount: string,
|
||||
network: Network,
|
||||
rpc: string
|
||||
) {
|
||||
platformToChains("Solana");
|
||||
const { key } = NETWORKS[network][srcChain];
|
||||
if (!key) {
|
||||
throw Error(`No ${network} key defined for ${srcChain}`);
|
||||
|
@ -244,12 +251,13 @@ export async function transferSolana(
|
|||
const connection = setupConnection(rpc);
|
||||
const keypair = web3s.Keypair.fromSecretKey(base58.decode(key));
|
||||
|
||||
const { core, token_bridge } = CONTRACTS[network][srcChain];
|
||||
const core = contracts.coreBridge.get(network, srcChain);
|
||||
if (!core) {
|
||||
throw new Error(
|
||||
`Core bridge address not defined for ${srcChain} ${network}`
|
||||
);
|
||||
}
|
||||
const token_bridge = contracts.tokenBridge.get(network, srcChain);
|
||||
if (!token_bridge) {
|
||||
throw new Error(
|
||||
`Token bridge address not defined for ${srcChain} ${network}`
|
||||
|
@ -268,8 +276,8 @@ export async function transferSolana(
|
|||
tokenBridgeId,
|
||||
payerAddress,
|
||||
BigInt(amount),
|
||||
tryNativeToUint8Array(dstAddress, dstChain),
|
||||
dstChain
|
||||
tryNativeToUint8Array(dstAddress, chainToChainId(dstChain)),
|
||||
chainToChainId(dstChain)
|
||||
);
|
||||
} else {
|
||||
// find the associated token account
|
||||
|
@ -287,8 +295,8 @@ export async function transferSolana(
|
|||
fromAddress,
|
||||
tokenAddress, // mintAddress
|
||||
BigInt(amount),
|
||||
tryNativeToUint8Array(dstAddress, dstChain),
|
||||
dstChain
|
||||
tryNativeToUint8Array(dstAddress, chainToChainId(dstChain)),
|
||||
chainToChainId(dstChain)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -316,18 +324,17 @@ export async function queryRegistrationsSolana(
|
|||
network: Network,
|
||||
module: "Core" | "NFTBridge" | "TokenBridge"
|
||||
): Promise<Object> {
|
||||
const chain = "solana" as ChainName;
|
||||
const chain = "Solana";
|
||||
const n = NETWORKS[network][chain];
|
||||
const contracts = CONTRACTS[network][chain];
|
||||
|
||||
let targetAddress: string | undefined;
|
||||
|
||||
switch (module) {
|
||||
case "TokenBridge":
|
||||
targetAddress = contracts.token_bridge;
|
||||
targetAddress = contracts.tokenBridge(network, chain);
|
||||
break;
|
||||
case "NFTBridge":
|
||||
targetAddress = contracts.nft_bridge;
|
||||
targetAddress = contracts.nftBridge(network, chain);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Invalid module: ${module}`);
|
||||
|
@ -346,26 +353,26 @@ export async function queryRegistrationsSolana(
|
|||
|
||||
// Query the bridge registration for all the chains in parallel.
|
||||
const registrations: (string | null)[][] = await Promise.all(
|
||||
Object.entries(CHAINS)
|
||||
.filter(([cname, _]) => cname !== chain && cname !== "unset")
|
||||
.map(async ([cstr, cid]) => [
|
||||
chains
|
||||
.filter((cname) => cname !== chain)
|
||||
.map(async (cstr) => [
|
||||
cstr,
|
||||
await (async () => {
|
||||
let cname = cstr as ChainName;
|
||||
// let cname = cstr as Chain;
|
||||
let addr: string | undefined;
|
||||
if (module === "TokenBridge") {
|
||||
addr = CONTRACTS[network][cname].token_bridge;
|
||||
addr = contracts.tokenBridge.get(network, cstr);
|
||||
} else {
|
||||
addr = CONTRACTS[network][cname].nft_bridge;
|
||||
addr = contracts.nftBridge.get(network, cstr);
|
||||
}
|
||||
if (addr === undefined) {
|
||||
return null;
|
||||
}
|
||||
let emitter_addr = await getEmitterAddress(cname as ChainName, addr);
|
||||
let emitter_addr = await getEmitterAddress(cstr, addr);
|
||||
|
||||
const endpoint = deriveEndpointKey(
|
||||
programId,
|
||||
cid,
|
||||
chainToChainId(cstr),
|
||||
hexToUint8Array(emitter_addr)
|
||||
);
|
||||
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
import {
|
||||
CHAINS,
|
||||
CONTRACTS,
|
||||
ChainName,
|
||||
TerraChainName,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import {
|
||||
Coin,
|
||||
Fee,
|
||||
|
@ -15,24 +9,29 @@ import {
|
|||
import axios from "axios";
|
||||
import { fromUint8Array } from "js-base64";
|
||||
import { NETWORKS } from "./consts";
|
||||
import { Network } from "./utils";
|
||||
import { Payload, impossible } from "./vaa";
|
||||
import { transferFromTerra } from "@certusone/wormhole-sdk/lib/esm/token_bridge/transfer";
|
||||
import { tryNativeToUint8Array } from "@certusone/wormhole-sdk/lib/esm/utils";
|
||||
import {
|
||||
Chain,
|
||||
Network,
|
||||
chains,
|
||||
contracts,
|
||||
toChainId,
|
||||
} from "@wormhole-foundation/sdk-base";
|
||||
import { tryNativeToUint8Array } from "./sdk/array";
|
||||
|
||||
export async function execute_terra(
|
||||
payload: Payload,
|
||||
vaa: Buffer,
|
||||
network: Network,
|
||||
chain: TerraChainName
|
||||
chain: "Terra" | "Terra2"
|
||||
): Promise<void> {
|
||||
const { rpc, key, chain_id } = NETWORKS[network][chain];
|
||||
const contracts = CONTRACTS[network][chain];
|
||||
|
||||
const terra = new LCDClient({
|
||||
URL: rpc,
|
||||
chainID: chain_id,
|
||||
isClassic: chain === "terra",
|
||||
isClassic: chain === "Terra",
|
||||
});
|
||||
|
||||
const wallet = terra.wallet(
|
||||
|
@ -46,13 +45,14 @@ export async function execute_terra(
|
|||
|
||||
switch (payload.module) {
|
||||
case "Core": {
|
||||
if (!contracts.core) {
|
||||
const coreContract = contracts.coreBridge(network, chain);
|
||||
if (!coreContract) {
|
||||
throw new Error(
|
||||
`Core bridge address not defined for ${chain} ${network}`
|
||||
);
|
||||
}
|
||||
|
||||
target_contract = contracts.core;
|
||||
target_contract = coreContract;
|
||||
// sigh...
|
||||
execute_msg = {
|
||||
submit_v_a_a: {
|
||||
|
@ -75,14 +75,15 @@ export async function execute_terra(
|
|||
break;
|
||||
}
|
||||
case "NFTBridge": {
|
||||
if (!contracts.nft_bridge) {
|
||||
const nftContract = contracts.nftBridge.get(network, chain);
|
||||
if (!nftContract) {
|
||||
// NOTE: this code can safely be removed once the terra NFT bridge is
|
||||
// released, but it's fine for it to stay, as the condition will just be
|
||||
// skipped once 'contracts.nft_bridge' is defined
|
||||
throw new Error(`NFT bridge not supported yet for ${chain}`);
|
||||
}
|
||||
|
||||
target_contract = contracts.nft_bridge;
|
||||
target_contract = nftContract;
|
||||
execute_msg = {
|
||||
submit_vaa: {
|
||||
data: fromUint8Array(vaa),
|
||||
|
@ -107,13 +108,14 @@ export async function execute_terra(
|
|||
break;
|
||||
}
|
||||
case "TokenBridge": {
|
||||
if (!contracts.token_bridge) {
|
||||
const tbContract = contracts.tokenBridge.get(network, chain);
|
||||
if (!tbContract) {
|
||||
throw new Error(
|
||||
`Token bridge address not defined for ${chain} ${network}`
|
||||
);
|
||||
}
|
||||
|
||||
target_contract = contracts.token_bridge;
|
||||
target_contract = tbContract;
|
||||
execute_msg = {
|
||||
submit_vaa: {
|
||||
data: fromUint8Array(vaa),
|
||||
|
@ -160,8 +162,8 @@ export async function execute_terra(
|
|||
}
|
||||
|
||||
export async function transferTerra(
|
||||
srcChain: TerraChainName,
|
||||
dstChain: ChainName,
|
||||
srcChain: "Terra" | "Terra2",
|
||||
dstChain: Chain,
|
||||
dstAddress: string,
|
||||
tokenAddress: string,
|
||||
amount: string,
|
||||
|
@ -172,7 +174,7 @@ export async function transferTerra(
|
|||
if (!n.key) {
|
||||
throw Error(`No ${network} key defined for ${srcChain} (see networks.ts)`);
|
||||
}
|
||||
const { token_bridge } = CONTRACTS[network][srcChain];
|
||||
const token_bridge = contracts.tokenBridge.get(network, srcChain);
|
||||
if (!token_bridge) {
|
||||
throw Error(`Unknown token bridge contract on ${network} for ${srcChain}`);
|
||||
}
|
||||
|
@ -180,7 +182,7 @@ export async function transferTerra(
|
|||
const terra = new LCDClient({
|
||||
URL: rpc,
|
||||
chainID: n.chain_id,
|
||||
isClassic: srcChain === "terra",
|
||||
isClassic: srcChain === "Terra",
|
||||
});
|
||||
|
||||
const wallet = terra.wallet(
|
||||
|
@ -194,8 +196,8 @@ export async function transferTerra(
|
|||
token_bridge,
|
||||
tokenAddress,
|
||||
amount,
|
||||
dstChain,
|
||||
tryNativeToUint8Array(dstAddress, dstChain)
|
||||
toChainId(dstChain),
|
||||
tryNativeToUint8Array(dstAddress, toChainId(dstChain))
|
||||
);
|
||||
await signAndSendTx(terra, wallet, msgs);
|
||||
}
|
||||
|
@ -242,20 +244,19 @@ async function signAndSendTx(
|
|||
|
||||
export async function queryRegistrationsTerra(
|
||||
network: Network,
|
||||
chain: TerraChainName,
|
||||
chain: "Terra" | "Terra2",
|
||||
module: "Core" | "NFTBridge" | "TokenBridge"
|
||||
): Promise<Object> {
|
||||
const n = NETWORKS[network][chain];
|
||||
const contracts = CONTRACTS[network][chain];
|
||||
|
||||
let targetContract: string | undefined;
|
||||
|
||||
switch (module) {
|
||||
case "TokenBridge":
|
||||
targetContract = contracts.token_bridge;
|
||||
targetContract = contracts.tokenBridge(network, chain);
|
||||
break;
|
||||
case "NFTBridge":
|
||||
targetContract = contracts.nft_bridge;
|
||||
targetContract = contracts.nftBridge.get(network, chain);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Invalid module: ${module}`);
|
||||
|
@ -276,19 +277,19 @@ export async function queryRegistrationsTerra(
|
|||
const client = new LCDClient({
|
||||
URL: n.rpc,
|
||||
chainID: n.chain_id,
|
||||
isClassic: chain === "terra",
|
||||
isClassic: chain === "Terra",
|
||||
});
|
||||
|
||||
// Query the bridge registration for all the chains in parallel.
|
||||
const registrations: (string | null)[][] = await Promise.all(
|
||||
Object.entries(CHAINS)
|
||||
.filter(([cname, _]) => cname !== chain && cname !== "unset")
|
||||
.map(async ([cname, cid]) => [
|
||||
chains
|
||||
.filter((cname) => cname !== chain)
|
||||
.map(async (cname) => [
|
||||
cname,
|
||||
await (async () => {
|
||||
let query_msg = {
|
||||
chain_registration: {
|
||||
chain: cid,
|
||||
chain: toChainId(cname),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import {
|
||||
Chain,
|
||||
ChainId,
|
||||
Network,
|
||||
PlatformToChains,
|
||||
chainToPlatform,
|
||||
toChain,
|
||||
} from "@wormhole-foundation/sdk-base";
|
||||
import { spawnSync } from "child_process";
|
||||
import { ethers } from "ethers";
|
||||
|
||||
export type Network = "MAINNET" | "TESTNET" | "DEVNET";
|
||||
|
||||
export function assertNetwork(n: string): asserts n is Network {
|
||||
if (n !== "MAINNET" && n !== "TESTNET" && n !== "DEVNET") {
|
||||
throw Error(`Unknown network: ${n}`);
|
||||
}
|
||||
}
|
||||
|
||||
export const checkBinary = (binaryName: string, readmeUrl?: string): void => {
|
||||
const binary = spawnSync(binaryName, ["--version"]);
|
||||
if (binary.status !== 0) {
|
||||
|
@ -29,3 +29,33 @@ export const evm_address = (x: string): string => {
|
|||
export const hex = (x: string): string => {
|
||||
return ethers.utils.hexlify(x, { allowMissingPrefix: true });
|
||||
};
|
||||
|
||||
export function assertEVMChain(
|
||||
chain: ChainId | Chain
|
||||
): asserts chain is PlatformToChains<"Evm"> {
|
||||
if (chainToPlatform(toChain(chain)) !== "Evm") {
|
||||
throw Error(`Expected an EVM chain, but ${chain} is not`);
|
||||
}
|
||||
}
|
||||
|
||||
export function getNetwork(network: string): Network {
|
||||
const lcNetwork: string = network.toLowerCase();
|
||||
if (lcNetwork === "mainnet") {
|
||||
return "Mainnet";
|
||||
}
|
||||
if (lcNetwork === "testnet") {
|
||||
return "Testnet";
|
||||
}
|
||||
if (lcNetwork === "devnet") {
|
||||
return "Devnet";
|
||||
}
|
||||
throw new Error(`Unknown network: ${network}`);
|
||||
}
|
||||
|
||||
export function chainToChain(input: string): Chain {
|
||||
if (input.length < 2) {
|
||||
throw new Error(`Invalid chain: ${input}`);
|
||||
}
|
||||
const chainStr = input[0].toUpperCase() + input.slice(1).toLowerCase();
|
||||
return toChain(chainStr);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
import {
|
||||
CONTRACTS,
|
||||
ChainName,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import {
|
||||
Coin,
|
||||
Fee,
|
||||
|
@ -12,18 +8,22 @@ import {
|
|||
} from "@xpla/xpla.js";
|
||||
import { fromUint8Array } from "js-base64";
|
||||
import { NETWORKS } from "./consts";
|
||||
import { Network } from "./utils";
|
||||
import { Payload, impossible } from "./vaa";
|
||||
import { transferFromXpla } from "@certusone/wormhole-sdk/lib/esm/token_bridge/transfer";
|
||||
import { tryNativeToUint8Array } from "@certusone/wormhole-sdk/lib/esm/utils";
|
||||
import {
|
||||
Chain,
|
||||
chainToChainId,
|
||||
contracts,
|
||||
Network,
|
||||
} from "@wormhole-foundation/sdk-base";
|
||||
import { tryNativeToUint8Array } from "./sdk/array";
|
||||
|
||||
export async function execute_xpla(
|
||||
payload: Payload,
|
||||
vaa: Buffer,
|
||||
network: Network
|
||||
) {
|
||||
const { rpc, key, chain_id } = NETWORKS[network].xpla;
|
||||
const contracts = CONTRACTS[network].xpla;
|
||||
const { rpc, key, chain_id } = NETWORKS[network].Xpla;
|
||||
if (!key) {
|
||||
throw Error(`No ${network} key defined for XPLA`);
|
||||
}
|
||||
|
@ -47,11 +47,12 @@ export async function execute_xpla(
|
|||
let execute_msg: object;
|
||||
switch (payload.module) {
|
||||
case "Core": {
|
||||
if (!contracts.core) {
|
||||
const coreContract = contracts.coreBridge.get(network, "Xpla");
|
||||
if (!coreContract) {
|
||||
throw new Error(`Core bridge address not defined for XPLA ${network}`);
|
||||
}
|
||||
|
||||
target_contract = contracts.core;
|
||||
target_contract = coreContract;
|
||||
execute_msg = {
|
||||
submit_v_a_a: {
|
||||
vaa: fromUint8Array(vaa),
|
||||
|
@ -73,14 +74,15 @@ export async function execute_xpla(
|
|||
break;
|
||||
}
|
||||
case "NFTBridge": {
|
||||
if (!contracts.nft_bridge) {
|
||||
const nftContract = contracts.nftBridge.get(network, "Xpla");
|
||||
if (!nftContract) {
|
||||
// NOTE: this code can safely be removed once the terra NFT bridge is
|
||||
// released, but it's fine for it to stay, as the condition will just be
|
||||
// skipped once 'contracts.nft_bridge' is defined
|
||||
throw new Error("NFT bridge not supported yet for XPLA");
|
||||
}
|
||||
|
||||
target_contract = contracts.nft_bridge;
|
||||
target_contract = nftContract;
|
||||
execute_msg = {
|
||||
submit_vaa: {
|
||||
data: fromUint8Array(vaa),
|
||||
|
@ -105,11 +107,12 @@ export async function execute_xpla(
|
|||
break;
|
||||
}
|
||||
case "TokenBridge": {
|
||||
if (!contracts.token_bridge) {
|
||||
const tbContract = contracts.tokenBridge.get(network, "Xpla");
|
||||
if (!tbContract) {
|
||||
throw new Error(`Token bridge address not defined for XPLA ${network}`);
|
||||
}
|
||||
|
||||
target_contract = contracts.token_bridge;
|
||||
target_contract = tbContract;
|
||||
execute_msg = {
|
||||
submit_vaa: {
|
||||
data: fromUint8Array(vaa),
|
||||
|
@ -156,18 +159,18 @@ export async function execute_xpla(
|
|||
}
|
||||
|
||||
export async function transferXpla(
|
||||
dstChain: ChainName,
|
||||
dstChain: Chain,
|
||||
dstAddress: string,
|
||||
tokenAddress: string,
|
||||
amount: string,
|
||||
network: Network,
|
||||
rpc: string
|
||||
) {
|
||||
const { key, chain_id } = NETWORKS[network].xpla;
|
||||
const { key, chain_id } = NETWORKS[network].Xpla;
|
||||
if (!key) {
|
||||
throw Error(`No ${network} key defined for XPLA`);
|
||||
}
|
||||
const { token_bridge } = CONTRACTS[network].xpla;
|
||||
const token_bridge = contracts.tokenBridge.get(network, "Xpla");
|
||||
if (token_bridge == undefined) {
|
||||
throw Error(`Unknown token bridge contract on ${network} for XPLA`);
|
||||
}
|
||||
|
@ -185,8 +188,8 @@ export async function transferXpla(
|
|||
token_bridge,
|
||||
tokenAddress,
|
||||
amount,
|
||||
dstChain,
|
||||
tryNativeToUint8Array(dstAddress, dstChain)
|
||||
chainToChainId(dstChain),
|
||||
tryNativeToUint8Array(dstAddress, chainToChainId(dstChain))
|
||||
);
|
||||
await signAndSendTx(client, wallet, msgs);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
"outDir": "./build",
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue