From df81c067c16314cf79d336bb150ebb710c6dc400 Mon Sep 17 00:00:00 2001 From: Shunji Zhan Date: Mon, 8 Jul 2024 17:06:12 +0800 Subject: [PATCH] clean up --- scripts/e2e-prod.ts | 3 +- scripts/scriptUtils.ts | 56 --------------------------- src/__tests__/configs/acala.yml | 2 +- src/__tests__/euphrates.test.ts | 4 +- src/__tests__/homa.test.ts | 6 +-- src/__tests__/relay.test.ts | 36 ++++------------- src/__tests__/testConsts.ts | 1 + src/__tests__/testUtils.ts | 9 ++--- src/__tests__/wormhole.test.ts | 7 ++-- src/__tests__/xcm.test.ts | 8 ++-- src/utils/index.ts | 1 - src/utils/token.ts | 29 -------------- src/utils/utils.ts | 36 +---------------- src/utils/wormhole.ts | 68 +-------------------------------- 14 files changed, 32 insertions(+), 234 deletions(-) delete mode 100644 scripts/scriptUtils.ts delete mode 100644 src/utils/token.ts diff --git a/scripts/e2e-prod.ts b/scripts/e2e-prod.ts index 473be8a..1354ac9 100644 --- a/scripts/e2e-prod.ts +++ b/scripts/e2e-prod.ts @@ -10,6 +10,7 @@ import path from 'path'; import { BSC_TOKEN, ETH_RPC , RELAYER_URL } from '../src/consts'; import { RouterChainId, getTokenBalance } from '../src/utils'; import { transferErc20, transferFromBSC } from './scriptUtils'; +import { transferToken } from '../src/__tests__/testUtils'; dotenv.config({ path: path.join(__dirname, '.env') }); const key = process.env.KEY; @@ -89,7 +90,7 @@ const routeWormhole = async (chainId: RouterChainId) => { console.log(`token balance: ${bal}`); console.log('xcming to router ...'); - const txHash = await transferErc20(token, '0.05', routerAddr, wallet); + const txHash = await transferToken(routerAddr, wallet, token, 0.05); console.log(`router received token: ${txHash}, waiting for routing ...`); const routeRes = await axios.post(RELAYER_URL.ROUTE_WORMHOLE, { ...params }); diff --git a/scripts/scriptUtils.ts b/scripts/scriptUtils.ts deleted file mode 100644 index 8b763ca..0000000 --- a/scripts/scriptUtils.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { CHAIN_ID_BSC, CONTRACTS } from '@certusone/wormhole-sdk'; -import { Contract, Signer, Wallet } from 'ethers'; -import { ERC20__factory } from '@acala-network/asset-router/dist/typechain-types'; -import { formatUnits, parseUnits } from 'ethers/lib/utils'; - -import { - RouterChainId, - bridgeToken, - getSignedVAAFromSequence, - parseAmount, -} from '../src/utils'; - -export const transferErc20 = async ( - tokenAddr: string, - amount: string, - dstAddr: string, - signer: Signer, -): Promise => { - const erc20 = ERC20__factory.connect(tokenAddr, signer); - const parsedAmount = parseUnits(amount, await erc20.decimals()); - - const tx = await erc20.transfer(dstAddr, parsedAmount); - const receipt = await tx.wait(); - - return receipt.transactionHash; -}; - -export const transferFromBSC = async ( - amount: string, - sourceAsset: string, - recipientAddr: string, - dstChainId: RouterChainId, - wallet: Wallet, - isMainnet = false, -): Promise => { - const tokenBridgeAddr = CONTRACTS[isMainnet ? 'MAINNET' : 'TESTNET'].bsc.token_bridge; - const coreBridgeAddr = CONTRACTS[isMainnet ? 'MAINNET' : 'TESTNET'].bsc.core; - const parsedAmount = await parseAmount(sourceAsset, amount, wallet); - const { sequence } = await bridgeToken( - wallet, - tokenBridgeAddr, - coreBridgeAddr, - recipientAddr, - sourceAsset, - dstChainId, - parsedAmount, - ); - console.log('transfer from BSC complete', { sequence }, 'waiting for VAA...'); - - return getSignedVAAFromSequence( - sequence, - CHAIN_ID_BSC, - tokenBridgeAddr, - isMainnet, - ); -}; diff --git a/src/__tests__/configs/acala.yml b/src/__tests__/configs/acala.yml index 5a83ac5..7f44e59 100644 --- a/src/__tests__/configs/acala.yml +++ b/src/__tests__/configs/acala.yml @@ -3,7 +3,7 @@ endpoint: - wss://acala-rpc.dwellir.com mock-signature-host: true # block: ${env.ACALA_BLOCK_NUMBER} -# block: 6510220 +block: 6535566 db: ./db.sqlite runtime-log-level: 5 diff --git a/src/__tests__/euphrates.test.ts b/src/__tests__/euphrates.test.ts index 74d9c4e..662b350 100644 --- a/src/__tests__/euphrates.test.ts +++ b/src/__tests__/euphrates.test.ts @@ -21,7 +21,7 @@ import { expectError, routeEuphrates, shouldRouteEuphrates, - transferToRouter, + transferToken, } from './testUtils'; const provider = new AcalaJsonRpcProvider(ETH_RPC.LOCAL); @@ -177,7 +177,7 @@ describe('/routeEuphrates', () => { const bal0 = await fetchTokenBalances(poolId); console.log('transferring token to router ...'); - await transferToRouter(routerAddr, user, inTokenAddr, stakeAmount); + await transferToken(routerAddr, user, inTokenAddr, stakeAmount); console.log('routing ...'); const routeRes = await routeEuphrates({ diff --git a/src/__tests__/homa.test.ts b/src/__tests__/homa.test.ts index 56ccfe2..b4d7deb 100644 --- a/src/__tests__/homa.test.ts +++ b/src/__tests__/homa.test.ts @@ -22,11 +22,11 @@ import { } from './testConsts'; import { expectError, - mockXcmToRouter, routeHoma, routeHomaAuto, routeStatus, shouldRouteHoma, + transferToken, } from './testUtils'; const provider = new AcalaJsonRpcProvider(ETH_RPC.LOCAL); @@ -214,7 +214,7 @@ describe('/routeHoma', () => { const bal0 = await fetchTokenBalances(); console.log('xcming to router ...'); - await mockXcmToRouter(routerAddr, user, DOT, stakeAmount); + await transferToken(routerAddr, user, DOT, stakeAmount); console.log('routing ...'); const routeRes = await routeHoma({ @@ -293,7 +293,7 @@ describe('/routeHoma', () => { }); console.log('xcming to router ...'); - await mockXcmToRouter(routerAddr, user, DOT, stakeAmount); + await transferToken(routerAddr, user, DOT, stakeAmount); console.log('waiting for auto routing ...'); await waitForRoute; diff --git a/src/__tests__/relay.test.ts b/src/__tests__/relay.test.ts index dc06c0b..6f38705 100644 --- a/src/__tests__/relay.test.ts +++ b/src/__tests__/relay.test.ts @@ -1,18 +1,17 @@ import { AcalaJsonRpcProvider } from '@acala-network/eth-providers'; -import { AxiosError } from 'axios'; import { CHAIN_ID_ACALA } from '@certusone/wormhole-sdk'; import { ERC20__factory } from '@acala-network/asset-router/dist/typechain-types'; import { ROUTER_TOKEN_INFO } from '@acala-network/asset-router/dist/consts'; import { describe, expect, it } from 'vitest'; import { ETH_RPC, RELAY_CONFIG } from '../consts'; +import { PROD_ADDR } from './testConsts'; import { VAA_10_USDC_ETH_TO_ACALA } from './vaa'; -import { relay, shouldRelay } from './testUtils'; +import { expectError, relay, shouldRelay } from './testUtils'; const provider = new AcalaJsonRpcProvider(ETH_RPC.LOCAL); const USDC_ADDR = ROUTER_TOKEN_INFO.usdc.acalaAddr; -const USER_ADDR = '0xBbBBa9Ebe50f9456E106e6ef2992179182889999'; describe('/shouldRelay', () => { it('when should relay', async () => { @@ -55,14 +54,7 @@ describe('/shouldRelay', () => { expect.fail('should throw error but did not'); } catch (err) { - expect((err as AxiosError).response?.data).toMatchInlineSnapshot(` - { - "error": [ - "targetChain is a required field", - ], - "msg": "invalid request params!", - } - `); + expectError(err, ['targetChain is a required field'], 400); } try { @@ -73,14 +65,7 @@ describe('/shouldRelay', () => { expect.fail('should throw error but did not'); } catch (err) { - expect((err as AxiosError).response?.data).toMatchInlineSnapshot(` - { - "error": [ - "originAsset is a required field", - ], - "msg": "invalid request params!", - } - `); + expectError(err, ['originAsset is a required field'], 400); } try { @@ -91,14 +76,7 @@ describe('/shouldRelay', () => { expect.fail('should throw error but did not'); } catch (err) { - expect((err as AxiosError).response?.data).toMatchInlineSnapshot(` - { - "error": [ - "amount is a required field", - ], - "msg": "invalid request params!", - } - `); + expectError(err, ['amount is a required field'], 400); } }); @@ -161,7 +139,7 @@ describe('/shouldRelay', () => { describe('/relay', () => { it('relay USDC to user', async () => { const usdc = ERC20__factory.connect(USDC_ADDR, provider); - const curBalRelayer = (await usdc.balanceOf(USER_ADDR)).toBigInt(); + const curBalRelayer = (await usdc.balanceOf(PROD_ADDR)).toBigInt(); console.log({ curBalRelayer }); const result = await relay({ @@ -170,7 +148,7 @@ describe('/relay', () => { }); expect(result.data?.status).to.eq(1); - const afterBalRelayer = (await usdc.balanceOf(USER_ADDR)).toBigInt(); + const afterBalRelayer = (await usdc.balanceOf(PROD_ADDR)).toBigInt(); console.log({ afterBalRelayer }); expect(afterBalRelayer - curBalRelayer).to.eq(10467941n); // 10.467941 USDC diff --git a/src/__tests__/testConsts.ts b/src/__tests__/testConsts.ts index 712a8c4..b311289 100644 --- a/src/__tests__/testConsts.ts +++ b/src/__tests__/testConsts.ts @@ -7,5 +7,6 @@ export const TEST_KEY = { export const TEST_ADDR_USER = new Wallet(TEST_KEY.USER).address; // 0x0085560b24769dAC4ed057F1B2ae40746AA9aAb6 export const TEST_ADDR_RELAYER = new Wallet(TEST_KEY.RELAYER).address; // 0xe3234f433914d4cfCF846491EC5a7831ab9f0bb3 +export const PROD_ADDR = '0xBbBBa9Ebe50f9456E106e6ef2992179182889999'; export const NOT_SUPPORTED_ADDRESS = ''; diff --git a/src/__tests__/testUtils.ts b/src/__tests__/testUtils.ts index 15bcb00..73b99eb 100644 --- a/src/__tests__/testUtils.ts +++ b/src/__tests__/testUtils.ts @@ -54,8 +54,8 @@ export const sudoTransferToken = async ( } }; -export const transferToRouter = async ( - routerAddr: string, +export const transferToken = async ( + toAddr: string, signer: Wallet, tokenAddr: string, amount: number, @@ -65,7 +65,7 @@ export const transferToRouter = async ( const decimals = await token.decimals(); const routeAmount = parseUnits(String(amount), decimals); - const routerBal = await token.balanceOf(routerAddr); + const routerBal = await token.balanceOf(toAddr); if (routerBal.gt(0)) { expect(routerBal.toBigInt()).to.eq(routeAmount.toBigInt()); } else { @@ -73,10 +73,9 @@ export const transferToRouter = async ( if (fromTokenBal.lt(routeAmount)) { throw new Error(`signer ${signer.address} has no enough token [${tokenAddr}] to transfer! ${fromTokenBal.toBigInt()} < ${routeAmount.toBigInt()}`); } - await (await token.transfer(routerAddr, routeAmount)).wait(); + await (await token.transfer(toAddr, routeAmount)).wait(); } }; -export const mockXcmToRouter = transferToRouter; export const expectError = (err: any, msg: any, code: number) => { if (axios.isAxiosError(err)) { diff --git a/src/__tests__/wormhole.test.ts b/src/__tests__/wormhole.test.ts index e83ceba..61ff491 100644 --- a/src/__tests__/wormhole.test.ts +++ b/src/__tests__/wormhole.test.ts @@ -6,6 +6,7 @@ import { describe, expect, it } from 'vitest'; import { ETH_RPC, PARA_ID } from '../consts'; import { + PROD_ADDR, TEST_ADDR_RELAYER, TEST_ADDR_USER, } from './testConsts'; @@ -15,6 +16,7 @@ import { shouldRouteWormhole, sudoTransferToken, } from './testUtils'; +import { parseUnits } from 'ethers/lib/utils'; const USDC_ADDR = ROUTER_TOKEN_INFO.usdc.acalaAddr; const USDC_ORIGIN_ADDR = ROUTER_TOKEN_INFO.usdc.originAddr; @@ -138,8 +140,7 @@ describe('/routeWormhole', () => { expect(routerAddr).toBeDefined(); console.log('xcming to router ...'); - await sudoTransferToken('0xBbBBa9Ebe50f9456E106e6ef2992179182889999', routerAddr, provider, USDC_ADDR, 0.123); - // await transferToRouter(routerAddr, relayer, USDC_ADDR, 0.123); + await sudoTransferToken(PROD_ADDR, routerAddr, provider, USDC_ADDR, 0.123); const curBalRelayer = (await usdc.balanceOf(TEST_ADDR_RELAYER)).toBigInt(); console.log({ curBalRelayer }); @@ -157,7 +158,7 @@ describe('/routeWormhole', () => { const afterBalRelayer = (await usdc.balanceOf(TEST_ADDR_RELAYER)).toBigInt(); console.log({ afterBalRelayer }); - expect(afterBalRelayer - curBalRelayer).to.eq(40000n); + expect(afterBalRelayer - curBalRelayer).to.eq(parseUnits('0.04', 6).toBigInt()); // USDC has 6 decimals }); // describe.skip('when should not route', () => {}) diff --git a/src/__tests__/xcm.test.ts b/src/__tests__/xcm.test.ts index 28510b8..ab3db45 100644 --- a/src/__tests__/xcm.test.ts +++ b/src/__tests__/xcm.test.ts @@ -5,6 +5,7 @@ import { describe, expect, it } from 'vitest'; import { ETH_RPC, PARA_ID } from '../consts'; import { + PROD_ADDR, TEST_ADDR_RELAYER, } from './testConsts'; import { @@ -22,6 +23,7 @@ import { shouldRouteXcm, sudoTransferToken, } from './testUtils'; +import { parseUnits } from 'ethers/lib/utils'; const DAI_ADDR = ROUTER_TOKEN_INFO.dai.acalaAddr; @@ -130,7 +132,7 @@ describe('/routeXcm', () => { const { routerAddr } = res.data; console.log('transferring to router ...'); - await sudoTransferToken('0xBbBBa9Ebe50f9456E106e6ef2992179182889999', routerAddr, provider, DAI_ADDR, 1.23); + await sudoTransferToken(PROD_ADDR, routerAddr, provider, DAI_ADDR, 1.23); const dai = ERC20__factory.connect(DAI_ADDR, provider); const curBalRelayer = (await dai.balanceOf(TEST_ADDR_RELAYER)).toBigInt(); @@ -143,7 +145,7 @@ describe('/routeXcm', () => { const afterBalRelayer = (await dai.balanceOf(TEST_ADDR_RELAYER)).toBigInt(); console.log({ afterBalRelayer }); - expect(afterBalRelayer - curBalRelayer).to.eq(40000000000000000n); + expect(afterBalRelayer - curBalRelayer).to.eq(parseUnits('0.04', 18).toBigInt()); // DAI has 18 decimals expect((await dai.balanceOf(routerAddr)).toBigInt()).to.eq(0n); // router should be destroyed @@ -182,7 +184,7 @@ describe('/relayAndRoute', () => { const afterBalRelayer = (await dai.balanceOf(TEST_ADDR_RELAYER)).toBigInt(); console.log({ afterBalRelayer }); - expect(afterBalRelayer - curBalRelayer).to.eq(40000000000000000n); + expect(afterBalRelayer - curBalRelayer).to.eq(parseUnits('0.04', 18).toBigInt()); // DAI has 18 decimals expect((await dai.balanceOf(routerAddr)).toBigInt()).to.eq(0n); // router should be destroyed diff --git a/src/utils/index.ts b/src/utils/index.ts index 1f22026..34bf4ba 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -7,4 +7,3 @@ export * from './validate'; export * from './wormhole'; export * from './address'; export * from './error'; -export * from './token'; diff --git a/src/utils/token.ts b/src/utils/token.ts deleted file mode 100644 index 3035e12..0000000 --- a/src/utils/token.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { BigNumber, Signer } from 'ethers'; -import { ERC20__factory } from '@acala-network/asset-router/dist/typechain-types'; -import { Provider } from '@ethersproject/abstract-provider'; -import { formatUnits, parseUnits } from 'ethers/lib/utils'; - -export const parseAmount = async ( - tokenAddr: string, - amount: string, - signerOrProvider: Signer | Provider, -): Promise => { - const token = ERC20__factory.connect(tokenAddr, signerOrProvider); - const decimals = await token.decimals(); - - return parseUnits(amount, decimals); -}; - -export const getTokenBalance = async ( - tokenAddr: string, - signer: Signer, -): Promise => { - const token = ERC20__factory.connect(tokenAddr, signer); - - const [bal, decimals] = await Promise.all([ - token.balanceOf(await signer.getAddress()), - token.decimals(), - ]); - - return formatUnits(bal, decimals); -}; diff --git a/src/utils/utils.ts b/src/utils/utils.ts index b2876cd..ffc3af1 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -1,6 +1,6 @@ import { ApiPromise, Keyring, WsProvider } from '@polkadot/api'; -import { BigNumber, PopulatedTransaction, Wallet } from 'ethers'; -import { CHAIN_ID_ACALA, CHAIN_ID_AVAX, CHAIN_ID_KARURA, CONTRACTS, hexToUint8Array } from '@certusone/wormhole-sdk'; +import { BigNumber, PopulatedTransaction } from 'ethers'; +import { CHAIN_ID_ACALA, CHAIN_ID_KARURA, hexToUint8Array } from '@certusone/wormhole-sdk'; import { DispatchError } from '@polkadot/types/interfaces'; import { ISubmittableResult } from '@polkadot/types/types'; import { JsonRpcProvider } from '@ethersproject/providers'; @@ -11,9 +11,7 @@ import { decodeEthGas, sleep } from '@acala-network/eth-providers'; import { options } from '@acala-network/api'; import { RelayerError } from './error'; -import { bridgeToken, getSignedVAAFromSequence } from './wormhole'; import { logger } from './logger'; -import { parseAmount } from './token'; export const ROUTER_CHAIN_IDS = [CHAIN_ID_KARURA, CHAIN_ID_ACALA] as const; export type RouterChainId = typeof ROUTER_CHAIN_IDS[number] @@ -33,36 +31,6 @@ export const getApi = async (privateKey: string, nodeUrl: string) => { return { substrateAddr, api }; }; -export const transferFromAvax = async ( - amount: string, - sourceAsset: string, - recipientAddr: string, - dstChainId: RouterChainId, - wallet: Wallet, - isMainnet = false, -): Promise => { - const tokenBridgeAddr = CONTRACTS[isMainnet ? 'MAINNET' : 'TESTNET'].avalanche.token_bridge; - const coreBridgeAddr = CONTRACTS[isMainnet ? 'MAINNET' : 'TESTNET'].avalanche.core; - const parsedAmount = await parseAmount(sourceAsset, amount, wallet); - const { sequence } = await bridgeToken( - wallet, - tokenBridgeAddr, - coreBridgeAddr, - recipientAddr, - sourceAsset, - dstChainId, - parsedAmount, - ); - console.log('transfer from AVAX complete', { sequence }, 'waiting for VAA...'); - - return getSignedVAAFromSequence( - sequence, - CHAIN_ID_AVAX, - tokenBridgeAddr, - isMainnet, - ); -}; - // TODO: add exitReason to receipt directly export const getTxFailingReason = async (txHash: string, provider: JsonRpcProvider): Promise => { const tx = await provider.getTransaction(txHash); diff --git a/src/utils/wormhole.ts b/src/utils/wormhole.ts index 8453445..b0a6958 100644 --- a/src/utils/wormhole.ts +++ b/src/utils/wormhole.ts @@ -1,22 +1,13 @@ -import { BigNumberish, ContractReceipt, Wallet } from 'ethers'; import { CHAIN_ID_KARURA, ChainId, - getEmitterAddressEth, - getSignedVAAWithRetry, - hexToUint8Array, - parseSequenceFromLogEth, parseTransferPayload, parseVaa, - transferFromEth, - tryNativeToHexString, - uint8ArrayToHex, } from '@certusone/wormhole-sdk'; -import { NodeHttpTransport } from '@improbable-eng/grpc-web-node-http-transport'; import { ROUTER_TOKEN_INFO } from '@acala-network/asset-router/dist/consts'; import { ChainConfig } from './configureEnv'; -import { ROUTER_TOKEN_INFO_TESTNET, WORMHOLE_GUARDIAN_RPC, ZERO_ADDR } from '../consts'; +import { ROUTER_TOKEN_INFO_TESTNET, ZERO_ADDR } from '../consts'; export interface VaaInfo { amount: bigint; @@ -39,42 +30,6 @@ export const parseVaaPayload = async (bytes: Uint8Array): Promise => { }; }; -export const bridgeToken = async ( - signer: Wallet, - tokenBridgeAddr: string, - coreBridgeAddr: string, - recipientAddr: string, - sourceAssetAddr: string, - targetChain: ChainId, - amount: BigNumberish, -): Promise<{ - receipt: ContractReceipt; - sequence: string; -}> => { - const hexString = tryNativeToHexString(recipientAddr, targetChain); - if (!hexString) { - throw new Error('Invalid recipient'); - } - const vaaCompatibleAddr = hexToUint8Array(hexString); - - console.log(`sending bridging tx with wallet ${signer.address} and amount ${amount} ...`); - const receipt = await transferFromEth( - tokenBridgeAddr, - signer, - sourceAssetAddr, - amount, - targetChain, - vaaCompatibleAddr, - ); - - const sequence = parseSequenceFromLogEth(receipt, coreBridgeAddr); - - return { - receipt, - sequence, - }; -}; - export const getRouterChainTokenAddr = async ( originAddr: string, chainConfig: ChainConfig, @@ -97,24 +52,3 @@ export const getRouterChainTokenAddr = async ( return routerChainTokenInfo; }; - -export const getSignedVAAFromSequence = async ( - sequence: string, - chainId: ChainId, - tokenBridgeAddr: string, - isMainnet = false, -) => { - const guardianRpc = isMainnet - ? WORMHOLE_GUARDIAN_RPC.MAINNET - : WORMHOLE_GUARDIAN_RPC.TESTNET; - const emitterAddress = getEmitterAddressEth(tokenBridgeAddr); - const { vaaBytes } = await getSignedVAAWithRetry( - guardianRpc, - chainId, - emitterAddress, - sequence, - { transport: NodeHttpTransport() }, - ); - - return uint8ArrayToHex(vaaBytes); -};