UNPKG

@funkit/fun-relay

Version:
1,551 lines (1,532 loc) 62.8 kB
// src/bitcoin.ts import { adaptBitcoinWallet } from "@relayprotocol/relay-bitcoin-wallet-adapter"; function getBitcoinWallet(walletAddress, signPsbt) { return adaptBitcoinWallet( walletAddress, (address, psbt, dynamicParams) => signPsbt(address, psbt, dynamicParams) ); } function getBitcoinWalletFromSigner(walletAddress, signer) { return getBitcoinWallet( walletAddress, async (_, psbt) => psbt.signAllInputs(signer).toBase64() ); } // src/client.ts import * as relaySdk from "@relayprotocol/relay-sdk"; // src/types.ts import { LogLevel } from "@relayprotocol/relay-sdk"; // src/constants.ts var RELAY_BITCOIN_CHAIN_ID_NUMBER = 8253038; var RELAY_BITCOIN_CHAIN_ID = `${RELAY_BITCOIN_CHAIN_ID_NUMBER}`; var RELAY_SOLANA_CHAIN_ID_NUMBER = 792703809; var RELAY_SOLANA_CHAIN_ID = `${RELAY_SOLANA_CHAIN_ID_NUMBER}`; var FUN_SOLANA_CHAIN_ID_NUMBER = 1151111081099710; var FUN_HYPERCORE_CHAIN_ID_NUMBER = 1337; var RELAY_LIGHTER_CHAIN_ID_NUMBER = 3586256; var RELAY_LIGHTER_CHAIN_ID = `${RELAY_LIGHTER_CHAIN_ID_NUMBER}`; var RELAY_TRON_CHAIN_ID_NUMBER = 728126428; var RELAY_TRON_CHAIN_ID = `${RELAY_TRON_CHAIN_ID_NUMBER}`; var FUNKIT_NATIVE_TOKEN = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; var RELAY_NATIVE_TOKEN = "0x0000000000000000000000000000000000000000"; var RELAY_NATIVE_TOKEN_HYPERCORE = "0x00000000000000000000000000000000"; var RELAY_NATIVE_TOKEN_SOLANA = "11111111111111111111111111111111"; var RELAY_NATIVE_TOKEN_BITCOIN = "bc1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqmql8k8"; var RELAY_LIGHTER_USDC_PERPS = "0"; var RELAY_LIGHTER_USDC_SPOT = "3"; var RELAY_LIGHTER_ETH_SPOT = "1"; var RELAY_LIGHTER_FUN_ADDRESS_MAP = { "0x0000000000000000000000000000000000000000": RELAY_LIGHTER_USDC_PERPS, "0x0000000000000000000000000000000000000001": RELAY_LIGHTER_ETH_SPOT, "0x0000000000000000000000000000000000000003": RELAY_LIGHTER_USDC_SPOT }; var FUN_RELAY_REVENUE_WALLET = "0xdfd877679e95c1276c85801805b2c2ab8f4f4cf6"; var FUN_RELAY_REFERRER = "funxyz"; var RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS = 25e3; var RELAY_TERMINAL_STATUSES = [ "refund" /* REFUND */, "failure" /* FAILURE */, "success" /* SUCCESS */ ]; // src/client.ts function initializeRelayClient({ chains, logger, ...options }) { const relayLogger = (message, level) => { const logType = level === relaySdk.LogLevel.Error ? "error" : "info"; const logMessage = message[0] ?? "Unknown error"; const logData = message.length > 1 ? message.slice(1) : void 0; logger[logType]("[RelayClient]", { message: logMessage, relayLogLevel: level, ...logData && { data: logData } }); }; return relaySdk.createClient({ ...options, baseApiUrl: relaySdk.MAINNET_RELAY_API, logLevel: options.logLevel ?? relaySdk.LogLevel.Verbose, logger: relayLogger, chains: [ ...chains.map(relaySdk.convertViemChainToRelayChain), { id: RELAY_SOLANA_CHAIN_ID_NUMBER, name: "Solana", displayName: "Solana" }, { id: RELAY_LIGHTER_CHAIN_ID_NUMBER, name: "Lighter", displayName: "Lighter" } ] }); } function getRelayClient() { const client = relaySdk.getClient(); if (!client) { throw new Error("Relay client is not defined"); } return client; } // src/execution.ts import { MAINNET_RELAY_API as MAINNET_RELAY_API2 } from "@relayprotocol/relay-sdk"; var RELAY_VM_TYPES = [ "bvm", "evm", "hypevm", "svm", "lvm", "tvm" ]; function getTxHash({ logger, transactionType, txHashes, steps }) { const logPrefix = "getTxHash"; const logProps = { logger, transactionType, txHashes, steps }; logger.info(`${logPrefix}:started`, logProps); const getTxHashFromTxHashes = () => { const rawTxHashWithUnreliableTyping = txHashes[0]?.txHash; const txHash = typeof rawTxHashWithUnreliableTyping === "object" ? rawTxHashWithUnreliableTyping.id : rawTxHashWithUnreliableTyping; logger.info(`${logPrefix}:txHashesMode`, { ...logProps, txHash }); if (!txHash) { logger.error(`${logPrefix}:txHashesMode:noTxHash`, { ...logProps, txHash }); } return txHash; }; const getTxHashFromReceipt = () => { if (transactionType !== "erc4337") { throw new Error( `Transaction type ${transactionType} is not supported for receipt mode` ); } const receipt = steps?.[0]?.items?.[0]?.receipt; const txHash = receipt && "transactionHash" in receipt ? receipt.transactionHash : void 0; logger.info(`${logPrefix}:receiptMode`, { ...logProps, txHash }); return txHash; }; switch (transactionType) { // txHashes mode is the default mode case "standard": { const txHash = getTxHashFromTxHashes(); return txHash; } // receipt mode is used for ERC-4337 smart wallet transactions // unsupported for Solana Virtual Machine (SVM) or Sui (sui) transactions case "erc4337": { const txHash = getTxHashFromReceipt(); if (!txHash) { logger.info(`${logPrefix}:receiptMode:fallbackToTxHashes`, { ...logProps, txHash }); return getTxHashFromTxHashes(); } return txHash; } default: { throw new Error(`Unknown transactionType: ${transactionType}`); } } } async function executeRelayQuote({ logger, onError, onProgress, onTransactionConfirmed, onUserActionsCompleted, relayQuote, walletClient, transactionType = "standard" }) { let isUserActionsCompleted = false; let isTransactionConfirmed = false; await getRelayClient().actions.execute({ quote: relayQuote, wallet: walletClient, onProgress: async ({ steps, fees, breakdown, currentStep, currentStepItem, txHashes, details, error }) => { const logPrefix = "onRelayProgress"; logger.info(`${logPrefix}:params`, { steps, currentStep, fees, breakdown, currentStepItem, txHashes, details, error }); onProgress?.(currentStep ?? null); if (error) { logger.info(`${logPrefix}:errorDetected`, error); await onError(error).catch((e) => { logger.error(`${logPrefix}:onErrorFailed`, e); }); } else if (txHashes?.length) { const txHash = getTxHash({ transactionType, logger, txHashes, steps }); if ( // Call onUserActionsCompleted only once !isUserActionsCompleted && steps.every( (step) => step.items.every( // 'completed' - catch-all for items marked completed with no other info // - e.g. Batched items will not have txHash but will have their item marked 'complete' // 'pending' - for origin chain transactions that have been included on chain // - may sometimes be skipped, hence the need for 'submitted' condition below // 'submitted' - for destination chain transactions that have been submitted to the network // receipt - is present when the transaction has been mined/confirmed // Ensure onUserActionsCompleted is always called before onTransactionConfirmed (item) => item.status === "complete" || item.checkStatus === "pending" || item.checkStatus === "submitted" || item.receipt !== void 0 ) ) ) { logger.info(`${logPrefix}:onUserActionsCompleted`, txHashes); isUserActionsCompleted = true; try { await onUserActionsCompleted?.(txHash); } catch (e) { logger.error( `${logPrefix}:onUserActionsCompletedFailed`, e ); } } if ( // Call onTransactionConfirmed only once !isTransactionConfirmed && steps.every( (step) => step.items.every((item) => item.status === "complete") ) ) { logger.info(`${logPrefix}:onTransactionConfirmed`, txHashes); isTransactionConfirmed = true; try { await onTransactionConfirmed?.(txHash); } catch (e) { logger.error( `${logPrefix}:onTransactionConfirmedFailed`, e ); } } } } }); } async function getRelayExecutionInfo(requestId, apiKey) { const url = `${MAINNET_RELAY_API2}/intents/status/v2?requestId=${requestId}`; const response = await fetch(url, { headers: { "x-api-key": apiKey } }); if (!response.ok) { throw Error(response.statusText); } const data = await response.json(); return data; } // src/fees.ts async function getFunRelayFees({ clientId, estUsdValue, fromTokenAddress, fromChainId, recipientAddress, senderAddress, toTokenAddress, toChainId, usePermit }) { const params = new URLSearchParams({ clientId, estUsdValue: estUsdValue.toString(), fromTokenAddress, fromChainId, toTokenAddress, toChainId, ...recipientAddress ? { recipientAddress } : {}, ...senderAddress ? { senderAddress } : {}, ...usePermit !== void 0 ? { usePermit: String(usePermit) } : {} }); const url = `https://frog.fun.xyz/api/fee?${params.toString()}`; const response = await fetch(url); if (!response.ok) { throw Error(response.statusText); } const data = await response.json(); return data; } function parseRelayFees({ fees, fromChainIdRelay, fromTokenAddressRelay, logger, sourceAssetDecimals, sourceUnitPrice }) { const relayGasFeesUsd = Number.parseFloat(fees?.gas?.amountUsd || "0"); const areFunLpFeesInSourceChainToken = fees?.app?.currency?.chainId === fromChainIdRelay && fees?.app?.currency?.address?.toLowerCase() === fromTokenAddressRelay.toLowerCase(); const funLpFeesUsd = Number.parseFloat(fees?.app?.amountUsd || "0"); const funLpFeesFromAmount = areFunLpFeesInSourceChainToken ? Number.parseFloat(fees?.app?.amountFormatted || "0") : funLpFeesUsd / sourceUnitPrice || 0; const funLpFeesFromAmountBaseUnit = areFunLpFeesInSourceChainToken ? BigInt(fees?.app?.amount || "0") : BigInt(Math.floor(funLpFeesFromAmount * 10 ** sourceAssetDecimals)); const areRelayLpFeesInSourceChainToken = fees?.relayer?.currency?.chainId === fromChainIdRelay && fees?.relayer?.currency?.address?.toLowerCase() === fromTokenAddressRelay.toLowerCase(); const relayLpFeesUsd = Number.parseFloat(fees?.relayer?.amountUsd || "0"); const relayLpFeesFromAmount = areRelayLpFeesInSourceChainToken ? Number.parseFloat(fees?.relayer?.amountFormatted || "0") : relayLpFeesUsd / sourceUnitPrice || 0; const relayLpFeesFromAmountBaseUnit = areRelayLpFeesInSourceChainToken ? BigInt(fees?.relayer?.amount || "0") : BigInt(Math.floor(relayLpFeesFromAmount * 10 ** sourceAssetDecimals)); const totalLpFeesUsd = funLpFeesUsd + relayLpFeesUsd; const totalLpFeesFromAmount = funLpFeesFromAmount + relayLpFeesFromAmount; const totalLpFeesFromAmountBaseUnit = funLpFeesFromAmountBaseUnit + relayLpFeesFromAmountBaseUnit; logger.info("parseRelayFees", { relayGasFeesUsd, funLpFeesUsd, funLpFeesFromAmount, funLpFeesFromAmountBaseUnit, relayLpFeesUsd, relayLpFeesFromAmount, relayLpFeesFromAmountBaseUnit, totalLpFeesUsd, totalLpFeesFromAmount, totalLpFeesFromAmountBaseUnit }); return { relayGasFeesUsd, totalLpFeesUsd, totalFeesUsd: relayGasFeesUsd + totalLpFeesUsd, totalFeesFromAmount: totalLpFeesFromAmount, totalFeesFromAmountBaseUnit: totalLpFeesFromAmountBaseUnit }; } // src/price.ts import { MAINNET_RELAY_API as MAINNET_RELAY_API3 } from "@relayprotocol/relay-sdk"; // src/utils.ts function convertFunToRelayTokenAddress(address, chainId) { if (address.toLowerCase() === FUNKIT_NATIVE_TOKEN.toLowerCase()) { switch (chainId) { case FUN_HYPERCORE_CHAIN_ID_NUMBER: return RELAY_NATIVE_TOKEN_HYPERCORE; case RELAY_BITCOIN_CHAIN_ID_NUMBER: return RELAY_NATIVE_TOKEN_BITCOIN; // TODO: is it correct to assume chainId here is relay chain id? case RELAY_SOLANA_CHAIN_ID_NUMBER: case FUN_SOLANA_CHAIN_ID_NUMBER: return RELAY_NATIVE_TOKEN_SOLANA; case RELAY_LIGHTER_CHAIN_ID_NUMBER: return RELAY_LIGHTER_USDC_PERPS; default: return RELAY_NATIVE_TOKEN; } } if (RELAY_LIGHTER_CHAIN_ID_NUMBER === chainId) { const relayAddress = RELAY_LIGHTER_FUN_ADDRESS_MAP[address.toLowerCase()]; if (relayAddress) { return relayAddress; } } return address; } function convertFunToRelayChainId(chainId) { if (chainId === FUN_SOLANA_CHAIN_ID_NUMBER) { return RELAY_SOLANA_CHAIN_ID_NUMBER; } return chainId; } function getRelayExecutionRefundState(info) { switch (info.status) { case "refund" /* REFUND */: return "REFUNDED" /* REFUNDED */; default: return void 0; } } function getRelayExecutionState(info) { switch (info.status) { case "success" /* SUCCESS */: return "COMPLETED" /* COMPLETED */; case "failure" /* FAILURE */: case "refund" /* REFUND */: return "CHECKOUT_ERROR" /* CHECKOUT_ERROR */; default: return "PENDING_RECEIVAL" /* PENDING_RECEIVAL */; } } function isRelayExecutionTerminalStatus(info) { return RELAY_TERMINAL_STATUSES.includes(info.status); } function indexBy(items, getKey) { const indexedItems = {}; for (const item of items) { const key = getKey(item); if (!key) { continue; } indexedItems[key] = item; } return indexedItems; } function filterNullishHeaders(params) { const result = {}; for (const [key, value] of Object.entries(params)) { if (value != null) { result[key] = value; } } return result; } // src/price.ts async function getRelayAssetPriceInfo({ chainId, address, apiKey }) { const relayChainId = convertFunToRelayChainId(Number(chainId)); const relayTokenAddress = convertFunToRelayTokenAddress( address, relayChainId ); const url = `${MAINNET_RELAY_API3}/currencies/token/price?chainId=${relayChainId}&address=${relayTokenAddress}`; const headers = filterNullishHeaders({ "x-api-key": apiKey }); const response = await fetch(url, { headers }); if (!response.ok) { throw Error(response.statusText); } const data = await response.json(); return data; } // src/currency.ts import { MAINNET_RELAY_API as MAINNET_RELAY_API4 } from "@relayprotocol/relay-sdk"; async function getRelayAssetInfo({ chainId, address, // https://fun-xyz.slack.com/archives/C08MQ85QB2N/p1770674350731879?thread_ts=1770670744.270889&cid=C08MQ85QB2N useExternalSearch = true, apiKey }) { const relayChainId = convertFunToRelayChainId(Number(chainId)); const relayTokenAddress = convertFunToRelayTokenAddress( address, relayChainId ); const url = `${MAINNET_RELAY_API4}/currencies/v2`; const headers = filterNullishHeaders({ "Content-Type": "application/json", "x-api-key": apiKey }); const body = { chainIds: [relayChainId], address: relayTokenAddress, useExternalSearch }; const response = await fetch(url, { method: "POST", headers, body: JSON.stringify(body) }); if (!response.ok) { throw Error(response.statusText); } const data = await response.json(); return data?.[0]; } // src/quote.ts import { isAPIError } from "@relayprotocol/relay-sdk"; import { encodeFunctionData } from "viem"; async function getQuoteEstUsdValue({ tokenChainId, tokenAddress, tokenAmountBaseUnit, logger, apiKey }) { try { const normalizedChainId = convertFunToRelayChainId( Number(tokenChainId) ).toString(); const normalizedTokenAddress = convertFunToRelayTokenAddress( tokenAddress, Number(tokenChainId) ); const [tokenPriceRes, tokenInfoRes] = await Promise.all([ getRelayAssetPriceInfo({ chainId: normalizedChainId, address: normalizedTokenAddress, apiKey }), getRelayAssetInfo({ chainId: normalizedChainId, address: normalizedTokenAddress, apiKey }) ]); const isWUsdeEthereal = normalizedChainId === "5064014" && normalizedTokenAddress.toLowerCase() === "0xB6fC4B1BFF391e5F6b4a3D2C7Bda1FeE3524692D".toLowerCase(); const price = tokenPriceRes.price; const decimals = isWUsdeEthereal ? 18 : tokenInfoRes.decimals; const absoluteAmount = BigInt(tokenAmountBaseUnit) / BigInt(10 ** decimals); return Number(price) * Number(absoluteAmount); } catch (err) { logger.error("getQuoteEstUsdValueError", { message: `Failed to get USD value for token ${tokenAddress} on chain ${tokenChainId}: ${getErrorMessage( err )}. Falling back to 0 USD.` }); return 0; } } function getReferrer(clientId) { return clientId ? `${FUN_RELAY_REFERRER}|${clientId}` : FUN_RELAY_REFERRER; } var RelayQuoteClientError = class extends Error { constructor(statusCode, relayErrorCode, message, requestId = "") { super( `An error occurred trying to generate a relay quote: ${relayErrorCode} - ReqId ${requestId || "NO_REQ_ID"} - ${message}` ); this.statusCode = statusCode; this.relayErrorCode = relayErrorCode; this.name = new.target.name; Object.setPrototypeOf(this, new.target.prototype); } }; var getHeaders = (funRelayConfig, apiKey) => { const headers = { "x-api-key": apiKey, // Remote headers will override passed in headers ...funRelayConfig.headers ? { ...funRelayConfig.headers } : {} }; return headers; }; async function getRelayQuote({ logger, walletClient, ...params }) { const { actionParams, clientId, fromChainId, fromTokenAddress, options, recipientAddress, toChainId, toTokenAddress, tradeType, userAddress, apiKey, usePermit } = params; const vmType = walletClient && "vmType" in walletClient ? walletClient.vmType : "evm"; try { const relayClient = getRelayClient(); const isSameChainFlow = String(fromChainId) === String(toChainId); const txs = actionParams?.map((action) => { const data = action.rawCalldata ?? encodeFunctionData({ abi: action.contractAbi, args: action.functionArgs, functionName: action.functionName }); return { data, to: action.contractAddress, // Relay supports msg.value via 2 fields: `value` and `originalTxValue` // Both `value` and `originalTxValue` are required to be set for `erc20` + gas transfers // Only `value` is required for native token transfers. // TODO: This flow needs verification. // Internally for Relay, // - `originalTxValue` is designed to "bubble up" the value to the original tx. This only works for user-executed same-chain operations with calls. This does not work / apply to cross chain operations // - `value` is the internal multicall value ...isSameChainFlow ? { originalTxValue: String(action.value ?? 0n) } : {}, value: String(action.value ?? 0n) }; }); const isExactIn = params.tradeType === "EXACT_INPUT"; const queryTokenAmountBaseUnit = isExactIn ? params.fromTokenAmountBaseUnit : params.toTokenAmountBaseUnit; const queryTokenAddress = isExactIn ? fromTokenAddress : toTokenAddress; const queryTokenChainId = isExactIn ? fromChainId : toChainId; const estUsdValue = await getQuoteEstUsdValue({ tokenChainId: queryTokenChainId, tokenAddress: queryTokenAddress, tokenAmountBaseUnit: queryTokenAmountBaseUnit.toString(), logger, apiKey }); const funRelayConfig = await getFunRelayFees({ clientId, estUsdValue: Number(estUsdValue) || 0, fromTokenAddress, fromChainId, recipientAddress, senderAddress: userAddress, toTokenAddress, toChainId, usePermit }); const headers = getHeaders(funRelayConfig, apiKey); const appFeeBp = funRelayConfig.b + funRelayConfig.v; logger.info("getRelayQuoteParams", { ...params, appFeeBp, estUsdValue, funRelayConfig, queryTokenAmountBaseUnit, txs }); const relayQuote = await relayClient.actions.getQuote( { amount: queryTokenAmountBaseUnit.toString(), chainId: convertFunToRelayChainId(Number(fromChainId)), currency: convertFunToRelayTokenAddress( fromTokenAddress, Number(fromChainId) ), recipient: recipientAddress, toChainId: convertFunToRelayChainId(Number(toChainId)), toCurrency: convertFunToRelayTokenAddress( toTokenAddress, Number(toChainId) ), tradeType, txs, user: userAddress, wallet: walletClient, options: { referrer: getReferrer(clientId), appFees: [ { fee: appFeeBp.toString(), recipient: FUN_RELAY_REVENUE_WALLET } ], // Passed in options ...options, // Remote options will always override passed in options ...funRelayConfig.config.options } }, void 0, headers ); logger.info("relayQuote", relayQuote); const toAmountUsd = Number(relayQuote.details?.currencyOut?.amountUsd || 0); const fromAmountUsd = Number(relayQuote.details?.currencyIn?.amountUsd || 0); const fromAmountString = relayQuote.details?.currencyIn?.amountFormatted || "0"; const fromAmountBaseUnitString = relayQuote.details?.currencyIn?.amount || "0"; const fromAssetAmount = Number(fromAmountString || 0); const relayRequestId = relayQuote.steps[0]?.requestId; if (!relayRequestId) { throw new Error("Relay quote does not contain a requestId"); } if (!relayQuote.details?.currencyIn || !relayQuote.details?.currencyOut) { throw new Error("Relay quote does not contain trade details"); } const { relayGasFeesUsd, totalLpFeesUsd, totalFeesUsd, totalFeesFromAmount, totalFeesFromAmountBaseUnit } = parseRelayFees({ fees: relayQuote.fees, fromChainIdRelay: convertFunToRelayChainId(Number(fromChainId)), fromTokenAddressRelay: convertFunToRelayTokenAddress( fromTokenAddress, Number(fromChainId) ), logger, sourceAssetDecimals: relayQuote.details.currencyIn.currency?.decimals ?? 18, sourceUnitPrice: fromAmountUsd / fromAssetAmount || 1 }); const estSubtotalFromAmount = (fromAssetAmount - totalFeesFromAmount).toString(); const estSubtotalFromAmountBaseUnit = (BigInt(fromAmountBaseUnitString) - totalFeesFromAmountBaseUnit).toString(); return { quoteId: relayRequestId, estCheckoutTimeMs: (relayQuote.details.timeEstimate || 0) * 1e3 + RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS, estFeesFromAmount: totalFeesFromAmount.toString(), estFeesFromAmountBaseUnit: totalFeesFromAmountBaseUnit.toString(), estFeesUsd: totalFeesUsd, estMarketMakerGasUsd: relayGasFeesUsd, estSubtotalFromAmount, estSubtotalFromAmountBaseUnit, estSubtotalUsd: toAmountUsd, estTotalFromAmount: fromAmountString, estTotalFromAmountBaseUnit: fromAmountBaseUnitString, estTotalUsd: fromAmountUsd, finalToAmountBaseUnit: relayQuote.details.currencyOut.amount ?? "0", // TODO: Or do we want 'minimumAmount'? fromTokenAddress, // TODO: fromTokenAddress is typed as `0x${string}` why does not accept SolanaAddress lpFeePercentage: 0, // TODO: ? lpFeeUsd: totalLpFeesUsd, metadata: { fromAmountBaseUnit: isExactIn ? queryTokenAmountBaseUnit.toString() : relayQuote.details.currencyIn.amount ?? "0", relayQuote: { ...relayQuote, vmType }, toAmountBaseUnit: isExactIn ? relayQuote.details.currencyOut.amount ?? "0" : queryTokenAmountBaseUnit.toString() } }; } catch (err) { if (err instanceof Error && isAPIError(err)) { const apiError = err; const rawError = apiError.rawError; if (rawError?.errorCode) { throw new RelayQuoteClientError( apiError.statusCode, rawError.errorCode, rawError.message ?? apiError.message, rawError.requestId ); } } const message = getErrorMessage(err); throw new Error( `An error occurred trying to generate a relay quote: ${message}` ); } } function getErrorMessage(err) { return err instanceof Error ? err.message : typeof err === "string" ? err : JSON.stringify(err); } // src/solana.ts import { adaptSolanaWallet } from "@relayprotocol/relay-svm-wallet-adapter"; import { SendTransactionError } from "@solana/web3.js"; function getSolanaWallet(walletAddress, connection, signTransaction, payerKey) { return adaptSolanaWallet( walletAddress, RELAY_SOLANA_CHAIN_ID_NUMBER, connection, async (transaction, options) => { const signed = await signTransaction(transaction); try { const signature = await connection.sendTransaction(signed, { ...options, maxRetries: 5 }); return { signature }; } catch (error) { if (error instanceof SendTransactionError) { console.error( "Failed transaction logs:", error, await error.getLogs(connection) ); } throw error; } }, payerKey ); } // src/tron.ts import { adaptTronWallet } from "@relayprotocol/relay-tron-wallet-adapter"; function getTronWallet(walletAddress, tronWeb) { return adaptTronWallet(walletAddress, tronWeb); } // src/assets.ts var ASSET_LOGO_SRCS = { $MFER: "https://sdk-cdn.fun.xyz/images/mfer.png", AARBUSDCN: "https://sdk-cdn.fun.xyz/images/aarbusdcn.png", AAVE: "https://sdk-cdn.fun.xyz/images/aave.svg", AERO: "https://sdk-cdn.fun.xyz/images/aero.svg", APE: "https://sdk-cdn.fun.xyz/images/ape.svg", APOLWMATIC: "https://sdk-cdn.fun.xyz/images/apolwmatic.png", ARB: "https://sdk-cdn.fun.xyz/images/arb.svg", BEHYPE: "https://sdk-cdn.fun.xyz/images/behype.svg", BENTO: "https://sdk-cdn.fun.xyz/images/bento.png", BLERF: "https://sdk-cdn.fun.xyz/images/blerf.png", BRETT: "https://sdk-cdn.fun.xyz/images/brett.svg", BSHIB: "https://sdk-cdn.fun.xyz/images/bshib.png", BTC: "https://sdk-cdn.fun.xyz/images/btc.svg", CASH: "https://sdk-cdn.fun.xyz/images/cash.svg", CBBTC: "https://sdk-cdn.fun.xyz/images/cbbtc.svg", CBETH: "https://sdk-cdn.fun.xyz/images/cbeth.png", CRO: "https://sdk-cdn.fun.xyz/images/cro.svg", CRV: "https://sdk-cdn.fun.xyz/images/crv.svg", DAI: "https://sdk-cdn.fun.xyz/images/dai.svg", DEGEN: "https://sdk-cdn.fun.xyz/images/degen.svg", ETH: "https://sdk-cdn.fun.xyz/images/eth.svg", GMX: "https://sdk-cdn.fun.xyz/images/gmx.svg", GRT: "https://sdk-cdn.fun.xyz/images/grt.svg", HYPE: "https://sdk-cdn.fun.xyz/images/hype.svg", IMX: "https://sdk-cdn.fun.xyz/images/imx.svg", INJ: "https://sdk-cdn.fun.xyz/images/inj.svg", LDO: "https://sdk-cdn.fun.xyz/images/ldo.svg", LINK: "https://sdk-cdn.fun.xyz/images/link.png", LUCK: "https://sdk-cdn.fun.xyz/images/luck.png", MATIC: "https://sdk-cdn.fun.xyz/images/matic.svg", MFER: "https://sdk-cdn.fun.xyz/images/mfer.png", MKR: "https://sdk-cdn.fun.xyz/images/mkr.svg", MNT: "https://sdk-cdn.fun.xyz/images/mnt.svg", OP: "https://sdk-cdn.fun.xyz/images/optimism.svg", PENDLE: "https://sdk-cdn.fun.xyz/images/pendle.svg", POL: "https://sdk-cdn.fun.xyz/images/matic.svg", PYUSD: "https://sdk-cdn.fun.xyz/images/pyusd.svg", QNT: "https://sdk-cdn.fun.xyz/images/qnt.svg", RNDR: "https://sdk-cdn.fun.xyz/images/rndr.svg", ROOST: "https://sdk-cdn.fun.xyz/images/roost.png", SAND: "https://sdk-cdn.fun.xyz/images/sand.svg", SHIB: "https://sdk-cdn.fun.xyz/images/shib.svg", SNX: "https://sdk-cdn.fun.xyz/images/snx.svg", SOL: "https://sdk-cdn.fun.xyz/images/sol.svg", SUSDS: "https://sdk-cdn.fun.xyz/images/susds.svg", TYBG: "https://sdk-cdn.fun.xyz/images/tybg.png", UNI: "https://sdk-cdn.fun.xyz/images/uni.png", USDC: "https://sdk-cdn.fun.xyz/images/usdc.svg", "USDC.E": "https://sdk-cdn.fun.xyz/images/usdc.svg", USDBC: "https://sdk-cdn.fun.xyz/images/usdc.svg", USDE: "https://sdk-cdn.fun.xyz/images/usde.svg", WUSDE: "https://sdk-cdn.fun.xyz/images/usde.svg", EUSDE: "https://sdk-cdn.fun.xyz/images/eusde.svg", USDT: "https://sdk-cdn.fun.xyz/images/usdt.svg", "USD\u20AE0": "https://sdk-cdn.fun.xyz/images/usdt0.svg", USDT0: "https://sdk-cdn.fun.xyz/images/usdt0.svg", USDS: "https://sdk-cdn.fun.xyz/images/usds.svg", USDH: "https://sdk-cdn.fun.xyz/images/usdh.svg", USDG: "https://sdk-cdn.fun.xyz/images/usdg.svg", VRTX: "https://sdk-cdn.fun.xyz/images/vrtx.svg", WBTC: "https://sdk-cdn.fun.xyz/images/wbtc.svg", WEETH: "https://sdk-cdn.fun.xyz/images/weeth.png", WETH: "https://sdk-cdn.fun.xyz/images/weth.svg", WHYPE: "https://sdk-cdn.fun.xyz/images/whype.png", WSTETH: "https://sdk-cdn.fun.xyz/images/wsteth.png", TRUMP: "https://sdk-cdn.fun.xyz/images/trump.png", BNB: "https://sdk-cdn.fun.xyz/images/bsc.svg", WBNB: "https://sdk-cdn.fun.xyz/images/bsc.svg", BTCB: "https://sdk-cdn.fun.xyz/images/btc.svg", UBTC: "https://sdk-cdn.fun.xyz/images/btc.svg", BUSD: "https://sdk-cdn.fun.xyz/images/busd.svg", XAUT: "https://sdk-cdn.fun.xyz/images/xaut.png", ADA: "https://sdk-cdn.fun.xyz/images/ada.svg", XRP: "https://sdk-cdn.fun.xyz/images/xrp.svg", UDOGE: "https://sdk-cdn.fun.xyz/images/doge.svg", DOGE: "https://sdk-cdn.fun.xyz/images/doge.svg", LTC: "https://sdk-cdn.fun.xyz/images/ltc.svg", HNT: "https://sdk-cdn.fun.xyz/images/hnt.svg", COMP: "https://sdk-cdn.fun.xyz/images/comp.svg", PEPE: "https://sdk-cdn.fun.xyz/images/pepe.svg", LSTHYPE: "https://sdk-cdn.fun.xyz/images/lsthype.svg", HBUSDT: "https://sdk-cdn.fun.xyz/images/hbusdt.svg", WVLP: "https://sdk-cdn.fun.xyz/images/wvlp.svg", LIQUIDHYPE: "https://sdk-cdn.fun.xyz/images/liquidhype.svg", VHYPE: "https://sdk-cdn.fun.xyz/images/vhype.png", HBHYPE: "https://sdk-cdn.fun.xyz/images/hbhype.svg", MON: "https://sdk-cdn.fun.xyz/images/monad.svg", WMON: "https://sdk-cdn.fun.xyz/images/wmon.svg", AUSD: "https://sdk-cdn.fun.xyz/images/ausd.svg", SUSHI: "https://sdk-cdn.fun.xyz/images/sushi.svg", SKY: "https://sdk-cdn.fun.xyz/images/sky.svg", LIT: "https://sdk-cdn.fun.xyz/images/lit.svg", AZTEC: "https://sdk-cdn.fun.xyz/images/aztec.svg", U: "https://sdk-cdn.fun.xyz/images/u.png", PUSD: "https://sdk-cdn.fun.xyz/images/pusd.svg", KBTC: "https://sdk-cdn.fun.xyz/images/kbtc.svg", QQQX: "https://sdk-cdn.fun.xyz/images/qqqx.svg", SPYX: "https://sdk-cdn.fun.xyz/images/spyx.svg", WSPYX: "https://sdk-cdn.fun.xyz/images/spyx.svg", WQQQX: "https://sdk-cdn.fun.xyz/images/qqqx.svg", AAPLX: "https://sdk-cdn.fun.xyz/images/applx.svg", WAAPLX: "https://sdk-cdn.fun.xyz/images/applx.svg", GOOGLX: "https://sdk-cdn.fun.xyz/images/googlx.svg", WGOOGLX: "https://sdk-cdn.fun.xyz/images/googlx.svg", METAX: "https://sdk-cdn.fun.xyz/images/metax.svg", WMETAX: "https://sdk-cdn.fun.xyz/images/metax.svg", NVDAX: "https://sdk-cdn.fun.xyz/images/nvdax.svg", WNVDAX: "https://sdk-cdn.fun.xyz/images/nvdax.svg", TSLAX: "https://sdk-cdn.fun.xyz/images/tslax.svg", WTSLAX: "https://sdk-cdn.fun.xyz/images/tslax.svg", MSFTX: "https://sdk-cdn.fun.xyz/images/msftx.svg", WMSFTX: "https://sdk-cdn.fun.xyz/images/msftx.svg", AMZNX: "https://sdk-cdn.fun.xyz/images/amznx.svg", WAMZNX: "https://sdk-cdn.fun.xyz/images/amznx.svg" }; var FALLBACK_ASSET = "https://sdk-cdn.fun.xyz/images/dollar_circle.png"; function getAssetLogoSrc(symbol) { return ASSET_LOGO_SRCS[symbol.toUpperCase()] || FALLBACK_ASSET; } // src/dynamicRoutes/lighter.ts import { concat, encodeAbiParameters, encodeFunctionData as encodeFunctionData2, toFunctionSelector } from "viem"; import { mainnet as mainnet3 } from "viem/chains"; // src/dynamicRoutes/abi.ts var UNWRAP_AND_CALL_ABI = [ { name: "unwrapAndCall", type: "function", stateMutability: "nonpayable", inputs: [ { name: "target", type: "address" }, { name: "callData", type: "bytes" } ], outputs: [{ name: "returnData", type: "bytes" }] } ]; var VAULT_DEPOSITOR_ABI = [ { inputs: [ { internalType: "address", name: "initialOwner", type: "address" } ], stateMutability: "nonpayable", type: "constructor" }, { inputs: [ { internalType: "uint256", name: "amount", type: "uint256" }, { internalType: "uint256", name: "tickSize", type: "uint256" } ], name: "AmountBelowMinimumTick", type: "error" }, { inputs: [{ internalType: "bytes", name: "returnData", type: "bytes" }], name: "DepositFailed", type: "error" }, { inputs: [], name: "DustRefundFailed", type: "error" }, { inputs: [], name: "EmptyMethodSignature", type: "error" }, { inputs: [], name: "InsufficientETHAmount", type: "error" }, { inputs: [], name: "InsufficientTokenAmount", type: "error" }, { inputs: [{ internalType: "string", name: "reason", type: "string" }], name: "InvalidCalldata", type: "error" }, { inputs: [], name: "InvalidDustRecipient", type: "error" }, { inputs: [], name: "InvalidFunctionSelector", type: "error" }, { inputs: [], name: "InvalidTickSize", type: "error" }, { inputs: [], name: "InvalidVault", type: "error" }, { inputs: [], name: "NoETHInContract", type: "error" }, { inputs: [{ internalType: "address", name: "owner", type: "address" }], name: "OwnableInvalidOwner", type: "error" }, { inputs: [{ internalType: "address", name: "account", type: "address" }], name: "OwnableUnauthorizedAccount", type: "error" }, { inputs: [], name: "ReentrancyGuardReentrantCall", type: "error" }, { inputs: [{ internalType: "address", name: "token", type: "address" }], name: "SafeERC20FailedOperation", type: "error" }, { inputs: [ { internalType: "address", name: "vault", type: "address" }, { internalType: "bytes4", name: "selector", type: "bytes4" } ], name: "SelectorNotAllowed", type: "error" }, { inputs: [], name: "VaultAlreadyRegistered", type: "error" }, { inputs: [], name: "VaultDoesNotSupportNative", type: "error" }, { inputs: [], name: "VaultNotRegistered", type: "error" }, { inputs: [], name: "VaultNotRegisteredForDeposit", type: "error" }, { anonymous: false, inputs: [ { indexed: true, internalType: "address", name: "recipient", type: "address" }, { indexed: true, internalType: "address", name: "token", type: "address" }, { indexed: false, internalType: "uint256", name: "dust", type: "uint256" }, { indexed: false, internalType: "uint256", name: "originalAmount", type: "uint256" }, { indexed: false, internalType: "uint256", name: "depositedAmount", type: "uint256" } ], name: "DustRefunded", type: "event" }, { anonymous: false, inputs: [ { indexed: true, internalType: "address", name: "vault", type: "address" }, { indexed: true, internalType: "address", name: "token", type: "address" }, { indexed: false, internalType: "uint256", name: "amount", type: "uint256" }, { indexed: false, internalType: "bytes", name: "returnData", type: "bytes" } ], name: "FunMediatedDeposit", type: "event" }, { anonymous: false, inputs: [ { indexed: true, internalType: "address", name: "previousOwner", type: "address" }, { indexed: true, internalType: "address", name: "newOwner", type: "address" } ], name: "OwnershipTransferred", type: "event" }, { anonymous: false, inputs: [ { indexed: true, internalType: "address", name: "vault", type: "address" }, { indexed: true, internalType: "bytes4", name: "newSelector", type: "bytes4" } ], name: "SelectorUpdated", type: "event" }, { anonymous: false, inputs: [ { indexed: true, internalType: "address", name: "vault", type: "address" }, { indexed: false, internalType: "string", name: "methodSignature", type: "string" }, { indexed: false, internalType: "bool", name: "convertTo18Decimals", type: "bool" } ], name: "VaultRegistered", type: "event" }, { anonymous: false, inputs: [ { indexed: true, internalType: "address", name: "vault", type: "address" } ], name: "VaultRemoved", type: "event" }, { inputs: [], name: "AMOUNT_PLACEHOLDER", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function" }, { inputs: [], name: "AMOUNT_PLACEHOLDER_BYTES32", outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], stateMutability: "view", type: "function" }, { inputs: [], name: "NATIVE_TOKEN", outputs: [{ internalType: "address", name: "", type: "address" }], stateMutability: "view", type: "function" }, { inputs: [ { internalType: "uint256", name: "amount", type: "uint256" }, { internalType: "uint256", name: "tickSize", type: "uint256" } ], name: "calculateTickRounding", outputs: [ { internalType: "uint256", name: "roundedAmount", type: "uint256" }, { internalType: "uint256", name: "dust", type: "uint256" } ], stateMutability: "pure", type: "function" }, { inputs: [ { internalType: "address", name: "token", type: "address" }, { internalType: "address", name: "vault", type: "address" }, { internalType: "bytes", name: "callData", type: "bytes" }, { internalType: "uint256", name: "minAmountOut", type: "uint256" } ], name: "deposit", outputs: [{ internalType: "bytes", name: "returnData", type: "bytes" }], stateMutability: "nonpayable", type: "function" }, { inputs: [ { internalType: "address", name: "token", type: "address" }, { internalType: "address", name: "vault", type: "address" }, { internalType: "bytes", name: "callData", type: "bytes" }, { internalType: "uint256", name: "minAmountOut", type: "uint256" }, { internalType: "uint256", name: "tickSize", type: "uint256" }, { internalType: "address", name: "dustRecipient", type: "address" } ], name: "depositWithTick", outputs: [{ internalType: "bytes", name: "returnData", type: "bytes" }], stateMutability: "nonpayable", type: "function" }, { inputs: [{ internalType: "address", name: "vault", type: "address" }], name: "getAllowedSelector", outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], stateMutability: "view", type: "function" }, { inputs: [{ internalType: "uint256", name: "tickSize", type: "uint256" }], name: "getMinimumDepositForTick", outputs: [{ internalType: "uint256", name: "minAmount", type: "uint256" }], stateMutability: "pure", type: "function" }, { inputs: [{ internalType: "address", name: "vault", type: "address" }], name: "getVaultConfig", outputs: [ { components: [ { internalType: "bool", name: "isRegistered", type: "bool" }, { internalType: "bool", name: "convertTo18Decimals", type: "bool" }, { internalType: "bool", name: "allowsNative", type: "bool" }, { internalType: "bytes4", name: "allowedSelector", type: "bytes4" } ], internalType: "struct VaultConfigLib.VaultConfig", name: "config", type: "tuple" } ], stateMutability: "view", type: "function" }, { inputs: [{ internalType: "address", name: "vault", type: "address" }], name: "isVaultRegistered", outputs: [{ internalType: "bool", name: "", type: "bool" }], stateMutability: "view", type: "function" }, { inputs: [], name: "owner", outputs: [{ internalType: "address", name: "", type: "address" }], stateMutability: "view", type: "function" }, { inputs: [ { internalType: "address", name: "vault", type: "address" }, { internalType: "string", name: "vaultABI", type: "string" }, { internalType: "bytes4", name: "allowedFunctionSelector", type: "bytes4" }, { internalType: "bool", name: "convertTo18Decimals", type: "bool" }, { internalType: "bool", name: "allowsNative", type: "bool" } ], name: "registerVault", outputs: [], stateMutability: "nonpayable", type: "function" }, { inputs: [{ internalType: "address", name: "vault", type: "address" }], name: "removeVault", outputs: [], stateMutability: "nonpayable", type: "function" }, { inputs: [], name: "renounceOwnership", outputs: [], stateMutability: "nonpayable", type: "function" }, { inputs: [{ internalType: "address", name: "newOwner", type: "address" }], name: "transferOwnership", outputs: [], stateMutability: "nonpayable", type: "function" }, { inputs: [ { internalType: "address", name: "vault", type: "address" }, { internalType: "bytes4", name: "newSelector", type: "bytes4" } ], name: "updateAllowedSelector", outputs: [], stateMutability: "nonpayable", type: "function" }, { inputs: [ { internalType: "uint256", name: "amount", type: "uint256" }, { internalType: "uint256", name: "tickSize", type: "uint256" } ], name: "validateAmountForTick", outputs: [ { internalType: "bool", name: "isValid", type: "bool" }, { internalType: "uint256", name: "roundedAmount", type: "uint256" }, { internalType: "uint256", name: "dust", type: "uint256" } ], stateMutability: "pure", type: "function" }, { inputs: [{ internalType: "address", name: "vault", type: "address" }], name: "vaultAllowsNative", outputs: [{ internalType: "bool", name: "", type: "bool" }], stateMutability: "view", type: "function" }, { inputs: [{ internalType: "address", name: "", type: "address" }], name: "vaultConfigs", outputs: [{ internalType: "uint40", name: "", type: "uint40" }], stateMutability: "view", type: "function" }, { inputs: [{ internalType: "address", name: "vault", type: "address" }], name: "vaultRequires18Decimals", outputs: [{ internalType: "bool", name: "", type: "bool" }], stateMutability: "view", type: "function" }, { stateMutability: "payable", type: "receive" } ]; // src/dynamicRoutes/consts.ts import { getAddress } from "viem"; import { mainnet } from "viem/chains"; import { erc20Abi } from "viem"; var AMOUNT_PLACEHOLDER = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffdeadbeefn; var tokenAddresses = { WETH: { [mainnet.id]: getAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") }, USDC: { [mainnet.id]: getAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48") }, LIT: { [mainnet.id]: getAddress("0x232CE3bd40fCd6f80f3d55A522d03f25Df784Ee2") }, LINK: { [mainnet.id]: getAddress("0x514910771AF9Ca656af840dff83E8264EcF986CA") }, UNI: { [mainnet.id]: getAddress("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984") }, AAVE: { [mainnet.id]: getAddress("0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9") }, SKY: { [mainnet.id]: getAddress("0x56072C95FAA701256059aa122697B133aDEd9279") }, LDO: { [mainnet.id]: getAddress("0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32") }, AZTEC: { [mainnet.id]: getAddress("0xA27EC0006e59f245217Ff08CD52A7E8b169E62D2") } }; var UNWRAP_AND_CALL_ADDRESS = { [mainnet.id]: getAddress("0x177591f2F4DcC3a47F768f6533eC6Edf564d6927") }; var VAULT_DEPOSITOR_ADDRESS = { [mainnet.id]: getAddress("0x40b72bB73B1E9380629B205e7880Fa409ae7fcc9") }; var LIGHTER_DEPOSIT_ADDRESS = getAddress( "0x3b4d794a66304f130a4db8f2551b0070dfcf5ca7" ); var MATCH_ALL_CONDITION = "*"; // src/dynamicRoutes/utils.ts import { erc20Abi as ERC20_ABI } from "viem"; import { mainnet as mainnet2 } from "viem/chains"; var createPath = (config) => { return config; }; var createRoute = (config) => { const getPathById = (pathId) => { const path = config.paths[pathId]; if (!path) { return null; } return path; }; return { id: config.id, config, getPathById }; }; var resolveBadge = (rule) => { if ("badge" in rule.use) { return rule.use.badge; } return void 0; }; var resolveForceBridge = (rule) => { if ("bridgeOverride" in rule.use) { return rule.use.bridgeOverride; } return void 0; }; var initDynamicRouting = (dynamicRoutes, dynamicRoutingConfig) => { const indexedRoutes = indexBy(dynamicRoutes, (route) => route.id); const indexedDynamicRoutingConfig = dynamicRoutingConfig.reduce( (acc, routeConfig) => { const route = indexedRoutes[routeConfig.routeId]; if (!route) { return acc; } const { rules } = routeConfig; const indexedRules = indexBy([...rules], (rule) => { if (rule.when === MATCH_ALL_CONDITION) { return MATCH_ALL_CONDITION; } return `${rule.when.chainId}-${rule.when.tokenAddress}`.toLowerCase(); }); const resolveRule = (rule) => { const path = route.getPathById(rule.use.path); if (!path) { return null; } const badge = resolveBadge(rule); const bridgeOverride = resolveForceBridge(rule); return { path, badge, bridgeOverride }; }; const findPath = ({ chainId, tokenAddress }) => { const specificRule = indexedRules[`${chainId}-${tokenAddress}`.toLowerCase()]; if (specificRule) { return resolveRule(specificRule); } const anyChainSpecificTokenAddress = indexedRules[`${MATCH_ALL_CONDITION}-${tokenAddress}`.toLowerCase()]; if (anyChainSpecificTokenAddress) { return resolveRule(anyChainSpecificTokenAddress); } const anyTokenAddressSpecificChain = indexedRules[`${chainId}-${MATCH_ALL_CONDITION}`.toLowerCase()]; if (anyTokenAddressSpecificChain) { return resolveRule(anyTokenAddressSpecificChain); } const wildcardRule = indexedRules[MATCH_ALL_CONDITION]; if (wildcardRule) { return resolveRule(wildcardRule); } return null; }; acc[routeConfig.routeId] = { route, rules, findPath }; return acc; }, {} ); return indexedDynamicRoutingConfig; }; var MAX_APPROVAL = "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; var getApprovalCalldata = ({ tokenAddress, spenderAddress, amount }) => { return { contractAbi: ERC20_ABI, contractAddress: tokenAddress, functionName: "approve", functionArgs: [spenderAddress, amount] }; }; var getResetApprovalCalldata = ({ tokenAddress, spenderAddress }) => { return getApprovalCalldata({ tokenAddress, spenderAddress, amount: "0" }); }; var RESET_APPROVAL_TOKENS = [tokenAddresses.LDO[mainnet2.id]].map( (address) => address.toLowerCase() ); var shouldResetApproval = (tokenAddress) => { return RESET_APPROVAL_TOKENS.includes(tokenAddress.toLowerCase()); }; // src/dynamicRoutes/lighter.ts var NATIVE_TOKEN = FUNKIT_NATIVE_TOKEN; var RELAY_LIGHTER_CHAIN_ID2 = 3586256; var RELAY_LIGHTER_ETH_SPOT_ADDRESS = "0x0000000000000000000000000000000000000001"; var RELAY_LIGHTER_USDC_PERPS_ADDRESS = "0x0000000000000000000000000000000000000000"; var RELAY_LIGHTER_USDC_SPOT_ADDRESS = "0x0000000000000000000000000000000000000003"; var TICK_SIZE_FOR_ASSET_INDEX = { [3 /* USDC */]: BigInt(1), [1 /* ETH */]: BigInt(10 ** 10), [2 /* LIT */]: BigInt(10 ** 10), [5 /* LINK */]: BigInt(10 ** 10), [6 /* UNI */]: BigInt(10 ** 10), [7 /* AAVE */]: BigInt(10 ** 10), [8 /* SKY */]: BigInt(10 ** 10), [9 /* LDO */]: BigInt(10 ** 10), [10 /* AZTEC */]: BigInt(10 ** 10) }; var DEPOSIT_TOKEN_FOR_ASSET_INDEX = { [3 /* USDC */]: tokenAddresses.USDC[mainnet3.id], [1 /* ETH */]: NATIVE_TOKEN, [2 /* LIT */]: tokenAddresses.LIT[mainnet3.id], [5 /* LINK */]: tokenAddresses.LINK[mainnet3.id], [6 /* UNI */]: tokenAddresses.UNI[mainnet3.id], [7 /* AAVE */]: tokenAddresses.AAVE[mainnet3.id], [8 /* SKY */]: tokenAddresses.SKY[mainnet3.id], [9 /* LDO */]: tokenAddresses.LDO[mainnet3.id], [10 /* AZTEC */]: tokenAddresses.AZTEC[mainnet3.id] }; var USDC_PERPS_SYMBOL = "USDC (Perps)"; var USDC_SPOT_SYMBOL = "USDC (Spot)"; var ETH_SPOT_SYMBOL = "ETH (Spot)"; var LINK_SPOT_SYMBOL = "LINK (Spot)"; var UNI_SPOT_SYMBOL = "UNI (Spot)"; var AAVE_SPOT_SYMBOL = "AAVE (Spot)"; var SKY_SPOT_SYMBOL = "SKY (Spot)"; var LDO_SPOT_SYMBOL = "LDO (Spot)"; var LIT_SPOT_SYMBOL = "LIT (Spot)"; var AZTEC_SPOT_SYMBOL = "AZTEC (Spot)"; var generateLighterMainnetDepositActions = ({ address, assetIndex, routeType }) => { const depositSelector = toFunctionSelector( "deposit(address,uint16,uint8,uint256)" ); const encodedLighterParams = encodeAbiPara