From ab0299b0514cef9f2e16e2952b388766872f1236 Mon Sep 17 00:00:00 2001 From: Venkatesh V Date: Thu, 12 Sep 2024 17:03:13 +0530 Subject: [PATCH] feat(abstract-eth): fetch gasPrice and gasLimit from explorer TICKET: COIN-1201 --- .../src/abstractEthLikeNewCoins.ts | 107 +++++++++++++++--- .../src/lib/transactionBuilder.ts | 2 +- 2 files changed, 90 insertions(+), 19 deletions(-) diff --git a/modules/abstract-eth/src/abstractEthLikeNewCoins.ts b/modules/abstract-eth/src/abstractEthLikeNewCoins.ts index 1bdb28869b..65aeec45ba 100644 --- a/modules/abstract-eth/src/abstractEthLikeNewCoins.ts +++ b/modules/abstract-eth/src/abstractEthLikeNewCoins.ts @@ -1520,10 +1520,14 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin { } } - const gasLimit = new optionalDeps.ethUtil.BN(this.setGasLimit(params.gasLimit)); + // If gasLimit is not passed as a param, then default gasLimit 50000 will be set here + let gasLimit = new optionalDeps.ethUtil.BN(this.setGasLimit(params.gasLimit)); + const gasPrice = params.eip1559 ? new optionalDeps.ethUtil.BN(params.eip1559.maxFeePerGas) - : new optionalDeps.ethUtil.BN(this.setGasPrice(params.gasPrice)); + : params.gasPrice + ? new optionalDeps.ethUtil.BN(this.setGasPrice(params.gasPrice)) + : await this.getGasPriceFromExternalAPI(); const bitgoFeeAddressNonce = await this.getAddressNonce(bitgoFeeAddress); @@ -1588,14 +1592,6 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin { await new Promise((resolve) => setTimeout(resolve, 1000)); const sequenceId = await this.querySequenceId(walletContractAddress); - const txInfo = { - recipients: recipients, - expireTime: this.getDefaultExpireTime(), - contractSequenceId: sequenceId, - gasLimit: gasLimit.toString(10), - isEvmBasedCrossChainRecovery: true, - }; - const network = this.getNetwork(); const batcherContractAddress = network?.batcherContractAddress as string; @@ -1646,8 +1642,30 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin { txBuilder.walletVersion(4); } + // If gasLimit was not passed as a param, then fetch the gasLimit from Explorer + if (!params.gasLimit) { + const sendData = txBuilder.getSendData(); + gasLimit = await this.getGasLimitFromExternalAPI( + params.bitgoFeeAddress as string, + params.walletContractAddress, + sendData + ); + txBuilder.fee({ + ...txFee, + gasLimit: gasLimit.toString(), + }); + } + const tx = await txBuilder.build(); + const txInfo = { + recipients: recipients, + expireTime: this.getDefaultExpireTime(), + contractSequenceId: sequenceId, + gasLimit: gasLimit.toString(10), + isEvmBasedCrossChainRecovery: true, + }; + const response: OfflineVaultTxInfo = { txHex: tx.toBroadcastFormat(), userKey, @@ -1740,14 +1758,6 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin { await new Promise((resolve) => setTimeout(resolve, 1000)); const sequenceId = await this.querySequenceId(params.walletContractAddress); - const txInfo = { - recipients: recipients, - expireTime: this.getDefaultExpireTime(), - contractSequenceId: sequenceId, - gasLimit: gasLimit.toString(10), - isEvmBasedCrossChainRecovery: true, - }; - const txBuilder = this.getTransactionBuilder(params.common) as TransactionBuilder; txBuilder.counter(bitgoFeeAddressNonce); txBuilder.contract(params.walletContractAddress as string); @@ -1799,8 +1809,29 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin { txBuilder.walletVersion(4); } + if (!params.gasLimit) { + const sendData = txBuilder.getSendData(); + gasLimit = await this.getGasLimitFromExternalAPI( + params.bitgoFeeAddress as string, + params.walletContractAddress, + sendData + ); + txBuilder.fee({ + ...txFee, + gasLimit: gasLimit.toString(), + }); + } + const tx = await txBuilder.build(); + const txInfo = { + recipients: recipients, + expireTime: this.getDefaultExpireTime(), + contractSequenceId: sequenceId, + gasLimit: gasLimit.toString(10), + isEvmBasedCrossChainRecovery: true, + }; + const response: OfflineVaultTxInfo = { txHex: tx.toBroadcastFormat(), userKey, @@ -2599,4 +2630,44 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin { } } } + + /** + * Fetch the gas price from the explorer + */ + async getGasPriceFromExternalAPI(): Promise { + try { + const res = await this.recoveryBlockchainExplorerQuery({ + module: 'proxy', + action: 'eth_gasPrice', + }); + const gasPrice = new BN(res.result.slice(2), 16); + console.log(` Got gas price: ${gasPrice}`); + return gasPrice; + } catch (e) { + throw new Error('Failed to get gas price'); + } + } + + /** + * Fetch the gas limit from the explorer + * @param from + * @param to + * @param data + */ + async getGasLimitFromExternalAPI(from: string, to: string, data: string): Promise { + try { + const res = await this.recoveryBlockchainExplorerQuery({ + module: 'proxy', + action: 'eth_estimateGas', + from, + to, + data, + }); + const gasLimit = new BN(res.result.slice(2), 16); + console.log(`Got gas limit: ${gasLimit}`); + return gasLimit; + } catch (e) { + throw new Error('Failed to get gas limit: '); + } + } } diff --git a/modules/abstract-eth/src/lib/transactionBuilder.ts b/modules/abstract-eth/src/lib/transactionBuilder.ts index 24a8110b2a..7f18451c5e 100644 --- a/modules/abstract-eth/src/lib/transactionBuilder.ts +++ b/modules/abstract-eth/src/lib/transactionBuilder.ts @@ -621,7 +621,7 @@ export abstract class TransactionBuilder extends BaseTransactionBuilder { * * @returns {string} serialized sendMultiSig data */ - private getSendData(): string { + public getSendData(): string { if (!this._transfer) { throw new BuildTransactionError('Missing transfer information'); }