approve:async ({from,contractAddress,privateKey,stakingProviderName,amountInWei,nonce,estimateGas,maxPriorityFeePerGas,gasFee,feesType,})=>{try{const{currentAllowance,firstTrx,secondTrx}=awaitretryFunc(asyncevmProvider=>{constwalletSigner=newethers.Wallet(privateKey,evmProvider);consttokenContract=newethers.Contract(contractAddress,localErc20ABI,walletSigner,);const{stakingProviderAddress}=awaitEvmStakingProvider.getStakingAddress({contractAddress,stakingProviderName,});constallowance=awaittokenContract.allowance(from,stakingProviderAddress,);console.log('Current allowance:',allowance.toString());if (allowance>=amountInWei){console.log('Already approved');returntrue;}letfinalEstimateGas=BigInt(estimateGas);if (typeoffinalEstimateGas!=='bigint'){finalEstimateGas=awaittokenContract['transfer(address,uint256)'].estimateGas(stakingProviderAddress,amountInWei);}letfinalGasPrice=gasFee;letfinalMaxPriorityFeePerGas=maxPriorityFeePerGas;if (typeoffinalGasPrice!=='bigint'){constgasFeeData=awaitgetEtherGasPrice(feesType,evmProvider);finalGasPrice=gasFeeData?.gasPrice;finalMaxPriorityFeePerGas=gasFeeData?.maxPriorityFeePerGas;}letoptions={type:2,// gasLimit: 100000n, // NOTE: this needs to revert before commit (for pending transaction)gasLimit:finalEstimateGas,// 100000// maxFeePerGas: 1n, // NOTE: this needs to revert before commitmaxFeePerGas:finalGasPrice,maxPriorityFeePerGas:validatePriorityFee(finalMaxPriorityFeePerGas,finalGasPrice,),nonce,};if (isEip1559NotSupported(chain_name)){deleteoptions.type;deleteoptions.maxPriorityFeePerGas;deleteoptions.maxFeePerGas;options.gasPrice=finalGasPrice;}constresetTrx=awaittokenContract.approve.populateTransaction(stakingProviderAddress,0n,options,);constapproveTx=awaittokenContract.approve.populateTransaction(stakingProviderAddress,amountInWei,allowance>0n?{...options,nonce:options.nonce+1}// reset will be sent → use N+1:options,);return{firstTrx:resetTrx,secondTrx:approveTx,currentAllowance:allowance,};},null,);lettrx1,trx2;if (currentAllowance>0n){console.log('Resetting allowance to 0...');constapproveHash=awaitcreateSendTransaction(newethers.Wallet(privateKey),firstTrx,);constapproveTxHash=approveHash.hash||approveHash;console.log('Approve first submitted:',approveTxHash);trx1=awaitEVMChain(chain_name,undefined,customRpcUrl,).waitForConfirmation({transaction:approveHash,interval:5000,retries:15,});console.log('Approved first confirmed',trx1);}constapproveHash=awaitcreateSendTransaction(newethers.Wallet(privateKey),secondTrx,);constapproveTxHash=approveHash.hash||approveHash;console.log('Approve second submitted:',approveTxHash);trx2=awaitEVMChain(chain_name,undefined,customRpcUrl,).waitForConfirmation({transaction:approveHash,interval:5000,retries:15,});console.log('Approved second confirmed',trx2);return{confirmTransaction:trx2,transaction1:trx1,transaction2:trx2,};}catch (error){console.error('Error in approve transaction',error);thrownewError(error);}},getEstimateFeForAllowanceApprove:async ({isFetchNonce,existingNonce,from,contractAddress,stakingProviderName,amountInWei,feesType,nonce,allowance,})=>retryFunc(asyncevmProvider=>{consttokenContract=newethers.Contract(contractAddress,erc20Abi,evmProvider,);const{stakingProviderAddress}=awaitEvmStakingProvider.getStakingAddress({contractAddress,stakingProviderName,});letestimateGas;try{estimateGas=awaittokenContract.approve.estimateGas(stakingProviderAddress,amountInWei,{from},);}catch (error){estimateGas=60000n;}// When an existing non-zero allowance must be reset first, the second tx// writes 0 → amountInWei (SSTORE ~20,000 gas) instead of the estimated// non-zero → non-zero case (~5,000 gas), so add the difference.try{constcurrentAllowance=awaittokenContract.allowance(from,stakingProviderAddress,);if (currentAllowance>0n&¤tAllowance<amountInWei){estimateGas+=20000n;}}catch (_){}constfinalEstimateGas=(estimateGas*110n)/100n;letcurrentNonce;if (isFetchNonce||existingNonce==null){currentNonce=awaitEVMChain(chain_name,undefined).getNonce({customRpcUrl,address:from,});}elseif (existingNonce){currentNonce=existingNonce;}constobj=awaitcalculateTotalFees({feesType,evmProvider,fromAddress:from,toAddress:stakingProviderAddress,estimateGas:finalEstimateGas,isFetchNonce:nonce==null,existingNonce:currentNonce,});return{...obj,allowance,fee:allowance?obj.fee*2:obj.fee,};},null),readAllowance:async ({from,contractAddress,stakingProviderName,amountInWei,})=>retryFunc(asyncevmProvider=>{consttokenContract=newethers.Contract(contractAddress,erc20Abi,evmProvider,);const{stakingProviderAddress}=awaitEvmStakingProvider.getStakingAddress({contractAddress,stakingProviderName,});constallowance=awaittokenContract.allowance(from,stakingProviderAddress,);constisApproved=allowance>=amountInWei;constneedsReset=!isApproved&&allowance>0n;constrequired=isApproved?0n:amountInWei-allowance;return{allowance,isApproved,needsReset,required,};},null),
Top comments (0)
Subscribe
We're a place where coders share, stay up-to-date and grow their careers.
Top comments (0)