UNPKG

@getclave/lifi-sdk

Version:

LI.FI Any-to-Any Cross-Chain-Swap SDK

130 lines (129 loc) 6.06 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.checkAllowance = void 0; const actions_1 = require("viem/actions"); const utils_1 = require("viem/utils"); const constants_1 = require("../../constants"); const getActionWithFallback_1 = require("./getActionWithFallback"); const getAllowance_1 = require("./getAllowance"); const parseEVMErrors_1 = require("./parseEVMErrors"); const getNativePermit_1 = require("./permits/getNativePermit"); const setAllowance_1 = require("./setAllowance"); const typeguards_1 = require("./typeguards"); const waitForTransactionReceipt_1 = require("./waitForTransactionReceipt"); const checkAllowance = async ({ client, chain, step, statusManager, executionOptions, allowUserInteraction = false, batchingSupported = false, permit2Supported = false, disableMessageSigning = false, }) => { // Find existing or create new allowance process const allowanceProcess = statusManager.findOrCreateProcess({ step, type: 'TOKEN_ALLOWANCE', chainId: step.action.fromChainId, }); try { // Handle existing pending transaction if (allowanceProcess.txHash && allowanceProcess.status !== 'DONE') { await waitForApprovalTransaction(client, allowanceProcess.txHash, allowanceProcess.type, step, chain, statusManager); return { status: 'DONE' }; } // Start new allowance check statusManager.updateProcess(step, allowanceProcess.type, 'STARTED'); const spenderAddress = permit2Supported ? chain.permit2 : step.estimate.approvalAddress; const fromAmount = BigInt(step.action.fromAmount); const approved = await (0, getAllowance_1.getAllowance)(client, step.action.fromToken.address, client.account.address, spenderAddress); // Return early if already approved if (fromAmount <= approved) { statusManager.updateProcess(step, allowanceProcess.type, 'DONE'); return { status: 'DONE' }; } const isRelayerTransaction = (0, typeguards_1.isRelayerStep)(step); // Check if proxy contract is available and message signing is not disabled, also not available for atomic batch const isNativePermitAvailable = !!chain.permit2Proxy && !batchingSupported && !disableMessageSigning; let nativePermitData; if (isRelayerTransaction) { nativePermitData = step.typedData.find((p) => p.primaryType === 'Permit'); } else if (isNativePermitAvailable) { nativePermitData = await (0, getActionWithFallback_1.getActionWithFallback)(client, getNativePermit_1.getNativePermit, 'getNativePermit', { chainId: chain.id, tokenAddress: step.action.fromToken.address, spenderAddress: chain.permit2Proxy, amount: fromAmount, }); } statusManager.updateProcess(step, allowanceProcess.type, 'ACTION_REQUIRED'); if (!allowUserInteraction) { return { status: 'ACTION_REQUIRED' }; } if (isNativePermitAvailable && nativePermitData) { const signature = await (0, utils_1.getAction)(client, actions_1.signTypedData, 'signTypedData')({ account: client.account, domain: nativePermitData.domain, types: nativePermitData.types, primaryType: 'Permit', message: nativePermitData.message, }); statusManager.updateProcess(step, allowanceProcess.type, 'DONE'); return { status: 'NATIVE_PERMIT', data: { ...nativePermitData, signature, }, }; } // Set new allowance const approveAmount = permit2Supported ? constants_1.MaxUint256 : fromAmount; const approveTxHash = await (0, setAllowance_1.setAllowance)(client, step.action.fromToken.address, spenderAddress, approveAmount, executionOptions, batchingSupported); if (batchingSupported) { statusManager.updateProcess(step, allowanceProcess.type, 'DONE'); return { status: 'BATCH_APPROVAL', data: { to: step.action.fromToken.address, data: approveTxHash, chainId: step.action.fromToken.chainId, }, }; } await waitForApprovalTransaction(client, approveTxHash, allowanceProcess.type, step, chain, statusManager); return { status: 'DONE' }; } catch (e) { const error = await (0, parseEVMErrors_1.parseEVMErrors)(e, step, allowanceProcess); statusManager.updateProcess(step, allowanceProcess.type, 'FAILED', { error: { message: error.cause.message, code: error.code, }, }); statusManager.updateExecution(step, 'FAILED'); throw error; } }; exports.checkAllowance = checkAllowance; const waitForApprovalTransaction = async (client, txHash, processType, step, chain, statusManager) => { const baseExplorerUrl = chain.metamask.blockExplorerUrls[0]; const getTxLink = (hash) => `${baseExplorerUrl}tx/${hash}`; statusManager.updateProcess(step, processType, 'PENDING', { txHash, txLink: getTxLink(txHash), }); const transactionReceipt = await (0, waitForTransactionReceipt_1.waitForTransactionReceipt)({ client, chainId: chain.id, txHash, onReplaced(response) { const newHash = response.transaction.hash; statusManager.updateProcess(step, processType, 'PENDING', { txHash: newHash, txLink: getTxLink(newHash), }); }, }); const finalHash = transactionReceipt?.transactionHash || txHash; statusManager.updateProcess(step, processType, 'DONE', { txHash: finalHash, txLink: getTxLink(finalHash), }); };