UNPKG

@lifi/widget

Version:

LI.FI Widget for cross-chain bridging and swapping. It will drive your multi-chain strategy and attract new users from everywhere.

238 lines (220 loc) 7.03 kB
import type { ExtendedTransactionInfo, FeeCost, FullStatusData, Process, ProcessStatus, Substatus, TokenAmount, ToolsResponse, } from '@lifi/sdk' import type { RouteExecution } from '../stores/routes/types.js' import { formatTokenPrice } from './format.js' const buildProcessFromTxHistory = (tx: FullStatusData): Process[] => { const sending = tx.sending as ExtendedTransactionInfo const receiving = tx.receiving as ExtendedTransactionInfo if (!sending.token?.chainId || !receiving.token?.chainId) { return [] } const processStatus: ProcessStatus = tx.status === 'DONE' ? 'DONE' : 'FAILED' const substatus: Substatus = processStatus === 'FAILED' ? 'UNKNOWN_ERROR' : 'COMPLETED' if (sending.chainId === receiving.chainId) { return [ { type: 'SWAP', // operations on same chain will be swaps startedAt: sending.timestamp ?? Date.now(), message: '', status: processStatus, txHash: sending.txHash, txLink: sending.txLink, doneAt: receiving.timestamp ?? Date.now(), substatus, substatusMessage: '', }, ] } const process: Process[] = [ { type: 'CROSS_CHAIN', // first step of bridging, ignoring the approvals startedAt: sending.timestamp ?? Date.now(), message: '', status: processStatus, // can be FAILED txHash: sending.txHash, txLink: sending.txLink, doneAt: sending.timestamp, }, { type: 'RECEIVING_CHAIN', // final step of bridging, post swaps startedAt: receiving.timestamp ?? Date.now(), message: '', status: processStatus, substatus, substatusMessage: '', doneAt: receiving.timestamp ?? Date.now(), txHash: receiving.txHash, txLink: receiving.txLink, }, ] return process } export const buildRouteFromTxHistory = ( tx: FullStatusData, tools?: ToolsResponse ) => { const sending = tx.sending as ExtendedTransactionInfo const receiving = tx.receiving as ExtendedTransactionInfo if (!sending.token?.chainId || !receiving.token?.chainId) { return } let usedTool = tx.sending.includedSteps?.find( (step) => step.toolDetails.key === tx.tool )?.toolDetails if (!usedTool) { const selectedBridge = tools?.bridges.find( (bridge) => bridge.key === tx.tool ) const selectedExchange = tools?.exchanges.find( (exchange) => exchange.key === tx.tool ) usedTool = { key: tx.tool, name: selectedBridge?.name ?? selectedExchange?.name ?? tx.tool, logoURI: selectedBridge?.logoURI ?? selectedExchange?.logoURI ?? '', } } const fromToken: TokenAmount = { ...sending.token, amount: BigInt(sending.amount ?? 0), } const toToken: TokenAmount = { ...receiving.token, amount: BigInt(receiving.amount ?? 0), } const sendingValue = sending.value ? BigInt(sending.value) : 0n const sendingFeeAmount = sending.gasToken.address === sending.token.address && sending.amount ? sendingValue - BigInt(sending.amount) : sendingValue const sendingFeeAmountUsd = sending.gasToken.priceUSD && sendingFeeAmount ? formatTokenPrice( sendingFeeAmount, sending.gasToken.priceUSD, sending.gasToken.decimals ) : 0 const feeCosts: FeeCost[] | undefined = sendingFeeAmount ? [ { amount: sendingFeeAmount.toString(), amountUSD: sendingFeeAmountUsd.toFixed(2), token: sending.gasToken, included: false, // Not used description: '', name: '', percentage: '', }, ] : undefined const routeExecution: RouteExecution = { status: 1, route: { id: (tx as FullStatusData).transactionId, fromAddress: (tx as FullStatusData).fromAddress, toAddress: (tx as FullStatusData).toAddress, fromChainId: sending.chainId, fromAmount: sending.amount ?? '', fromAmountUSD: sending.amountUSD ?? '', toAmount: receiving.amount ?? '', toAmountMin: receiving.amount ?? '', toAmountUSD: receiving.amountUSD ?? '', toChainId: receiving.chainId, fromToken, toToken, gasCostUSD: sending.gasAmountUSD, steps: [ { id: crypto.randomUUID(), type: 'lifi', tool: tx.tool, toolDetails: usedTool, action: { fromToken: sending.token, fromAmount: sending.amount ?? '', fromChainId: sending.chainId, fromAddress: (tx as FullStatusData).fromAddress, toToken: receiving.token, toChainId: receiving.chainId, toAddress: (tx as FullStatusData).toAddress, slippage: 0, }, estimate: { tool: tx.tool, approvalAddress: '', fromAmount: sending.amount ?? '', fromAmountUSD: sending.amountUSD ?? '', toAmountMin: receiving.amount ?? '', toAmount: receiving.amount ?? '', toAmountUSD: receiving.amountUSD ?? '', executionDuration: 0, }, includedSteps: [ { id: '', type: sending.chainId === receiving.chainId ? 'swap' : 'cross', action: { fromChainId: sending.chainId, fromAmount: sending.amount ?? '', fromToken: sending.token, toChainId: receiving.chainId, toToken: receiving.token, slippage: 0, fromAddress: (tx as FullStatusData).fromAddress, toAddress: (tx as FullStatusData).toAddress, }, estimate: { tool: tx.tool, fromAmount: sending.amount ?? '', toAmount: receiving.amount ?? '', toAmountMin: receiving.amount ?? '', approvalAddress: '', executionDuration: 0, }, tool: tx.tool, toolDetails: usedTool, }, ], integrator: tx.metadata?.integrator ?? '', execution: { status: 'DONE', // can be FAILED startedAt: sending.timestamp ?? Date.now(), doneAt: receiving.timestamp ?? Date.now(), process: buildProcessFromTxHistory(tx), fromAmount: sending.amount, toAmount: receiving.amount, toToken: receiving.token, gasCosts: [ { amount: sending.gasAmount, amountUSD: sending.gasAmountUSD, token: sending.gasToken, estimate: '0', limit: '0', price: '0', type: 'SEND', }, ], feeCosts, }, }, ], insurance: { state: 'NOT_INSURABLE', feeAmountUsd: '0', }, }, } return routeExecution }