diff --git a/src/libs/TransactionRecoveryApi/AxelarGMPRecoveryAPI.ts b/src/libs/TransactionRecoveryApi/AxelarGMPRecoveryAPI.ts index 8427f1a5..bbead97e 100644 --- a/src/libs/TransactionRecoveryApi/AxelarGMPRecoveryAPI.ts +++ b/src/libs/TransactionRecoveryApi/AxelarGMPRecoveryAPI.ts @@ -13,7 +13,6 @@ import { } from "../types"; import { AxelarRecoveryApi, - BatchedCommandsAxelarscanResponse, ExecuteParams, GMPStatus, GMPStatusResponse, @@ -476,6 +475,19 @@ export class AxelarGMPRecoveryAPI extends AxelarRecoveryApi { ); return txStatus?.status === GMPStatus.DEST_EXECUTED; } + /** + * Check if given transaction is already confirmed. + * @param txHash string - transaction hash + * @returns Promise - true if transaction is already confirmed + */ + public async isConfirmed(txHash: string): Promise { + const txStatus: GMPStatusResponse | undefined = await this.queryTransactionStatus(txHash).catch( + () => undefined + ); + return [GMPStatus.SRC_GATEWAY_CONFIRMED, GMPStatus.DEST_GATEWAY_APPROVED].includes( + this.parseGMPStatus(txStatus?.status) as GMPStatus + ); + } /** * Calculate the gas fee in native token for executing a transaction at the destination chain using the source chain's gas price. @@ -498,6 +510,8 @@ export class AxelarGMPRecoveryAPI extends AxelarRecoveryApi { const provider = options.provider || getDefaultProvider(sourceChain, this.environment); const receipt = await provider.getTransactionReceipt(txHash); const paidGasFee = getNativeGasAmountFromTxReceipt(receipt) || "0"; + const hasTxBeenConfirmed = (await this.isConfirmed(txHash)) || false; + options.shouldSubtractBaseFee = hasTxBeenConfirmed; return this.subtractGasFee(sourceChain, destinationChain, gasTokenSymbol, paidGasFee, options); } @@ -578,7 +592,11 @@ export class AxelarGMPRecoveryAPI extends AxelarRecoveryApi { chain, destinationChain, nativeGasTokenSymbol, - { estimatedGas: options?.estimatedGasUsed, provider: evmWalletDetails.provider } + { + estimatedGas: options?.estimatedGasUsed, + gasMultipler: options?.gasMultipler, + provider: evmWalletDetails.provider, + } ).catch(() => undefined); } @@ -781,10 +799,21 @@ export class AxelarGMPRecoveryAPI extends AxelarRecoveryApi { sourceChain, destinationChain, gasTokenSymbol, - options.estimatedGas + options.estimatedGas, + options.gasMultipler, + undefined, + false ); - const topupGasAmount = ethers.BigNumber.from(totalGasFee); + let topupGasAmount = ethers.BigNumber.from(totalGasFee); + if (options.shouldSubtractBaseFee) { + const response = await this.axelarQueryApi + .getNativeGasBaseFee(sourceChain, destinationChain, gasTokenSymbol as GasToken) + .catch(() => undefined); + if (response && response.baseFee) { + topupGasAmount = topupGasAmount.sub(response.baseFee); + } + } return topupGasAmount.gt(0) ? topupGasAmount.toString() : "0"; } diff --git a/src/libs/TransactionRecoveryApi/AxelarRecoveryApi.ts b/src/libs/TransactionRecoveryApi/AxelarRecoveryApi.ts index 6f10a2f6..70a49d88 100644 --- a/src/libs/TransactionRecoveryApi/AxelarRecoveryApi.ts +++ b/src/libs/TransactionRecoveryApi/AxelarRecoveryApi.ts @@ -27,6 +27,7 @@ export enum GMPStatus { INSUFFICIENT_FEE = "insufficient_fee", UNKNOWN_ERROR = "unknown_error", CANNOT_FETCH_STATUS = "cannot_fetch_status", + SRC_GATEWAY_CONFIRMED = "confirmed", } export enum GasPaidStatus { @@ -188,7 +189,7 @@ export class AxelarRecoveryApi { ); } - private parseGMPStatus(response: any): GMPStatus | string { + public parseGMPStatus(response: any): GMPStatus | string { const { error, status } = response; if (status === "error" && error) return GMPStatus.DEST_EXECUTE_ERROR; diff --git a/src/libs/types/index.ts b/src/libs/types/index.ts index b6933d60..d0948b00 100644 --- a/src/libs/types/index.ts +++ b/src/libs/types/index.ts @@ -145,6 +145,7 @@ export interface AddGasOptions { amount?: string; refundAddress?: string; estimatedGasUsed?: number; + gasMultipler?: number; evmWalletDetails?: EvmWalletDetails; } @@ -177,6 +178,8 @@ export interface TxResult { export interface QueryGasFeeOptions { provider?: ethers.providers.JsonRpcProvider; estimatedGas?: number; + gasMultipler?: number; + shouldSubtractBaseFee?: boolean; } export interface QueryTransferOptions {