sdk/js: Terra2 integration tests
This commit is contained in:
parent
52e66964b0
commit
3028b81d63
|
@ -36,7 +36,7 @@ const interateToStandardTransactionCount = async () => {
|
|||
return Promise.resolve();
|
||||
};
|
||||
|
||||
module.exports = async function(callback) {
|
||||
module.exports = async function (callback) {
|
||||
try {
|
||||
const accounts = await web3.eth.getAccounts();
|
||||
|
||||
|
@ -61,6 +61,10 @@ module.exports = async function(callback) {
|
|||
from: accounts[0],
|
||||
gas: 1000000,
|
||||
});
|
||||
await token.methods.mint(accounts[2], "1000000000000000000000").send({
|
||||
from: accounts[0],
|
||||
gas: 1000000,
|
||||
});
|
||||
|
||||
const nftAddress = (
|
||||
await ERC721.new(
|
||||
|
|
|
@ -7,6 +7,8 @@ const ci = !!process.env.CI;
|
|||
export const ETH_NODE_URL = ci ? "ws://eth-devnet:8545" : "ws://localhost:8545";
|
||||
export const ETH_PRIVATE_KEY =
|
||||
"0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d";
|
||||
export const ETH_PRIVATE_KEY2 =
|
||||
"0x6370fd033278c143179d81c5526140625662b8daa446c22ee2d73db3707e620c"; // account 2
|
||||
export const ETH_CORE_BRIDGE_ADDRESS =
|
||||
"0xC89Ce4735882C9F0f0FE26686c53074E09B0D550";
|
||||
export const ETH_TOKEN_BRIDGE_ADDRESS =
|
||||
|
@ -31,12 +33,19 @@ export const TERRA_CHAIN_ID = "localterra";
|
|||
export const TERRA_GAS_PRICES_URL = ci
|
||||
? "http://terra-fcd:3060/v1/txs/gas_prices"
|
||||
: "http://localhost:3060/v1/txs/gas_prices";
|
||||
export const TERRA2_GAS_PRICES_URL = ci
|
||||
? "http://terra2-fcd:3060/v1/txs/gas_prices"
|
||||
: "http://localhost:3061/v1/txs/gas_prices";
|
||||
export const TERRA_CORE_BRIDGE_ADDRESS =
|
||||
"terra18vd8fpwxzck93qlwghaj6arh4p7c5n896xzem5";
|
||||
export const TERRA_TOKEN_BRIDGE_ADDRESS =
|
||||
"terra10pyejy66429refv3g35g2t7am0was7ya7kz2a4";
|
||||
export const TERRA2_TOKEN_BRIDGE_ADDRESS =
|
||||
"terra1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrquka9l6";
|
||||
export const TERRA_PRIVATE_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";
|
||||
export const TERRA2_PRIVATE_KEY =
|
||||
"symbol force gallery make bulk round subway violin worry mixture penalty kingdom boring survey tool fringe patrol sausage hard admit remember broken alien absorb"; // test3
|
||||
export const TEST_ERC20 = "0x2D8BE6BF0baA74e0A907016679CaE9190e80dD0A";
|
||||
export const TEST_SOLANA_TOKEN = "2WDq7wSs9zYrpx2kbHDA4RUTRch2CCTP6ZWaH4GNfnQQ";
|
||||
export const WORMHOLE_RPC_HOSTS = ci
|
||||
|
|
|
@ -105,9 +105,9 @@ export async function transferFromEthToSolana(): Promise<string> {
|
|||
}
|
||||
|
||||
export async function waitForTerraExecution(
|
||||
transaction: string
|
||||
transaction: string,
|
||||
lcd: LCDClient
|
||||
): Promise<TxInfo | undefined> {
|
||||
const lcd = new LCDClient(TERRA_HOST);
|
||||
let done: boolean = false;
|
||||
let info;
|
||||
while (!done) {
|
||||
|
|
|
@ -1180,7 +1180,7 @@ describe("Integration Tests", () => {
|
|||
fee: feeEstimate,
|
||||
});
|
||||
const result = await lcd.tx.broadcast(executeTx);
|
||||
const info = await waitForTerraExecution(result.txhash);
|
||||
const info = await waitForTerraExecution(result.txhash, lcd);
|
||||
if (!info) {
|
||||
throw new Error("info not found");
|
||||
}
|
||||
|
@ -1316,7 +1316,7 @@ describe("Integration Tests", () => {
|
|||
fee: feeEstimate,
|
||||
});
|
||||
const result = await lcd.tx.broadcast(executeTx);
|
||||
const info = await waitForTerraExecution(result.txhash);
|
||||
const info = await waitForTerraExecution(result.txhash, lcd);
|
||||
if (!info) {
|
||||
throw new Error("info not found");
|
||||
}
|
||||
|
@ -1559,7 +1559,7 @@ describe("Integration Tests", () => {
|
|||
fee: feeEstimate,
|
||||
});
|
||||
let result = await lcd.tx.broadcast(executeTx);
|
||||
let info = await waitForTerraExecution(result.txhash);
|
||||
let info = await waitForTerraExecution(result.txhash, lcd);
|
||||
if (!info) {
|
||||
throw new Error("info not found");
|
||||
}
|
||||
|
@ -1678,7 +1678,7 @@ describe("Integration Tests", () => {
|
|||
fee: feeEstimate,
|
||||
});
|
||||
result = await lcd.tx.broadcast(executeTx);
|
||||
info = await waitForTerraExecution(result.txhash);
|
||||
info = await waitForTerraExecution(result.txhash, lcd);
|
||||
if (!info) {
|
||||
throw new Error("info not found");
|
||||
}
|
||||
|
@ -2390,7 +2390,10 @@ describe("Integration Tests", () => {
|
|||
fee: feeEstimate,
|
||||
});
|
||||
const attestResult = await lcd.tx.broadcast(executeAttest);
|
||||
const attestInfo = await waitForTerraExecution(attestResult.txhash);
|
||||
const attestInfo = await waitForTerraExecution(
|
||||
attestResult.txhash,
|
||||
lcd
|
||||
);
|
||||
if (!attestInfo) {
|
||||
throw new Error("info not found");
|
||||
}
|
||||
|
@ -2471,7 +2474,7 @@ describe("Integration Tests", () => {
|
|||
fee: feeEstimate,
|
||||
});
|
||||
const txResult = await lcd.tx.broadcast(executeTx);
|
||||
const txInfo = await waitForTerraExecution(txResult.txhash);
|
||||
const txInfo = await waitForTerraExecution(txResult.txhash, lcd);
|
||||
if (!txInfo) {
|
||||
throw new Error("info not found");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
import { beforeAll, afterAll, expect, test } from "@jest/globals";
|
||||
import {
|
||||
isTxError,
|
||||
LCDClient,
|
||||
MnemonicKey,
|
||||
Msg,
|
||||
Wallet,
|
||||
} from "@terra-money/terra.js";
|
||||
import { ethers } from "ethers";
|
||||
import { parseUnits } from "ethers/lib/utils";
|
||||
import {
|
||||
createWrappedOnEth,
|
||||
createWrappedOnTerra,
|
||||
getEmitterAddressEth,
|
||||
getEmitterAddressTerra,
|
||||
getIsTransferCompletedTerra,
|
||||
parseSequenceFromLogEth,
|
||||
parseSequenceFromLogTerra,
|
||||
redeemOnEth,
|
||||
redeemOnTerra,
|
||||
updateWrappedOnEth,
|
||||
} from "../..";
|
||||
import { tryNativeToUint8Array } from "../../utils";
|
||||
import { CHAIN_ID_ETH, CHAIN_ID_TERRA2 } from "../../utils/consts";
|
||||
import { attestFromEth, attestFromTerra } from "../attest";
|
||||
import { approveEth, transferFromEth, transferFromTerra } from "../transfer";
|
||||
import {
|
||||
ETH_CORE_BRIDGE_ADDRESS,
|
||||
ETH_NODE_URL,
|
||||
ETH_PRIVATE_KEY2,
|
||||
ETH_TOKEN_BRIDGE_ADDRESS,
|
||||
TERRA2_GAS_PRICES_URL,
|
||||
TERRA2_TOKEN_BRIDGE_ADDRESS,
|
||||
TERRA2_PRIVATE_KEY,
|
||||
TEST_ERC20,
|
||||
} from "./consts";
|
||||
import { getSignedVAABySequence, waitForTerraExecution } from "./helpers";
|
||||
|
||||
const lcd = new LCDClient({
|
||||
URL: !!process.env.CI ? "http://terra2-terrad:1317" : "http://localhost:1318",
|
||||
chainID: "localterra",
|
||||
});
|
||||
const terraWallet = lcd.wallet(
|
||||
new MnemonicKey({ mnemonic: TERRA2_PRIVATE_KEY })
|
||||
);
|
||||
const terraWalletAddress = terraWallet.key.accAddress;
|
||||
|
||||
const provider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
|
||||
const signer = new ethers.Wallet(ETH_PRIVATE_KEY2, provider);
|
||||
const ethEmitterAddress = getEmitterAddressEth(ETH_TOKEN_BRIDGE_ADDRESS);
|
||||
const ethTransferAmount = parseUnits("1", 18);
|
||||
|
||||
let ethWalletAddress: string;
|
||||
let terraEmitterAddress: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
ethWalletAddress = await signer.getAddress();
|
||||
terraEmitterAddress = await getEmitterAddressTerra(
|
||||
TERRA2_TOKEN_BRIDGE_ADDRESS
|
||||
);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
provider.destroy();
|
||||
});
|
||||
|
||||
const terraBroadcastAndWaitForExecution = async (
|
||||
msgs: Msg[],
|
||||
wallet: Wallet
|
||||
) => {
|
||||
const tx = await wallet.createAndSignTx({
|
||||
msgs,
|
||||
});
|
||||
const txResult = await lcd.tx.broadcast(tx);
|
||||
if (isTxError(txResult)) {
|
||||
throw new Error("tx error");
|
||||
}
|
||||
const txInfo = await waitForTerraExecution(txResult.txhash, lcd);
|
||||
if (!txInfo) {
|
||||
throw new Error("tx info not found");
|
||||
}
|
||||
return txInfo;
|
||||
};
|
||||
|
||||
const terraBroadcastTxAndGetSignedVaa = async (msgs: Msg[], wallet: Wallet) => {
|
||||
const txInfo = await terraBroadcastAndWaitForExecution(msgs, wallet);
|
||||
const txSequence = parseSequenceFromLogTerra(txInfo);
|
||||
if (!txSequence) {
|
||||
throw new Error("tx sequence not found");
|
||||
}
|
||||
return await getSignedVAABySequence(
|
||||
CHAIN_ID_TERRA2,
|
||||
txSequence,
|
||||
terraEmitterAddress
|
||||
);
|
||||
};
|
||||
|
||||
const ethParseLogAndGetSignedVaa = async (receipt: ethers.ContractReceipt) => {
|
||||
const sequence = parseSequenceFromLogEth(receipt, ETH_CORE_BRIDGE_ADDRESS);
|
||||
return await getSignedVAABySequence(
|
||||
CHAIN_ID_ETH,
|
||||
sequence,
|
||||
ethEmitterAddress
|
||||
);
|
||||
};
|
||||
|
||||
test("Attest and transfer token from Terra2 to Ethereum", async () => {
|
||||
// Attest
|
||||
const attestMsg = await attestFromTerra(
|
||||
TERRA2_TOKEN_BRIDGE_ADDRESS,
|
||||
terraWalletAddress,
|
||||
"uluna"
|
||||
);
|
||||
const attestSignedVaa = await terraBroadcastTxAndGetSignedVaa(
|
||||
[attestMsg],
|
||||
terraWallet
|
||||
);
|
||||
try {
|
||||
await createWrappedOnEth(ETH_TOKEN_BRIDGE_ADDRESS, signer, attestSignedVaa);
|
||||
} catch {
|
||||
await updateWrappedOnEth(ETH_TOKEN_BRIDGE_ADDRESS, signer, attestSignedVaa);
|
||||
}
|
||||
// Transfer
|
||||
const transferMsgs = await transferFromTerra(
|
||||
terraWalletAddress,
|
||||
TERRA2_TOKEN_BRIDGE_ADDRESS,
|
||||
"uluna",
|
||||
"1000000",
|
||||
CHAIN_ID_ETH,
|
||||
tryNativeToUint8Array(ethWalletAddress, CHAIN_ID_ETH)
|
||||
);
|
||||
const transferSignedVaa = await terraBroadcastTxAndGetSignedVaa(
|
||||
transferMsgs,
|
||||
terraWallet
|
||||
);
|
||||
await redeemOnEth(ETH_TOKEN_BRIDGE_ADDRESS, signer, transferSignedVaa);
|
||||
});
|
||||
|
||||
test("Attest and transfer token from Ethereum to Terra2", async () => {
|
||||
// Attest
|
||||
const attestReceipt = await attestFromEth(
|
||||
ETH_TOKEN_BRIDGE_ADDRESS,
|
||||
signer,
|
||||
TEST_ERC20
|
||||
);
|
||||
const attestSignedVaa = await ethParseLogAndGetSignedVaa(attestReceipt);
|
||||
const createWrappedMsg = await createWrappedOnTerra(
|
||||
TERRA2_TOKEN_BRIDGE_ADDRESS,
|
||||
terraWalletAddress,
|
||||
attestSignedVaa
|
||||
);
|
||||
await terraBroadcastAndWaitForExecution([createWrappedMsg], terraWallet);
|
||||
// Transfer
|
||||
await approveEth(
|
||||
ETH_TOKEN_BRIDGE_ADDRESS,
|
||||
TEST_ERC20,
|
||||
signer,
|
||||
ethTransferAmount
|
||||
);
|
||||
const transferReceipt = await transferFromEth(
|
||||
ETH_TOKEN_BRIDGE_ADDRESS,
|
||||
signer,
|
||||
TEST_ERC20,
|
||||
ethTransferAmount,
|
||||
CHAIN_ID_TERRA2,
|
||||
tryNativeToUint8Array(terraWalletAddress, CHAIN_ID_TERRA2)
|
||||
);
|
||||
const transferSignedVaa = await ethParseLogAndGetSignedVaa(transferReceipt);
|
||||
const redeemMsg = await redeemOnTerra(
|
||||
TERRA2_TOKEN_BRIDGE_ADDRESS,
|
||||
terraWalletAddress,
|
||||
transferSignedVaa
|
||||
);
|
||||
await terraBroadcastAndWaitForExecution([redeemMsg], terraWallet);
|
||||
expect(
|
||||
await getIsTransferCompletedTerra(
|
||||
TERRA2_TOKEN_BRIDGE_ADDRESS,
|
||||
transferSignedVaa,
|
||||
lcd,
|
||||
TERRA2_GAS_PRICES_URL
|
||||
)
|
||||
).toBe(true);
|
||||
});
|
Loading…
Reference in New Issue