diff --git a/README.md b/README.md index 9394ee7..f10016c 100644 --- a/README.md +++ b/README.md @@ -637,13 +637,13 @@ GET /shouldRouteSwapAndLp?recipient=0x0085560b24769dAC4ed057F1B2ae40746AA9aAb6&s - swap small amount of token and airdrop ACA to recipient - swap `swapAmount` token to LDOT, then add LP, refund the remaining token recipient - stake Lp to euphrates for the recipient -- returns the txhash +- returns the txhash and how many records are removed ``` POST /routeSwapAndLp data: { poolId: string; // euphrates pool id recipient: string; // dest evm address - token: string; // token to route + token: string; // token to route swapAmount: string; // how many token to swap before adding liquidity minShareAmount?: string; // add liquidity min share amount (default: 0) } @@ -661,7 +661,10 @@ data: { => tx hash { - data: '0xe1c82c53796d82d87d2e31e289b3cc8ff18e304b8ac95f2bd7548a1706bb8655' + data: { + txHash: '0xe1c82c53796d82d87d2e31e289b3cc8ff18e304b8ac95f2bd7548a1706bb8655', + removed: 1 + } } /* ---------- when error ---------- */ @@ -677,12 +680,14 @@ POST /rescueSwapAndLp data: { poolId: string; // euphrates pool id recipient: string; // dest evm address - token: string; // token to route + token: string; // token to route swapAmount: string; // how many token to swap before adding liquidity minShareAmount?: string; // add liquidity min share amount (default: 0) } ``` +example +``` POST /rescueSwapAndLp data: { "poolId": 7, @@ -700,6 +705,18 @@ data: { // similar to /routeXcm ``` +### `/saveRouterInfo` +save router info to db + +``` +POST /saveRouterInfo +data: { + routerAddr: string; + recipient: string; + params: string; // router params +} +``` + ### `/routerInfo` get router info diff --git a/src/api/swapAndLp.ts b/src/api/swapAndLp.ts index a6ef802..2dd6389 100644 --- a/src/api/swapAndLp.ts +++ b/src/api/swapAndLp.ts @@ -14,6 +14,7 @@ import { _populateRouteTx, getChainConfig, getMainnetChainId, + parseRouterAddr, } from '../utils'; import { db } from '../db'; @@ -108,28 +109,24 @@ export const routeSwapAndLp = async (params: SwapAndLpParams) => { ); const receipt = await tx.wait(); + const errParams = { ...params, txHash: receipt.transactionHash }; if (receipt.status !== 1) { - throw new RouteError('swap and lp failed', { ...params, txHash: receipt.transactionHash }); + throw new RouteError('swap and lp failed', errParams); } - // parse receipit log to get router addr - const iface = BaseRouter__factory.createInterface(); - const routerDeployedEventSig = iface.getEventTopic('RouterCreated'); - const routerDeployedLog = receipt.logs.find(log => log.topics[0] === routerDeployedEventSig); - if (!routerDeployedLog) { - throw new RouteError('router deployed log not found', { ...params, txHash: receipt.transactionHash }); + let routerAddr: string; + try { + routerAddr = parseRouterAddr(receipt); + } catch (err) { + throw new RouteError(`failed to parse router addr from receipt: ${err.message}`, errParams); } - const parsedLog = iface.parseLog(routerDeployedLog); - const routerAddr = parsedLog.args.addr; - const removed = await db.removeRouterInfo({ routerAddr }); return { txHash: receipt.transactionHash, removed, }; - return receipt.transactionHash; }; export const rescueSwapAndLp = async (params: SwapAndLpParams) => { diff --git a/src/api/swapAndRoute.ts b/src/api/swapAndRoute.ts index e0200f8..d378a45 100644 --- a/src/api/swapAndRoute.ts +++ b/src/api/swapAndRoute.ts @@ -3,7 +3,7 @@ import { ERC20__factory } from '@certusone/wormhole-sdk/lib/cjs/ethers-contracts import { SwapAndStakeEuphratesFactory__factory } from '@acala-network/asset-router/dist/typechain-types'; import { constants } from 'ethers'; -import { DROP_SWAP_AMOUNT_JITOSOL, EUPHRATES_ADDR, EUPHRATES_POOLS, RELAYER_ADDR, SWAP_SUPPLY_TOKENS, DROP_AMOUNT_ACA } from '../consts'; +import { DROP_AMOUNT_ACA, DROP_SWAP_AMOUNT_JITOSOL, EUPHRATES_ADDR, EUPHRATES_POOLS, RELAYER_ADDR, SWAP_SUPPLY_TOKENS } from '../consts'; import { Mainnet, RouteError, diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 03ed581..47d1cbb 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -1,5 +1,5 @@ import { ApiPromise, Keyring, WsProvider } from '@polkadot/api'; -import { BigNumber, PopulatedTransaction } from 'ethers'; +import { BigNumber, Contract, ContractReceipt, 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'; @@ -10,7 +10,8 @@ import { cryptoWaitReady } from '@polkadot/util-crypto'; import { decodeEthGas, sleep } from '@acala-network/eth-providers'; import { options } from '@acala-network/api'; -import { RelayerError } from './error'; +import { BaseRouter__factory } from '@acala-network/asset-router/dist/typechain-types'; +import { RelayerError, RouteError } from './error'; import { logger } from './logger'; export const ROUTER_CHAIN_IDS = [CHAIN_ID_KARURA, CHAIN_ID_ACALA] as const; @@ -181,3 +182,17 @@ export const serialize = (params: any) => { return 'failed to serialize'; } }; + +export const parseRouterAddr = (receipt: ContractReceipt) => { + const iface = BaseRouter__factory.createInterface(); + const routerDeployedEventSig = iface.getEventTopic('RouterCreated'); + const routerDeployedLog = receipt.logs.find(log => log.topics[0] === routerDeployedEventSig); + if (!routerDeployedLog) { + throw new Error('router deployed log not found'); + } + + const parsedLog = iface.parseLog(routerDeployedLog); + const routerAddr = parsedLog.args.addr; + + return routerAddr; +};