@paxoslabs/earn-sdk
Version:
Paxos Labs Earn SDK
1,030 lines (1,022 loc) • 32.2 kB
JavaScript
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