UNPKG

@paxoslabs/earn-sdk

Version:
1,030 lines (1,022 loc) 32.2 kB
import { getAssetSlippage } from './chunk-3K72Y6ME.mjs'; import { prepareBridgeTransactionData } from './chunk-EYR4YMSX.mjs'; export { getBridgeFee, getDepositExchangeRate, getWithdrawExchangeRate, isDepositSpendApproved, isWithdrawalSpendApproved, prepareBridgeTransactionData } from './chunk-EYR4YMSX.mjs'; import { getRateInQuoteWithAssetDecimals, TellerAbi, getClient, getRateInQuoteAndSharesAndWantAssetDecimals, BoringVaultAbi } from './chunk-SBKCBPE3.mjs'; export { getVaultByKey } from './chunk-DHTKSLVZ.mjs'; import { toChainId } from './chunk-4URQP4CS.mjs'; import { calculateDeadline } from './chunk-FLFXJYNL.mjs'; import { tryCatch, WAD } from './chunk-MHZTLW64.mjs'; import { DEFAULT_DEPOSIT_SLIPPAGE, findVaultByConfig, APIError, fetchSupportedAssets, DEFAULT_APPROVAL_AMOUNT, DEFAULT_DEADLINE, ATOMIC_QUEUE_CONTRACT_ADDRESS, DEFAULT_WITHDRAW_SLIPPAGE } from './chunk-NTRZGVUA.mjs'; export { APIError, fetchSupportedAssets, fetchVaults, findVaultByConfig, getAssetsFromCache, getCache, getVaultsFromCache, getWithdrawSupportedAssets, initializeCache, refreshVaultCache } from './chunk-NTRZGVUA.mjs'; import { parseUnits, erc20Abi, hexToSignature, encodeFunctionData } from 'viem'; // src/vaults/deposit/utils.ts var calculateMinimumMint = (depositAmount, rate, vaultTokenDecimals, slippage) => { const slippageValue = slippage ?? DEFAULT_DEPOSIT_SLIPPAGE; const slippageAsBigInt = BigInt(slippageValue) * WAD.bigint / BigInt(1e4); const minimumMint = depositAmount * WAD.bigint / rate; const slippageAmount = minimumMint * slippageAsBigInt / WAD.bigint; if (vaultTokenDecimals > 18) { return (minimumMint - slippageAmount) * BigInt(10) ** (BigInt(vaultTokenDecimals) - BigInt(18)); } return (minimumMint - slippageAmount) / BigInt(10) ** (BigInt(18) - BigInt(vaultTokenDecimals)); }; // src/vaults/deposit/deposit.ts async function prepareDepositTransactionData(params) { const { yieldType, depositToken, depositAmount, chainId, slippage = DEFAULT_DEPOSIT_SLIPPAGE } = params; try { const normalizedChainId = toChainId(chainId); let vault; try { vault = await findVaultByConfig({ depositTokenAddress: depositToken, yieldType, chainId: normalizedChainId }); } catch (error) { throw new APIError( `Failed to resolve vault for token ${depositToken} with yield type ${yieldType} on chain ${normalizedChainId}: ${error instanceof Error ? error.message : "Unknown error"}`, { endpoint: "prepareDepositTransactionData", cause: error } ); } if (!vault) { throw new APIError( `No vault found for token address ${depositToken} with yield type '${yieldType}' on chain ${normalizedChainId}. This combination may not be supported.`, { endpoint: "prepareDepositTransactionData" } ); } let asset = null; const assets = await fetchSupportedAssets({ address: depositToken }); if (assets.length > 0) { asset = assets.find((a) => a.supportedChains.includes(normalizedChainId)) || assets[0] || null; } if (!asset) { throw new APIError( `Asset metadata not found for token ${depositToken} on chain ${normalizedChainId}`, { endpoint: "prepareDepositTransactionData" } ); } const tellerAddress = vault.Nucleus.tellerAddressId; const accountantAddress = vault.Nucleus.accountantAddressId; const depositAssetAddress = asset.address; const [depositAssetDecimalsResult, rateInQuoteResult] = await getRateInQuoteWithAssetDecimals({ assetAddress: depositAssetAddress, accountantAddress, chainId: normalizedChainId }); if (depositAssetDecimalsResult.status === "failure") { throw new APIError( `Failed to get asset decimals: ${depositAssetDecimalsResult.error?.message || "Unknown error"}`, { endpoint: "prepareDepositTransactionData", cause: depositAssetDecimalsResult.error } ); } if (rateInQuoteResult.status === "failure") { throw new APIError( `Failed to get exchange rate: ${rateInQuoteResult.error?.message || "Unknown error"}`, { endpoint: "prepareDepositTransactionData", cause: rateInQuoteResult.error } ); } const depositAmountAsBigInt = parseUnits(depositAmount, asset.decimals); const vaultSharesAssets = await fetchSupportedAssets({ address: vault.Nucleus.boringVaultAddressId }); if (vaultSharesAssets.length === 0) { throw new APIError( `Vault shares token not found in supported assets: ${vault.Nucleus.boringVaultAddressId}`, { endpoint: "prepareDepositTransactionData" } ); } const minimumMint = calculateMinimumMint( depositAmountAsBigInt, rateInQuoteResult.result, vaultSharesAssets[0].decimals, slippage ); return { abi: TellerAbi, address: tellerAddress, functionName: "deposit", args: [depositAssetAddress, depositAmountAsBigInt, minimumMint], chainId: normalizedChainId }; } catch (error) { if (error instanceof APIError) { throw error; } throw new APIError( `Failed to prepare deposit transaction: ${error instanceof Error ? error.message : String(error)}`, { endpoint: "prepareDepositTransactionData", cause: error } ); } } async function prepareApproveDepositToken(params) { const { depositToken, boringVaultAddress, depositAmount } = params; try { let decimals = 18; const assets = await fetchSupportedAssets({ address: depositToken }); if (assets.length > 0) { decimals = assets[0].decimals; } const depositAmountAsBigInt = depositAmount ? parseUnits(depositAmount, decimals) : DEFAULT_APPROVAL_AMOUNT; return { abi: erc20Abi, address: depositToken, functionName: "approve", args: [boringVaultAddress, depositAmountAsBigInt] }; } catch (error) { if (error instanceof APIError) { throw error; } throw new APIError( `Failed to prepare approval transaction: ${error instanceof Error ? error.message : String(error)}`, { endpoint: "prepareApproveDepositToken", cause: error } ); } } // src/contracts/erc2612-abi.ts var erc2612Abi = [ // Standard ERC20 functions (subset needed for permit flow) { constant: true, inputs: [{ name: "_owner", type: "address" }], name: "nonces", outputs: [{ name: "", type: "uint256" }], type: "function" }, { constant: true, inputs: [], name: "DOMAIN_SEPARATOR", outputs: [{ name: "", type: "bytes32" }], type: "function" }, { constant: false, inputs: [ { name: "owner", type: "address" }, { name: "spender", type: "address" }, { name: "value", type: "uint256" }, { name: "deadline", type: "uint256" }, { name: "v", type: "uint8" }, { name: "r", type: "bytes32" }, { name: "s", type: "bytes32" } ], name: "permit", outputs: [], type: "function" }, { constant: true, inputs: [], name: "name", outputs: [{ name: "", type: "string" }], type: "function" }, { constant: true, inputs: [], name: "version", outputs: [{ name: "", type: "string" }], type: "function" } ]; // src/vaults/deposit/deposit-with-permit.ts var PERMIT_TYPES = { Permit: [ { name: "owner", type: "address" }, { name: "spender", type: "address" }, { name: "value", type: "uint256" }, { name: "nonce", type: "uint256" }, { name: "deadline", type: "uint256" } ] }; async function prepareDepositPermitSignature(params) { const { yieldType, depositToken, depositAmount, recipientAddress, chainId, deadline } = params; try { const normalizedChainId = toChainId(chainId); let vault; try { vault = await findVaultByConfig({ depositTokenAddress: depositToken, yieldType, chainId: normalizedChainId }); } catch (error) { throw new APIError( `Failed to resolve vault for token ${depositToken} with yield type ${yieldType} on chain ${normalizedChainId}: ${error instanceof Error ? error.message : "Unknown error"}`, { endpoint: "prepareDepositPermitSignature", cause: error } ); } if (!vault) { throw new APIError( `No vault found for token address ${depositToken} with yield type '${yieldType}' on chain ${normalizedChainId}. This combination may not be supported.`, { endpoint: "prepareDepositPermitSignature" } ); } const tellerAddress = vault.Nucleus.tellerAddressId; const client = await getClient(normalizedChainId); let tokenName; let tokenVersion; let nonce; try { const [nameResult, versionResult, nonceResult] = await Promise.allSettled([ client.readContract({ address: depositToken, abi: erc2612Abi, functionName: "name" }), client.readContract({ address: depositToken, abi: erc2612Abi, functionName: "version" }), client.readContract({ address: depositToken, abi: erc2612Abi, functionName: "nonces", args: [recipientAddress] }) ]); if (nameResult.status === "fulfilled") { tokenName = nameResult.value; } else { throw new APIError( `Failed to read token name from ${depositToken}`, { endpoint: "prepareDepositPermitSignature", cause: nameResult.reason } ); } if (versionResult.status === "fulfilled") { tokenVersion = versionResult.value; } else { tokenVersion = "1"; } if (nonceResult.status === "fulfilled") { nonce = nonceResult.value; } else { throw new APIError( `Token ${depositToken} does not support EIP-2612 permit. Missing required function: nonces()`, { endpoint: "prepareDepositPermitSignature", cause: nonceResult.reason } ); } } catch (error) { if (error instanceof APIError) { throw error; } throw new APIError( `Failed to read token metadata: ${error instanceof Error ? error.message : "Unknown error"}`, { endpoint: "prepareDepositPermitSignature", cause: error } ); } const permitDeadline = deadline ?? BigInt(Math.floor(Date.now() / 1e3) + 3600); const assets = await fetchSupportedAssets({ address: depositToken }); if (assets.length === 0) { throw new APIError( `Asset metadata not found for token ${depositToken}`, { endpoint: "prepareDepositPermitSignature" } ); } const asset = assets[0]; const value = parseUnits(depositAmount, asset.decimals); const domain = { name: tokenName, version: tokenVersion, chainId: normalizedChainId, verifyingContract: depositToken }; const message = { owner: recipientAddress, spender: tellerAddress, value, nonce, deadline: permitDeadline }; return { domain, types: PERMIT_TYPES, message, primaryType: "Permit" }; } catch (error) { if (error instanceof APIError) { throw error; } throw new APIError( `Failed to prepare permit signature: ${error instanceof Error ? error.message : String(error)}`, { endpoint: "prepareDepositPermitSignature", cause: error } ); } } function parsePermitSignature(signature) { try { const parsed = hexToSignature(signature); let v; if (parsed.v !== void 0) { v = Number(parsed.v); } else if (parsed.yParity !== void 0) { v = parsed.yParity + 27; } else { v = 27; } return { v, r: parsed.r, s: parsed.s }; } catch (error) { throw new APIError( `Invalid permit signature format. Expected hex string but received: ${signature}. ${error instanceof Error ? error.message : "Unknown error"}`, { endpoint: "parsePermitSignature", cause: error } ); } } async function prepareDepositWithPermitTransactionData(params) { const { yieldType, depositToken, depositAmount, chainId, signature, deadline, slippage = DEFAULT_DEPOSIT_SLIPPAGE } = params; try { const { v, r, s } = parsePermitSignature(signature); if (slippage < 0 || slippage > 1e4) { throw new APIError( `Invalid slippage value: ${slippage}. Slippage must be between 0 and 10000 basis points.`, { endpoint: "prepareDepositWithPermitTransactionData" } ); } const normalizedChainId = toChainId(chainId); let vault; try { vault = await findVaultByConfig({ depositTokenAddress: depositToken, yieldType, chainId: normalizedChainId }); } catch (error) { throw new APIError( `Failed to resolve vault for token ${depositToken} with yield type ${yieldType} on chain ${normalizedChainId}: ${error instanceof Error ? error.message : "Unknown error"}`, { endpoint: "prepareDepositWithPermitTransactionData", cause: error } ); } if (!vault) { throw new APIError( `No vault found for token address ${depositToken} with yield type '${yieldType}' on chain ${normalizedChainId}. This combination may not be supported.`, { endpoint: "prepareDepositWithPermitTransactionData" } ); } let asset = null; const assets = await fetchSupportedAssets({ address: depositToken }); if (assets.length > 0) { asset = assets.find((a) => a.supportedChains.includes(normalizedChainId)) || assets[0] || null; } if (!asset) { throw new APIError( `Asset metadata not found for token ${depositToken} on chain ${normalizedChainId}`, { endpoint: "prepareDepositWithPermitTransactionData" } ); } if (!asset.supportedChains || !asset.supportedChains.includes(normalizedChainId)) { throw new APIError( `Token ${asset.symbol || depositToken} not supported on chain ${normalizedChainId}`, { endpoint: "prepareDepositWithPermitTransactionData" } ); } const tellerAddress = vault.Nucleus.tellerAddressId; const accountantAddress = vault.Nucleus.accountantAddressId; const depositAssetAddress = asset.address; const [depositAssetDecimalsResult, rateInQuoteResult] = await getRateInQuoteWithAssetDecimals({ assetAddress: depositAssetAddress, accountantAddress, chainId: normalizedChainId }); if (depositAssetDecimalsResult.status === "failure") { throw new APIError( `Failed to get asset decimals: ${depositAssetDecimalsResult.error?.message || "Unknown error"}`, { endpoint: "prepareDepositWithPermitTransactionData", cause: depositAssetDecimalsResult.error } ); } if (rateInQuoteResult.status === "failure") { throw new APIError( `Failed to get exchange rate: ${rateInQuoteResult.error?.message || "Unknown error"}`, { endpoint: "prepareDepositWithPermitTransactionData", cause: rateInQuoteResult.error } ); } const depositAmountAsBigInt = parseUnits(depositAmount, asset.decimals); const vaultSharesAssets = await fetchSupportedAssets({ address: vault.Nucleus.boringVaultAddressId }); if (vaultSharesAssets.length === 0) { throw new APIError( `Vault shares token not found in supported assets: ${vault.Nucleus.boringVaultAddressId}`, { endpoint: "prepareDepositWithPermitTransactionData" } ); } const minimumMint = calculateMinimumMint( depositAmountAsBigInt, rateInQuoteResult.result, vaultSharesAssets[0].decimals, slippage ); const encodedData = encodeFunctionData({ abi: TellerAbi, functionName: "depositWithPermit", args: [ depositAssetAddress, depositAmountAsBigInt, minimumMint, deadline, v, r, s ] }); return { data: encodedData, address: tellerAddress, chainId: normalizedChainId }; } catch (error) { if (error instanceof APIError) { throw error; } throw new APIError( `Failed to prepare deposit with permit transaction: ${error instanceof Error ? error.message : String(error)}`, { endpoint: "prepareDepositWithPermitTransactionData", cause: error } ); } } // src/contracts/atomic-queue-abi.ts var AtomicQueueAbi = [ { type: "function", name: "getUserAtomicRequest", inputs: [ { name: "user", type: "address", internalType: "address" }, { name: "offer", type: "address", internalType: "contract ERC20" }, { name: "want", type: "address", internalType: "contract ERC20" } ], outputs: [ { name: "", type: "tuple", internalType: "struct AtomicQueue.AtomicRequest", components: [ { name: "deadline", type: "uint64", internalType: "uint64" }, { name: "atomicPrice", type: "uint88", internalType: "uint88" }, { name: "offerAmount", type: "uint96", internalType: "uint96" }, { name: "inSolve", type: "bool", internalType: "bool" } ] } ], stateMutability: "view" }, { type: "function", name: "isAtomicRequestValid", inputs: [ { name: "offer", type: "address", internalType: "contract ERC20" }, { name: "user", type: "address", internalType: "address" }, { name: "userRequest", type: "tuple", internalType: "struct AtomicQueue.AtomicRequest", components: [ { name: "deadline", type: "uint64", internalType: "uint64" }, { name: "atomicPrice", type: "uint88", internalType: "uint88" }, { name: "offerAmount", type: "uint96", internalType: "uint96" }, { name: "inSolve", type: "bool", internalType: "bool" } ] } ], outputs: [{ name: "", type: "bool", internalType: "bool" }], stateMutability: "view" }, { type: "function", name: "solve", inputs: [ { name: "offer", type: "address", internalType: "contract ERC20" }, { name: "want", type: "address", internalType: "contract ERC20" }, { name: "users", type: "address[]", internalType: "address[]" }, { name: "runData", type: "bytes", internalType: "bytes" }, { name: "solver", type: "address", internalType: "address" } ], outputs: [], stateMutability: "nonpayable" }, { type: "function", name: "updateAtomicRequest", inputs: [ { name: "offer", type: "address", internalType: "contract ERC20" }, { name: "want", type: "address", internalType: "contract ERC20" }, { name: "userRequest", type: "tuple", internalType: "struct AtomicQueue.AtomicRequest", components: [ { name: "deadline", type: "uint64", internalType: "uint64" }, { name: "atomicPrice", type: "uint88", internalType: "uint88" }, { name: "offerAmount", type: "uint96", internalType: "uint96" }, { name: "inSolve", type: "bool", internalType: "bool" } ] } ], outputs: [], stateMutability: "nonpayable" }, { type: "function", name: "userAtomicRequest", inputs: [ { name: "", type: "address", internalType: "address" }, { name: "", type: "address", internalType: "contract ERC20" }, { name: "", type: "address", internalType: "contract ERC20" } ], outputs: [ { name: "deadline", type: "uint64", internalType: "uint64" }, { name: "atomicPrice", type: "uint88", internalType: "uint88" }, { name: "offerAmount", type: "uint96", internalType: "uint96" }, { name: "inSolve", type: "bool", internalType: "bool" } ], stateMutability: "view" }, { type: "function", name: "viewSolveMetaData", inputs: [ { name: "offer", type: "address", internalType: "contract ERC20" }, { name: "want", type: "address", internalType: "contract ERC20" }, { name: "users", type: "address[]", internalType: "address[]" } ], outputs: [ { name: "metaData", type: "tuple[]", internalType: "struct AtomicQueue.SolveMetaData[]", components: [ { name: "user", type: "address", internalType: "address" }, { name: "flags", type: "uint8", internalType: "uint8" }, { name: "assetsToOffer", type: "uint256", internalType: "uint256" }, { name: "assetsForWant", type: "uint256", internalType: "uint256" } ] }, { name: "totalAssetsForWant", type: "uint256", internalType: "uint256" }, { name: "totalAssetsToOffer", type: "uint256", internalType: "uint256" } ], stateMutability: "view" }, { type: "event", name: "AtomicRequestFulfilled", inputs: [ { name: "user", type: "address", indexed: false, internalType: "address" }, { name: "offerToken", type: "address", indexed: false, internalType: "address" }, { name: "wantToken", type: "address", indexed: false, internalType: "address" }, { name: "offerAmountSpent", type: "uint256", indexed: false, internalType: "uint256" }, { name: "wantAmountReceived", type: "uint256", indexed: false, internalType: "uint256" }, { name: "timestamp", type: "uint256", indexed: false, internalType: "uint256" } ], anonymous: false }, { type: "event", name: "AtomicRequestUpdated", inputs: [ { name: "user", type: "address", indexed: false, internalType: "address" }, { name: "offerToken", type: "address", indexed: false, internalType: "address" }, { name: "wantToken", type: "address", indexed: false, internalType: "address" }, { name: "amount", type: "uint256", indexed: false, internalType: "uint256" }, { name: "deadline", type: "uint256", indexed: false, internalType: "uint256" }, { name: "minPrice", type: "uint256", indexed: false, internalType: "uint256" }, { name: "timestamp", type: "uint256", indexed: false, internalType: "uint256" } ], anonymous: false }, { type: "error", name: "AtomicQueue__RequestDeadlineExceeded", inputs: [{ name: "user", type: "address", internalType: "address" }] }, { type: "error", name: "AtomicQueue__UserNotInSolve", inputs: [{ name: "user", type: "address", internalType: "address" }] }, { type: "error", name: "AtomicQueue__UserRepeated", inputs: [{ name: "user", type: "address", internalType: "address" }] }, { type: "error", name: "AtomicQueue__ZeroOfferAmount", inputs: [{ name: "user", type: "address", internalType: "address" }] } ]; // src/vaults/withdraw/utils.ts var prepareUserRequest = (offerAmount, atomicPrice, deadline) => { const deadlineTimeStamp = calculateDeadline(deadline); return { deadline: deadlineTimeStamp, atomicPrice, offerAmount, inSolve: false }; }; var calculateAtomicPrice = (rateInQuote, wantAssetDecimals, slippage) => { const wantPrecision = BigInt(10 ** wantAssetDecimals); const slippageAsBigInt = BigInt(slippage) * wantPrecision / BigInt(1e4); return rateInQuote * (wantPrecision - slippageAsBigInt) / wantPrecision; }; // src/vaults/withdraw/withdraw.ts var prepareWithdrawTransactionData = async ({ vault, wantAsset, chainId, offerAmount, deadline = DEFAULT_DEADLINE, slippage }) => { try { const normalizedChainId = toChainId(chainId); if (vault.chainId !== normalizedChainId) { throw new APIError( `Vault chain mismatch: vault is on chain ${vault.chainId}, requested chain ${normalizedChainId}`, { endpoint: "prepareWithdrawTransactionData" } ); } if (!wantAsset.supportedChains.includes(normalizedChainId)) { throw new APIError( `Want asset ${wantAsset.symbol} is not supported on chain ${normalizedChainId}. Supported chains: ${wantAsset.supportedChains.join(", ")}`, { endpoint: "prepareWithdrawTransactionData" } ); } if (!vault.Nucleus.boringVaultAddressId) { throw new APIError( `BoringVault contract address not configured for vault ${vault.id}`, { endpoint: "prepareWithdrawTransactionData" } ); } if (!vault.Nucleus.accountantAddressId) { throw new APIError( `Accountant contract address not configured for vault ${vault.id}`, { endpoint: "prepareWithdrawTransactionData" } ); } const boringVaultAddress = vault.Nucleus.boringVaultAddressId; const accountantAddress = vault.Nucleus.accountantAddressId; const wantAssetAddress = wantAsset.address; const vaultSharesAssets = await fetchSupportedAssets({ address: boringVaultAddress }); if (vaultSharesAssets.length === 0) { throw new APIError( `Vault shares token not found in supported assets: ${boringVaultAddress}`, { endpoint: "prepareWithdrawTransactionData" } ); } const vaultSharesDecimals = vaultSharesAssets[0].decimals; const rateInQuote = await getRateInQuoteAndSharesAndWantAssetDecimals({ sharesAssetAddress: boringVaultAddress, wantAssetAddress, accountantAddress, chainId: normalizedChainId }); if (rateInQuote[2]?.status === "failure") { throw new APIError( `Failed to get exchange rate: ${rateInQuote[2].error.message}`, { endpoint: "prepareWithdrawTransactionData", cause: rateInQuote[2].error } ); } const formattedOfferAmount = parseUnits(offerAmount, vaultSharesDecimals); const { data: solverSlippage, error: solverSlippageError, success: solverSlippageSuccess } = await tryCatch( getAssetSlippage(normalizedChainId, boringVaultAddress, wantAssetAddress) ); if (!solverSlippageSuccess) { throw new APIError( `Failed to get solver slippage: ${solverSlippageError.message}`, { endpoint: "prepareWithdrawTransactionData", cause: solverSlippageError } ); } const effectiveSlippage = slippage ?? solverSlippage; const atomicPrice = calculateAtomicPrice( rateInQuote[2].result, // rateInQuote bigint wantAsset.decimals, // Want asset decimals from API effectiveSlippage ); const userRequest = prepareUserRequest( formattedOfferAmount, atomicPrice, deadline ); return { abi: AtomicQueueAbi, address: ATOMIC_QUEUE_CONTRACT_ADDRESS, functionName: "updateAtomicRequest", args: [boringVaultAddress, wantAssetAddress, userRequest], chainId: normalizedChainId }; } catch (error) { if (error instanceof APIError) { throw error; } throw new APIError( `Failed to prepare withdrawal transaction: ${error instanceof Error ? error.message : String(error)}`, { endpoint: "prepareWithdrawTransactionData", cause: error } ); } }; var prepareBridgeAndWithdrawTransactionData = async ({ vault, wantAsset, sourceChainId, destinationChainId, offerAmount, userAddress, deadline = DEFAULT_DEADLINE, slippage = DEFAULT_WITHDRAW_SLIPPAGE, vaultKey }) => { try { const { data: withdrawTransactionData, error: withdrawError, success: withdrawSuccess } = await tryCatch( prepareWithdrawTransactionData({ vault, wantAsset, chainId: destinationChainId, userAddress, offerAmount, deadline, slippage }) ); if (!withdrawSuccess) { throw new APIError( `Failed to prepare withdrawal transaction: ${withdrawError.message}`, { endpoint: "prepareBridgeAndWithdrawTransactionData", cause: withdrawError } ); } const { args } = withdrawTransactionData; const [, , userRequest] = args; const { offerAmount: bridgeAmount } = userRequest; if (!vaultKey) { throw new APIError( `vaultKey parameter is currently required for bridge configuration lookup (temporary limitation)`, { endpoint: "prepareBridgeAndWithdrawTransactionData" } ); } const { data: bridgeTransactionData, error: bridgeError, success: bridgeSuccess } = await tryCatch( prepareBridgeTransactionData({ vaultKey, bridgeAmount, sourceChainId, destinationChainId, userAddress }) ); if (!bridgeSuccess) { throw new APIError( `Failed to prepare bridge transaction: ${bridgeError.message}`, { endpoint: "prepareBridgeAndWithdrawTransactionData", cause: bridgeError } ); } return { bridgeTransactionData, withdrawTransactionData }; } catch (error) { if (error instanceof APIError) { throw error; } throw new APIError( `Failed to prepare bridge and withdraw transaction: ${error instanceof Error ? error.message : String(error)}`, { endpoint: "prepareBridgeAndWithdrawTransactionData", cause: error } ); } }; var prepareApproveWithdrawToken = async ({ vault, withdrawAmount, chainId }) => { try { const normalizedChainId = toChainId(chainId); if (vault.chainId !== normalizedChainId) { throw new APIError( `Vault chain mismatch: vault is on chain ${vault.chainId}, requested chain ${normalizedChainId}`, { endpoint: "prepareApproveWithdrawToken" } ); } if (!vault.Nucleus.boringVaultAddressId) { throw new APIError( `BoringVault contract address not configured for vault ${vault.id}`, { endpoint: "prepareApproveWithdrawToken" } ); } const boringVaultAddress = vault.Nucleus.boringVaultAddressId; const vaultSharesAssets = await fetchSupportedAssets({ address: boringVaultAddress }); if (vaultSharesAssets.length === 0) { throw new APIError( `Vault shares token not found in supported assets: ${boringVaultAddress}`, { endpoint: "prepareApproveWithdrawToken" } ); } const withdrawAmountAsBigInt = withdrawAmount ? parseUnits(withdrawAmount, vaultSharesAssets[0].decimals) : DEFAULT_APPROVAL_AMOUNT; return { abi: BoringVaultAbi, address: boringVaultAddress, functionName: "approve", args: [ATOMIC_QUEUE_CONTRACT_ADDRESS, withdrawAmountAsBigInt] }; } catch (error) { if (error instanceof APIError) { throw error; } throw new APIError( `Failed to prepare approval transaction: ${error instanceof Error ? error.message : String(error)}`, { endpoint: "prepareApproveWithdrawToken", cause: error } ); } }; export { PERMIT_TYPES, parsePermitSignature, prepareApproveDepositToken, prepareApproveWithdrawToken, prepareBridgeAndWithdrawTransactionData, prepareDepositPermitSignature, prepareDepositTransactionData, prepareDepositWithPermitTransactionData, prepareWithdrawTransactionData }; //# sourceMappingURL=index.mjs.map //# sourceMappingURL=index.mjs.map