clients/js: Added transfer token command
This commit is contained in:
parent
44273c0641
commit
817f179b34
|
@ -18,6 +18,7 @@
|
|||
"@injectivelabs/utils": "^1.10.5",
|
||||
"@mysten/sui.js": "^0.32.2",
|
||||
"@sei-js/core": "^1.3.2",
|
||||
"@solana/spl-token": "^0.3.5",
|
||||
"@solana/web3.js": "^1.22.0",
|
||||
"@terra-money/terra.js": "^3.1.3",
|
||||
"@types/config": "^3.3.0",
|
||||
|
@ -3223,9 +3224,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@solana/spl-token": {
|
||||
"version": "0.3.7",
|
||||
"resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.3.7.tgz",
|
||||
"integrity": "sha512-bKGxWTtIw6VDdCBngjtsGlKGLSmiu/8ghSt/IOYJV24BsymRbgq7r12GToeetpxmPaZYLddKwAz7+EwprLfkfg==",
|
||||
"version": "0.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.3.5.tgz",
|
||||
"integrity": "sha512-0bGC6n415lGjKu02gkLOIpP1wzndSP0SHwN9PefJ+wKAhmfU1rl3AV1Pa41uap2kzSCD6F9642ngNO8KXPvh/g==",
|
||||
"dependencies": {
|
||||
"@solana/buffer-layout": "^4.0.0",
|
||||
"@solana/buffer-layout-utils": "^0.2.0",
|
||||
|
@ -10594,9 +10595,9 @@
|
|||
}
|
||||
},
|
||||
"@solana/spl-token": {
|
||||
"version": "0.3.7",
|
||||
"resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.3.7.tgz",
|
||||
"integrity": "sha512-bKGxWTtIw6VDdCBngjtsGlKGLSmiu/8ghSt/IOYJV24BsymRbgq7r12GToeetpxmPaZYLddKwAz7+EwprLfkfg==",
|
||||
"version": "0.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.3.5.tgz",
|
||||
"integrity": "sha512-0bGC6n415lGjKu02gkLOIpP1wzndSP0SHwN9PefJ+wKAhmfU1rl3AV1Pa41uap2kzSCD6F9642ngNO8KXPvh/g==",
|
||||
"requires": {
|
||||
"@solana/buffer-layout": "^4.0.0",
|
||||
"@solana/buffer-layout-utils": "^0.2.0",
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
"@injectivelabs/utils": "^1.10.5",
|
||||
"@mysten/sui.js": "^0.32.2",
|
||||
"@sei-js/core": "^1.3.2",
|
||||
"@solana/spl-token": "^0.3.5",
|
||||
"@solana/web3.js": "^1.22.0",
|
||||
"@terra-money/terra.js": "^3.1.3",
|
||||
"@types/config": "^3.3.0",
|
||||
|
|
|
@ -2,11 +2,16 @@ import {
|
|||
_submitVAAAlgorand,
|
||||
signSendAndConfirmAlgorand,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/algorand";
|
||||
import { CONTRACTS } from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
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";
|
||||
|
||||
export async function execute_algorand(
|
||||
payload: Payload,
|
||||
|
@ -25,16 +30,6 @@ export async function execute_algorand(
|
|||
|
||||
const contracts = CONTRACTS[network][chainName];
|
||||
console.log("contracts", contracts);
|
||||
const ALGORAND_HOST = {
|
||||
algodToken: "",
|
||||
algodServer: rpc,
|
||||
algodPort: "",
|
||||
};
|
||||
if (network === "DEVNET") {
|
||||
ALGORAND_HOST.algodToken =
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
||||
ALGORAND_HOST.algodPort = "4001";
|
||||
}
|
||||
|
||||
let target_contract: string;
|
||||
switch (payload.module) {
|
||||
|
@ -127,11 +122,7 @@ export async function execute_algorand(
|
|||
|
||||
const target = BigInt(parseInt(target_contract));
|
||||
const CORE_ID = BigInt(parseInt(contracts.core));
|
||||
const algodClient = new Algodv2(
|
||||
ALGORAND_HOST.algodToken,
|
||||
ALGORAND_HOST.algodServer,
|
||||
ALGORAND_HOST.algodPort
|
||||
);
|
||||
const algodClient = getClient(network, rpc);
|
||||
const algoWallet: Account = mnemonicToSecretKey(key);
|
||||
|
||||
// Create transaction
|
||||
|
@ -147,3 +138,59 @@ export async function execute_algorand(
|
|||
const result = await signSendAndConfirmAlgorand(algodClient, txs, algoWallet);
|
||||
console.log("Confirmed in round:", result["confirmed-round"]);
|
||||
}
|
||||
|
||||
export async function transferAlgorand(
|
||||
dstChain: ChainName,
|
||||
dstAddress: string,
|
||||
tokenAddress: string,
|
||||
amount: string,
|
||||
network: Network,
|
||||
rpc: string
|
||||
) {
|
||||
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);
|
||||
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,
|
||||
CORE_ID,
|
||||
wallet.addr,
|
||||
assetId,
|
||||
BigInt(amount),
|
||||
recipient,
|
||||
dstChain,
|
||||
BigInt(0)
|
||||
);
|
||||
const result = await signSendAndConfirmAlgorand(client, txs, wallet);
|
||||
console.log("Confirmed in round:", result["confirmed-round"]);
|
||||
}
|
||||
|
||||
function getClient(network: Network, rpc: string) {
|
||||
const ALGORAND_HOST = {
|
||||
algodToken: "",
|
||||
algodServer: rpc,
|
||||
algodPort: "",
|
||||
};
|
||||
if (network === "DEVNET") {
|
||||
ALGORAND_HOST.algodToken =
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
||||
ALGORAND_HOST.algodPort = "4001";
|
||||
}
|
||||
const client = new Algodv2(
|
||||
ALGORAND_HOST.algodToken,
|
||||
ALGORAND_HOST.algodServer,
|
||||
ALGORAND_HOST.algodPort
|
||||
);
|
||||
return client;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import {
|
||||
CONTRACTS,
|
||||
ChainId,
|
||||
ChainName,
|
||||
assertChain,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import { AptosAccount, AptosClient, BCS, TxnBuilderTypes } from "aptos";
|
||||
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";
|
||||
|
@ -11,6 +13,10 @@ 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,
|
||||
tryNativeToUint8Array,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils";
|
||||
|
||||
export async function execute_aptos(
|
||||
payload: Payload,
|
||||
|
@ -236,6 +242,44 @@ export async function execute_aptos(
|
|||
}
|
||||
}
|
||||
|
||||
export async function transferAptos(
|
||||
dstChain: ChainName,
|
||||
dstAddress: string,
|
||||
tokenAddress: string,
|
||||
amount: string,
|
||||
network: Network,
|
||||
rpc: string
|
||||
) {
|
||||
const { key } = NETWORKS[network].aptos;
|
||||
if (!key) {
|
||||
throw new Error("No key for aptos");
|
||||
}
|
||||
rpc = rpc ?? NETWORKS[network].aptos.rpc;
|
||||
if (!rpc) {
|
||||
throw new Error("No rpc for aptos");
|
||||
}
|
||||
const { token_bridge } = CONTRACTS[network].aptos;
|
||||
if (!token_bridge) {
|
||||
throw new Error("token bridge contract is undefined");
|
||||
}
|
||||
const account = new AptosAccount(new Uint8Array(Buffer.from(key, "hex")));
|
||||
const client = new AptosClient(rpc);
|
||||
const transferPayload = transferFromAptos(
|
||||
token_bridge,
|
||||
tokenAddress === "native" ? "0x1::aptos_coin::AptosCoin" : tokenAddress,
|
||||
amount,
|
||||
dstChain,
|
||||
tryNativeToUint8Array(dstAddress, dstChain)
|
||||
);
|
||||
const tx = (await generateSignAndSubmitEntryFunction(
|
||||
client,
|
||||
account,
|
||||
transferPayload
|
||||
)) as Types.UserTransaction;
|
||||
await client.waitForTransaction(tx.hash);
|
||||
console.log(`hash: ${tx.hash}`);
|
||||
}
|
||||
|
||||
export function deriveWrappedAssetAddress(
|
||||
token_bridge_address: Uint8Array, // 32 bytes
|
||||
origin_chain: ChainId,
|
||||
|
|
|
@ -129,7 +129,7 @@ export const submit = async (
|
|||
console.log(` Type ${getWrappedCoinType(coinPackageId)}`);
|
||||
|
||||
if (!rpc && network !== "DEVNET") {
|
||||
// Wait for wrapped asset creation to be propogated to other
|
||||
// Wait for wrapped asset creation to be propagated to other
|
||||
// nodes in case this complete registration call is load balanced
|
||||
// to another node.
|
||||
await sleep(5000);
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
import { transferFromSui } from "@certusone/wormhole-sdk/lib/esm/token_bridge/transfer";
|
||||
import {
|
||||
executeTransactionBlock,
|
||||
getProvider,
|
||||
getSigner,
|
||||
setMaxGasBudgetDevnet,
|
||||
} from "./utils";
|
||||
import {
|
||||
CONTRACTS,
|
||||
ChainName,
|
||||
Network,
|
||||
tryNativeToUint8Array,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils";
|
||||
|
||||
export async function transferSui(
|
||||
dstChain: ChainName,
|
||||
dstAddress: string,
|
||||
tokenAddress: string,
|
||||
amount: string,
|
||||
network: Network,
|
||||
rpc: string
|
||||
) {
|
||||
const { core, token_bridge } = CONTRACTS[network]["sui"];
|
||||
if (!core) {
|
||||
throw Error("Core bridge object ID is undefined");
|
||||
}
|
||||
if (!token_bridge) {
|
||||
throw new Error("Token bridge object ID is undefined");
|
||||
}
|
||||
const provider = getProvider(network, rpc);
|
||||
const signer = getSigner(provider, network);
|
||||
const owner = await signer.getAddress();
|
||||
const coinType = tokenAddress === "native" ? "0x2::sui::SUI" : tokenAddress;
|
||||
const coins = (
|
||||
await provider.getCoins({
|
||||
owner,
|
||||
coinType,
|
||||
})
|
||||
).data;
|
||||
const tx = await transferFromSui(
|
||||
provider,
|
||||
core,
|
||||
token_bridge,
|
||||
coins,
|
||||
coinType,
|
||||
BigInt(amount),
|
||||
dstChain,
|
||||
tryNativeToUint8Array(dstAddress, dstChain)
|
||||
);
|
||||
setMaxGasBudgetDevnet(network, tx);
|
||||
const result = await executeTransactionBlock(signer, tx);
|
||||
console.log(JSON.stringify(result));
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
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 { transferTerra } from "../terra";
|
||||
import { transferInjective } from "../injective";
|
||||
import { transferXpla } from "../xpla";
|
||||
import { transferSolana } from "../solana";
|
||||
import { transferAlgorand } from "../algorand";
|
||||
import { transferNear } from "../near";
|
||||
import { transferSui } from "../chains/sui/transfer";
|
||||
import { transferAptos } from "../aptos";
|
||||
|
||||
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,
|
||||
demandOption: true,
|
||||
})
|
||||
.option("dst-chain", {
|
||||
describe: "destination chain",
|
||||
choices: CHAIN_NAME_CHOICES,
|
||||
demandOption: true,
|
||||
})
|
||||
.option("dst-addr", {
|
||||
describe: "destination address",
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
})
|
||||
.option("token-addr", {
|
||||
describe: "token address",
|
||||
type: "string",
|
||||
default: "native",
|
||||
defaultDescription: "native token",
|
||||
demandOption: false,
|
||||
})
|
||||
.option("amount", {
|
||||
describe: "token amount",
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
})
|
||||
.option("network", NETWORK_OPTIONS)
|
||||
.option("rpc", {
|
||||
describe: "RPC endpoint",
|
||||
type: "string",
|
||||
demandOption: false,
|
||||
});
|
||||
|
||||
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");
|
||||
}
|
||||
// TODO: support transfers to sei
|
||||
if (dstChain === "sei") {
|
||||
throw new Error("transfer to sei currently unsupported");
|
||||
}
|
||||
if (srcChain === dstChain) {
|
||||
throw new Error("source and destination chains can't be the same");
|
||||
}
|
||||
const amount = argv.amount;
|
||||
if (BigInt(amount) <= 0) {
|
||||
throw new Error("amount must be greater than 0");
|
||||
}
|
||||
const tokenAddr = argv["token-addr"];
|
||||
if (tokenAddr === "native" && isCosmWasmChain(srcChain)) {
|
||||
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;
|
||||
if (!rpc) {
|
||||
throw new Error(`No ${network} rpc defined for ${srcChain}`);
|
||||
}
|
||||
if (isEVMChain(srcChain)) {
|
||||
await transferEVM(
|
||||
srcChain,
|
||||
dstChain,
|
||||
dstAddr,
|
||||
tokenAddr,
|
||||
amount,
|
||||
network,
|
||||
rpc
|
||||
);
|
||||
} else if (isTerraChain(srcChain)) {
|
||||
await transferTerra(
|
||||
srcChain,
|
||||
dstChain,
|
||||
dstAddr,
|
||||
tokenAddr,
|
||||
amount,
|
||||
network,
|
||||
rpc
|
||||
);
|
||||
} else if (srcChain === "solana" || srcChain === "pythnet") {
|
||||
await transferSolana(
|
||||
srcChain,
|
||||
dstChain,
|
||||
dstAddr,
|
||||
tokenAddr,
|
||||
amount,
|
||||
network,
|
||||
rpc
|
||||
);
|
||||
} else if (srcChain === "algorand") {
|
||||
await transferAlgorand(dstChain, dstAddr, tokenAddr, amount, network, rpc);
|
||||
} else if (srcChain === "near") {
|
||||
await transferNear(dstChain, dstAddr, tokenAddr, amount, network, rpc);
|
||||
} else if (srcChain === "injective") {
|
||||
await transferInjective(dstChain, dstAddr, tokenAddr, amount, network, rpc);
|
||||
} 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") {
|
||||
await transferSui(dstChain, dstAddr, tokenAddr, amount, network, rpc);
|
||||
} 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 you get a type error here, hover over `chain`'s type and it tells you
|
||||
// which cases are not handled
|
||||
impossible(srcChain);
|
||||
}
|
||||
};
|
|
@ -42,3 +42,7 @@ export const CHAIN_ID_OR_NAME_CHOICES = [
|
|||
...Object.keys(CHAINS),
|
||||
...Object.values(CHAINS),
|
||||
] as (ChainName | ChainId)[];
|
||||
|
||||
export const CHAIN_NAME_CHOICES = Object.keys(CHAINS).filter(
|
||||
(c) => c !== "unset"
|
||||
) as ChainName[];
|
||||
|
|
|
@ -3,16 +3,16 @@ import {
|
|||
BridgeImplementation__factory,
|
||||
Implementation__factory,
|
||||
NFTBridgeImplementation__factory,
|
||||
WormholeRelayer__factory
|
||||
WormholeRelayer__factory,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/ethers-contracts";
|
||||
import {
|
||||
getWormholeRelayerAddress
|
||||
} from "@certusone/wormhole-sdk/lib/esm/relayer"
|
||||
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";
|
||||
|
@ -20,6 +20,13 @@ import { solidityKeccak256 } from "ethers/lib/utils";
|
|||
import { NETWORKS } from "./consts";
|
||||
import { Network } from "./utils";
|
||||
import { Encoding, Payload, encode, impossible, typeWidth } from "./vaa";
|
||||
import {
|
||||
approveEth,
|
||||
getAllowanceEth,
|
||||
transferFromEth,
|
||||
transferFromEthNative,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/token_bridge/transfer";
|
||||
import { tryNativeToUint8Array } from "@certusone/wormhole-sdk/lib/esm/utils";
|
||||
|
||||
const _IMPLEMENTATION_SLOT =
|
||||
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";
|
||||
|
@ -264,6 +271,39 @@ export async function getImplementation(
|
|||
)[0];
|
||||
}
|
||||
|
||||
async function getSigner(chain: EVMChainName, key: string, rpc: string) {
|
||||
let provider: ethers.providers.JsonRpcProvider;
|
||||
let signer: ethers.Wallet;
|
||||
if (chain === "celo") {
|
||||
provider = new celo.CeloProvider(rpc);
|
||||
await provider.ready;
|
||||
signer = new celo.CeloWallet(key, provider);
|
||||
} else {
|
||||
provider = new ethers.providers.JsonRpcProvider(rpc);
|
||||
signer = new ethers.Wallet(key, provider);
|
||||
}
|
||||
// Here we apply a set of chain-specific overrides.
|
||||
// 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") {
|
||||
overrides = await getKaruraGasParams(rpc);
|
||||
} 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") {
|
||||
overrides = { gasPrice: (await signer.getGasPrice()).toString() };
|
||||
}
|
||||
return {
|
||||
signer,
|
||||
provider,
|
||||
overrides,
|
||||
};
|
||||
}
|
||||
|
||||
export async function execute_evm(
|
||||
payload: Payload,
|
||||
vaa: Buffer,
|
||||
|
@ -284,32 +324,7 @@ export async function execute_evm(
|
|||
|
||||
const key: string = n.key;
|
||||
const contracts: Contracts = CONTRACTS[network][chain];
|
||||
let provider: ethers.providers.JsonRpcProvider;
|
||||
let signer: ethers.Wallet;
|
||||
if (chain === "celo") {
|
||||
provider = new celo.CeloProvider(rpc);
|
||||
await provider.ready;
|
||||
signer = new celo.CeloWallet(key, provider);
|
||||
} else {
|
||||
provider = new ethers.providers.JsonRpcProvider(rpc);
|
||||
signer = new ethers.Wallet(key, provider);
|
||||
}
|
||||
|
||||
// Here we apply a set of chain-specific overrides.
|
||||
// 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") {
|
||||
overrides = await getKaruraGasParams(rpc);
|
||||
} 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") {
|
||||
overrides = { gasPrice: (await signer.getGasPrice()).toString() };
|
||||
}
|
||||
const { signer, overrides } = await getSigner(chain, key, rpc);
|
||||
|
||||
switch (payload.module) {
|
||||
case "Core": {
|
||||
|
@ -434,38 +449,95 @@ export async function execute_evm(
|
|||
break;
|
||||
}
|
||||
case "WormholeRelayer":
|
||||
contract_address = contract_address
|
||||
contract_address = contract_address
|
||||
? contract_address
|
||||
: getWormholeRelayerAddress(chain, network);
|
||||
if (contract_address === undefined) {
|
||||
throw Error(`Unknown Wormhole Relayer contract on ${network} for ${chain}`)
|
||||
}
|
||||
let rb = WormholeRelayer__factory.connect(contract_address, signer)
|
||||
switch (payload.type) {
|
||||
case "ContractUpgrade":
|
||||
console.log("Upgrading contract")
|
||||
console.log("Hash: " + (await rb.submitContractUpgrade(vaa, overrides)).hash)
|
||||
console.log("Don't forget to verify the new implementation! See ethereum/VERIFY.md for instructions")
|
||||
break
|
||||
case "RegisterChain":
|
||||
console.log("Registering chain")
|
||||
console.log("Hash: " + (await rb.registerWormholeRelayerContract(vaa, overrides)).hash)
|
||||
break
|
||||
case "SetDefaultDeliveryProvider":
|
||||
console.log("Setting default relay provider")
|
||||
console.log("Hash: " + (await rb.setDefaultDeliveryProvider(vaa, overrides)).hash)
|
||||
break
|
||||
default:
|
||||
impossible(payload)
|
||||
break
|
||||
|
||||
}
|
||||
break
|
||||
if (contract_address === undefined) {
|
||||
throw Error(
|
||||
`Unknown Wormhole Relayer contract on ${network} for ${chain}`
|
||||
);
|
||||
}
|
||||
let rb = WormholeRelayer__factory.connect(contract_address, signer);
|
||||
switch (payload.type) {
|
||||
case "ContractUpgrade":
|
||||
console.log("Upgrading contract");
|
||||
console.log(
|
||||
"Hash: " + (await rb.submitContractUpgrade(vaa, overrides)).hash
|
||||
);
|
||||
console.log(
|
||||
"Don't forget to verify the new implementation! See ethereum/VERIFY.md for instructions"
|
||||
);
|
||||
break;
|
||||
case "RegisterChain":
|
||||
console.log("Registering chain");
|
||||
console.log(
|
||||
"Hash: " +
|
||||
(await rb.registerWormholeRelayerContract(vaa, overrides)).hash
|
||||
);
|
||||
break;
|
||||
case "SetDefaultDeliveryProvider":
|
||||
console.log("Setting default relay provider");
|
||||
console.log(
|
||||
"Hash: " +
|
||||
(await rb.setDefaultDeliveryProvider(vaa, overrides)).hash
|
||||
);
|
||||
break;
|
||||
default:
|
||||
impossible(payload);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
impossible(payload);
|
||||
}
|
||||
}
|
||||
|
||||
export async function transferEVM(
|
||||
srcChain: EVMChainName,
|
||||
dstChain: ChainName,
|
||||
dstAddress: string,
|
||||
tokenAddress: string,
|
||||
amount: string,
|
||||
network: Network,
|
||||
rpc: string
|
||||
) {
|
||||
const n = NETWORKS[network][srcChain];
|
||||
if (!n.key) {
|
||||
throw Error(`No ${network} key defined for ${srcChain} (see networks.ts)`);
|
||||
}
|
||||
const { token_bridge } = CONTRACTS[network][srcChain];
|
||||
if (!token_bridge) {
|
||||
throw Error(`Unknown token bridge contract on ${network} for ${srcChain}`);
|
||||
}
|
||||
const { signer, overrides } = await getSigner(srcChain, n.key, rpc);
|
||||
let tx;
|
||||
if (tokenAddress === "native") {
|
||||
tx = await transferFromEthNative(
|
||||
token_bridge,
|
||||
signer,
|
||||
amount,
|
||||
toChainId(dstChain),
|
||||
tryNativeToUint8Array(dstAddress, dstChain)
|
||||
);
|
||||
} else {
|
||||
const allowance = await getAllowanceEth(token_bridge, tokenAddress, signer);
|
||||
if (allowance.lt(amount)) {
|
||||
await approveEth(token_bridge, tokenAddress, signer, amount, overrides);
|
||||
}
|
||||
tx = await transferFromEth(
|
||||
token_bridge,
|
||||
signer,
|
||||
tokenAddress,
|
||||
amount,
|
||||
dstChain,
|
||||
tryNativeToUint8Array(dstAddress, dstChain),
|
||||
undefined,
|
||||
overrides
|
||||
);
|
||||
}
|
||||
console.log(`Hash: ${tx.transactionHash}`);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Hijack a core contract. This function is useful when working with a mainnet
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import {
|
||||
CHAINS,
|
||||
CONTRACTS,
|
||||
ChainName,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import {
|
||||
getNetworkInfo,
|
||||
|
@ -11,6 +12,7 @@ import {
|
|||
ChainRestAuthApi,
|
||||
createTransaction,
|
||||
MsgExecuteContractCompat,
|
||||
Msgs,
|
||||
PrivateKey,
|
||||
TxGrpcApi,
|
||||
} from "@injectivelabs/sdk-ts";
|
||||
|
@ -19,6 +21,8 @@ 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";
|
||||
|
||||
export async function execute_injective(
|
||||
payload: Payload,
|
||||
|
@ -157,11 +161,61 @@ export async function execute_injective(
|
|||
});
|
||||
console.log("transaction:", transaction);
|
||||
|
||||
await signAndSendTx(walletPK, network, transaction);
|
||||
}
|
||||
|
||||
export async function transferInjective(
|
||||
dstChain: ChainName,
|
||||
dstAddress: string,
|
||||
tokenAddress: string,
|
||||
amount: string,
|
||||
network: Network,
|
||||
rpc: string
|
||||
) {
|
||||
if (network === "DEVNET") {
|
||||
throw new Error("Injective is not supported in DEVNET");
|
||||
}
|
||||
const chain = "injective";
|
||||
const { key } = NETWORKS[network][chain];
|
||||
if (!key) {
|
||||
throw Error(`No ${network} key defined for Injective`);
|
||||
}
|
||||
const { token_bridge } = CONTRACTS[network][chain];
|
||||
if (token_bridge == undefined) {
|
||||
throw Error(`Unknown token bridge contract on ${network} for ${chain}`);
|
||||
}
|
||||
|
||||
const walletPK = PrivateKey.fromMnemonic(key);
|
||||
const walletInjAddr = walletPK.toBech32();
|
||||
|
||||
const msgs = await transferFromInjective(
|
||||
walletInjAddr,
|
||||
token_bridge,
|
||||
tokenAddress,
|
||||
amount,
|
||||
dstChain,
|
||||
tryNativeToUint8Array(dstAddress, dstChain)
|
||||
);
|
||||
|
||||
await signAndSendTx(walletPK, network, msgs);
|
||||
}
|
||||
|
||||
async function signAndSendTx(
|
||||
walletPK: PrivateKey,
|
||||
network: string,
|
||||
msgs: Msgs | Msgs[]
|
||||
) {
|
||||
const endPoint =
|
||||
network === "MAINNET"
|
||||
? InjectiveNetwork.MainnetK8s
|
||||
: InjectiveNetwork.TestnetK8s;
|
||||
const networkInfo = getNetworkInfo(endPoint);
|
||||
const walletPublicKey = walletPK.toPublicKey().toBase64();
|
||||
const accountDetails = await new ChainRestAuthApi(
|
||||
networkInfo.rest
|
||||
).fetchAccount(walletInjAddr);
|
||||
).fetchAccount(walletPK.toBech32());
|
||||
const { signBytes, txRaw } = createTransaction({
|
||||
message: transaction,
|
||||
message: msgs,
|
||||
memo: "",
|
||||
fee: getStdFee((parseInt(DEFAULT_STD_FEE.gas, 10) * 2.5).toString()),
|
||||
pubKey: walletPublicKey,
|
||||
|
|
|
@ -15,6 +15,7 @@ import * as parse from "./cmds/parse";
|
|||
import * as recover from "./cmds/recover";
|
||||
import * as submit from "./cmds/submit";
|
||||
import * as sui from "./cmds/sui";
|
||||
import * as transfer from "./cmds/transfer";
|
||||
import * as verifyVaa from "./cmds/verifyVaa";
|
||||
|
||||
yargs(hideBin(process.argv))
|
||||
|
@ -30,6 +31,7 @@ yargs(hideBin(process.argv))
|
|||
.command(recover)
|
||||
.command(submit)
|
||||
.command(sui)
|
||||
.command(transfer)
|
||||
.command(verifyVaa)
|
||||
.strict()
|
||||
.demandCommand().argv;
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
import { CONTRACTS } from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
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";
|
||||
|
||||
export const execute_near = async (
|
||||
payload: Payload,
|
||||
|
@ -142,3 +150,62 @@ export const execute_near = async (
|
|||
const txHash = result1.transaction.hash + ":" + result2.transaction.hash;
|
||||
console.log("Hash: " + txHash);
|
||||
};
|
||||
|
||||
export async function transferNear(
|
||||
dstChain: ChainName,
|
||||
dstAddress: string,
|
||||
tokenAddress: string,
|
||||
amount: string,
|
||||
network: Network,
|
||||
rpc: string
|
||||
) {
|
||||
const { key, networkId, deployerAccount } = NETWORKS[network].near;
|
||||
if (!key) {
|
||||
throw Error(`No ${network} key defined for NEAR`);
|
||||
}
|
||||
const { core, token_bridge } = CONTRACTS[network].near;
|
||||
if (core === undefined) {
|
||||
throw Error(`Unknown core contract on ${network} for NEAR`);
|
||||
}
|
||||
if (token_bridge === undefined) {
|
||||
throw Error(`Unknown token bridge contract on ${network} for NEAR`);
|
||||
}
|
||||
const keyStore = new InMemoryKeyStore();
|
||||
keyStore.setKey(networkId, deployerAccount, KeyPair.fromString(key));
|
||||
const near = await connect({
|
||||
keyStore,
|
||||
networkId,
|
||||
nodeUrl: rpc,
|
||||
headers: {},
|
||||
});
|
||||
const nearAccount = new Account(near.connection, deployerAccount);
|
||||
if (tokenAddress === "native") {
|
||||
const msg = await transferNearFromNear(
|
||||
near.connection.provider,
|
||||
core,
|
||||
token_bridge,
|
||||
BigInt(amount),
|
||||
tryNativeToUint8Array(dstAddress, dstChain),
|
||||
dstChain,
|
||||
BigInt(0)
|
||||
);
|
||||
const result = await nearAccount.functionCall(msg);
|
||||
console.log(result.transaction.hash);
|
||||
} else {
|
||||
const msgs = await transferTokenFromNear(
|
||||
near.connection.provider,
|
||||
nearAccount.accountId,
|
||||
core,
|
||||
token_bridge,
|
||||
tokenAddress,
|
||||
BigInt(amount),
|
||||
tryNativeToUint8Array(dstAddress, dstChain),
|
||||
dstChain,
|
||||
BigInt(0)
|
||||
);
|
||||
for (const msg of msgs) {
|
||||
const result = await nearAccount.functionCall(msg);
|
||||
console.log(result.transaction.hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,15 +19,25 @@ import {
|
|||
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";
|
||||
import { Payload, VAA, impossible } from "./vaa";
|
||||
import { ChainName, hexToUint8Array } from "@certusone/wormhole-sdk";
|
||||
import { getEmitterAddress } from "./emitter";
|
||||
import { Network } from "./utils";
|
||||
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";
|
||||
|
||||
export async function execute_solana(
|
||||
v: VAA<Payload>,
|
||||
|
@ -217,6 +227,84 @@ export async function execute_solana(
|
|||
console.log("SIGNATURE", signature);
|
||||
}
|
||||
|
||||
export async function transferSolana(
|
||||
srcChain: SolanaChainName,
|
||||
dstChain: ChainName,
|
||||
dstAddress: string,
|
||||
tokenAddress: string,
|
||||
amount: string,
|
||||
network: Network,
|
||||
rpc: string
|
||||
) {
|
||||
const { key } = NETWORKS[network][srcChain];
|
||||
if (!key) {
|
||||
throw Error(`No ${network} key defined for ${srcChain}`);
|
||||
}
|
||||
|
||||
const connection = setupConnection(rpc);
|
||||
const keypair = web3s.Keypair.fromSecretKey(base58.decode(key));
|
||||
|
||||
const { core, token_bridge } = CONTRACTS[network][srcChain];
|
||||
if (!core) {
|
||||
throw new Error(
|
||||
`Core bridge address not defined for ${srcChain} ${network}`
|
||||
);
|
||||
}
|
||||
if (!token_bridge) {
|
||||
throw new Error(
|
||||
`Token bridge address not defined for ${srcChain} ${network}`
|
||||
);
|
||||
}
|
||||
|
||||
const bridgeId = new web3s.PublicKey(core);
|
||||
const tokenBridgeId = new web3s.PublicKey(token_bridge);
|
||||
const payerAddress = keypair.publicKey.toString();
|
||||
|
||||
let transaction;
|
||||
if (tokenAddress === "native") {
|
||||
transaction = await transferNativeSol(
|
||||
connection,
|
||||
bridgeId,
|
||||
tokenBridgeId,
|
||||
payerAddress,
|
||||
BigInt(amount),
|
||||
tryNativeToUint8Array(dstAddress, dstChain),
|
||||
dstChain
|
||||
);
|
||||
} else {
|
||||
// find the associated token account
|
||||
const fromAddress = (
|
||||
await getAssociatedTokenAddress(
|
||||
new PublicKey(tokenAddress),
|
||||
keypair.publicKey
|
||||
)
|
||||
).toString();
|
||||
transaction = await transferFromSolana(
|
||||
connection,
|
||||
bridgeId,
|
||||
tokenBridgeId,
|
||||
payerAddress,
|
||||
fromAddress,
|
||||
tokenAddress, // mintAddress
|
||||
BigInt(amount),
|
||||
tryNativeToUint8Array(dstAddress, dstChain),
|
||||
dstChain
|
||||
);
|
||||
}
|
||||
|
||||
// sign, send, and confirm transaction
|
||||
transaction.partialSign(keypair);
|
||||
const signature = await connection.sendRawTransaction(
|
||||
transaction.serialize()
|
||||
);
|
||||
await connection.confirmTransaction(signature);
|
||||
const info = await connection.getTransaction(signature);
|
||||
if (!info) {
|
||||
throw new Error("An error occurred while fetching the transaction info");
|
||||
}
|
||||
console.log("SIGNATURE", signature);
|
||||
}
|
||||
|
||||
const setupConnection = (rpc: string): web3s.Connection =>
|
||||
new web3s.Connection(rpc, "confirmed");
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import {
|
||||
CHAINS,
|
||||
CONTRACTS,
|
||||
ChainName,
|
||||
TerraChainName,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import {
|
||||
|
@ -9,12 +10,15 @@ import {
|
|||
LCDClient,
|
||||
MnemonicKey,
|
||||
MsgExecuteContract,
|
||||
Wallet,
|
||||
} from "@terra-money/terra.js";
|
||||
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";
|
||||
|
||||
export async function execute_terra(
|
||||
payload: Payload,
|
||||
|
@ -152,6 +156,55 @@ export async function execute_terra(
|
|||
{ uluna: 1000 }
|
||||
);
|
||||
|
||||
await signAndSendTx(terra, wallet, [transaction]);
|
||||
}
|
||||
|
||||
export async function transferTerra(
|
||||
srcChain: TerraChainName,
|
||||
dstChain: ChainName,
|
||||
dstAddress: string,
|
||||
tokenAddress: string,
|
||||
amount: string,
|
||||
network: Network,
|
||||
rpc: string
|
||||
) {
|
||||
const n = NETWORKS[network][srcChain];
|
||||
if (!n.key) {
|
||||
throw Error(`No ${network} key defined for ${srcChain} (see networks.ts)`);
|
||||
}
|
||||
const { token_bridge } = CONTRACTS[network][srcChain];
|
||||
if (!token_bridge) {
|
||||
throw Error(`Unknown token bridge contract on ${network} for ${srcChain}`);
|
||||
}
|
||||
|
||||
const terra = new LCDClient({
|
||||
URL: rpc,
|
||||
chainID: n.chain_id,
|
||||
isClassic: srcChain === "terra",
|
||||
});
|
||||
|
||||
const wallet = terra.wallet(
|
||||
new MnemonicKey({
|
||||
mnemonic: n.key,
|
||||
})
|
||||
);
|
||||
|
||||
const msgs = await transferFromTerra(
|
||||
wallet.key.accAddress,
|
||||
token_bridge,
|
||||
tokenAddress,
|
||||
amount,
|
||||
dstChain,
|
||||
tryNativeToUint8Array(dstAddress, dstChain)
|
||||
);
|
||||
await signAndSendTx(terra, wallet, msgs);
|
||||
}
|
||||
|
||||
async function signAndSendTx(
|
||||
terra: LCDClient,
|
||||
wallet: Wallet,
|
||||
msgs: MsgExecuteContract[]
|
||||
) {
|
||||
const feeDenoms = ["uluna"];
|
||||
const gasPrices = await axios
|
||||
.get("https://terra-classic-fcd.publicnode.com/v1/txs/gas_prices")
|
||||
|
@ -164,7 +217,7 @@ export async function execute_terra(
|
|||
},
|
||||
],
|
||||
{
|
||||
msgs: [transaction],
|
||||
msgs,
|
||||
memo: "",
|
||||
feeDenoms,
|
||||
gasPrices,
|
||||
|
@ -173,7 +226,7 @@ export async function execute_terra(
|
|||
|
||||
return wallet
|
||||
.createAndSignTx({
|
||||
msgs: [transaction],
|
||||
msgs,
|
||||
memo: "",
|
||||
fee: new Fee(
|
||||
feeEstimate.gas_limit,
|
||||
|
|
|
@ -1,15 +1,21 @@
|
|||
import { CONTRACTS } from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import {
|
||||
CONTRACTS,
|
||||
ChainName,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
|
||||
import {
|
||||
Coin,
|
||||
Fee,
|
||||
LCDClient,
|
||||
MnemonicKey,
|
||||
MsgExecuteContract,
|
||||
Wallet,
|
||||
} 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";
|
||||
|
||||
export async function execute_xpla(
|
||||
payload: Payload,
|
||||
|
@ -146,6 +152,50 @@ export async function execute_xpla(
|
|||
{ axpla: "1700000000000000000" }
|
||||
);
|
||||
|
||||
await signAndSendTx(client, wallet, [transaction]);
|
||||
}
|
||||
|
||||
export async function transferXpla(
|
||||
dstChain: ChainName,
|
||||
dstAddress: string,
|
||||
tokenAddress: string,
|
||||
amount: string,
|
||||
network: Network,
|
||||
rpc: string
|
||||
) {
|
||||
const { key, chain_id } = NETWORKS[network].xpla;
|
||||
if (!key) {
|
||||
throw Error(`No ${network} key defined for XPLA`);
|
||||
}
|
||||
const { token_bridge } = CONTRACTS[network].xpla;
|
||||
if (token_bridge == undefined) {
|
||||
throw Error(`Unknown token bridge contract on ${network} for XPLA`);
|
||||
}
|
||||
const client = new LCDClient({
|
||||
URL: rpc,
|
||||
chainID: chain_id,
|
||||
});
|
||||
const wallet = client.wallet(
|
||||
new MnemonicKey({
|
||||
mnemonic: key,
|
||||
})
|
||||
);
|
||||
const msgs = transferFromXpla(
|
||||
wallet.key.accAddress,
|
||||
token_bridge,
|
||||
tokenAddress,
|
||||
amount,
|
||||
dstChain,
|
||||
tryNativeToUint8Array(dstAddress, dstChain)
|
||||
);
|
||||
await signAndSendTx(client, wallet, msgs);
|
||||
}
|
||||
|
||||
async function signAndSendTx(
|
||||
client: LCDClient,
|
||||
wallet: Wallet,
|
||||
msgs: MsgExecuteContract[]
|
||||
) {
|
||||
const feeDenoms = ["axpla"];
|
||||
// const gasPrices = await axios
|
||||
// .get("https://dimension-lcd.xpla.dev/v1/txs/gas_prices")
|
||||
|
@ -158,7 +208,7 @@ export async function execute_xpla(
|
|||
},
|
||||
],
|
||||
{
|
||||
msgs: [transaction],
|
||||
msgs,
|
||||
memo: "",
|
||||
feeDenoms,
|
||||
// gasPrices,
|
||||
|
@ -167,7 +217,7 @@ export async function execute_xpla(
|
|||
|
||||
wallet
|
||||
.createAndSignTx({
|
||||
msgs: [transaction],
|
||||
msgs,
|
||||
memo: "",
|
||||
fee: new Fee(
|
||||
feeEstimate.gas_limit,
|
||||
|
|
|
@ -145,7 +145,7 @@ export async function transferFromEthNative(
|
|||
tokenBridgeAddress: string,
|
||||
signer: ethers.Signer,
|
||||
amount: ethers.BigNumberish,
|
||||
recipientChain: ChainId | ChainId,
|
||||
recipientChain: ChainId | ChainName,
|
||||
recipientAddress: Uint8Array,
|
||||
relayerFee: ethers.BigNumberish = 0,
|
||||
overrides: PayableOverrides & { from?: string | Promise<string> } = {},
|
||||
|
|
Loading…
Reference in New Issue