@accret/bridge-sdk
Version:
314 lines • 14.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getQuote = getQuote;
exports.executeSwap = executeSwap;
exports.getTokenList = getTokenList;
const types_1 = require("../types");
const jupiter_1 = require("./jupiter");
const mayan_1 = require("./mayan");
const deBridge_1 = require("./deBridge");
const utils_1 = require("../utils");
/**
* @description Formats a quote response into a standardized AccretQuote format
* @param provider - The provider of the quote
* @param quote - The quote response from the provider
* @param inputParams - The original input parameters for the quote request
* @returns The formatted quote in AccretQuote format
*/
function formatQuote(provider, quote, inputParams) {
let quoteDetails;
switch (provider) {
case types_1.AccretSupportedProvider.DEBRIDGE:
// Single Chain
if (inputParams.fromChain === inputParams.toChain) {
const singleChainQuote = quote;
quoteDetails = {
provider,
details: {
tokenIn: {
address: singleChainQuote.estimation.tokenIn.address,
amount: parseFloat(singleChainQuote.estimation.tokenIn.amount),
decimals: singleChainQuote.estimation.tokenIn.decimals,
name: singleChainQuote.estimation.tokenIn.name,
symbol: singleChainQuote.estimation.tokenIn.symbol,
},
tokenOut: {
address: singleChainQuote.estimation.tokenOut.address,
amount: parseFloat(singleChainQuote.estimation.tokenOut.amount),
decimals: singleChainQuote.estimation.tokenOut.decimals,
name: singleChainQuote.estimation.tokenOut.name,
symbol: singleChainQuote.estimation.tokenOut.symbol,
},
slippage: singleChainQuote.estimation.slippage,
},
fee: parseFloat(singleChainQuote.estimation.tokenOut.amount || "0") *
0.01,
rawQuote: singleChainQuote,
};
}
else {
const crossChainQuote = quote;
quoteDetails = {
provider,
details: {
tokenIn: {
address: crossChainQuote.estimation.srcChainTokenIn.address,
amount: parseFloat(crossChainQuote.estimation.srcChainTokenIn.amount),
decimals: crossChainQuote.estimation.srcChainTokenIn.decimals,
name: crossChainQuote.estimation.srcChainTokenIn.name,
symbol: crossChainQuote.estimation.srcChainTokenIn.symbol,
amountUsd: crossChainQuote.estimation.srcChainTokenIn.approximateUsdValue,
},
tokenOut: {
address: crossChainQuote.estimation.dstChainTokenOut.address,
amount: parseFloat(crossChainQuote.estimation.dstChainTokenOut.amount),
decimals: crossChainQuote.estimation.dstChainTokenOut.decimals,
name: crossChainQuote.estimation.dstChainTokenOut.name,
symbol: crossChainQuote.estimation.dstChainTokenOut.symbol,
amountUsd: crossChainQuote.estimation.dstChainTokenOut.approximateUsdValue,
},
slippage: crossChainQuote.estimation.recommendedSlippage,
},
fee: parseFloat(crossChainQuote.estimation.costsDetails[0]?.payload.feeAmount ||
"0") * 0.01,
feeUsd: parseFloat(crossChainQuote.estimation.costsDetails[0]?.payload
.feeApproximateUsdValue || "0"),
estimatedTime: crossChainQuote.order?.approximateFulfillmentDelay || 0,
rawQuote: crossChainQuote,
};
}
break;
case types_1.AccretSupportedProvider.JUPITER: {
const quoteResponse = quote;
quoteDetails = {
provider: types_1.AccretSupportedProvider.JUPITER,
details: {
tokenIn: {
address: inputParams.fromToken,
decimals: inputParams.srcTokenDecimals,
amount: parseFloat(quoteResponse.inAmount),
},
tokenOut: {
address: quoteResponse.outputMint,
amount: parseFloat(quoteResponse.outAmount),
},
slippage: quoteResponse.slippageBps,
},
fee: parseFloat(quoteResponse.platformFee?.amount || "0"),
rawQuote: quoteResponse,
};
break;
}
case types_1.AccretSupportedProvider.MAYAN: {
const mayanQuote = quote;
quoteDetails = {
provider,
details: {
tokenIn: {
address: mayanQuote.fromToken.contract,
amount: parseFloat(mayanQuote.effectiveAmountIn64),
decimals: mayanQuote.fromToken.decimals,
name: mayanQuote.fromToken.name,
symbol: mayanQuote.fromToken.symbol,
},
tokenOut: {
address: mayanQuote.toToken.mint,
amount: mayanQuote.expectedAmountOut,
decimals: mayanQuote.toToken.decimals,
name: mayanQuote.toToken.name,
symbol: mayanQuote.toToken.symbol,
amountUsd: mayanQuote.price,
},
slippage: mayanQuote.slippageBps,
},
fee: mayanQuote.bridgeFee,
estimatedTime: mayanQuote.etaSeconds,
rawQuote: mayanQuote,
};
break;
}
}
return quoteDetails;
}
/**
* @description Finds the best quote from an array of quotes based on the output amount
* @param quotes - An array of AccretQuote objects
* @returns The best quote object
*/
function findBestQuote(quotes) {
if (quotes.length === 0) {
throw new Error("No quotes available");
}
const validQuotes = quotes.filter((quote) => quote.details.tokenOut.amount > 0);
if (validQuotes.length === 0) {
throw new Error("No valid quotes with positive output amount");
}
validQuotes.sort((quote1, quote2) => quote2.details.tokenOut.amount - quote1.details.tokenOut.amount);
const bestQuote = validQuotes[0];
if (!bestQuote) {
throw new Error("No valid quote found after filtering");
}
return bestQuote;
}
/**
* @description Fetches quotes from multiple providers and returns the best and the other quotes
* @param params - The parameters for fetching a quote
* @param params.fromChain - The chain from which to swap
* @param params.fromToken - The token to swap from
* @param params.toChain - The chain to which to swap
* @param params.toToken - The token to swap to
* @param params.amount - The amount to swap
* @param params.srcTokenDecimals - The decimals of the source token
* @param params.slippage - The slippage in basis points (default is 50)
* @param params.referrer - The referrer for the swap (optional)
* @param params.referrerBps - The referrer basis points (optional)
* @param params.referrerAddress - The referrer address (optional)
* @returns An object containing the best quote and all quotes
*/
async function getQuote(params) {
const quotes = [];
const errors = [];
// Set Referrer Address
if (!params.referrerAddress || !params.referrerBps) {
params.referrerAddress =
params.fromChain === types_1.AccretSupportedChain.SOLANA_CHAIN
? utils_1.AccretReferrerAddresses.solana
: utils_1.AccretReferrerAddresses.evm;
params.referrerBps = 50;
}
// Get DeBridge Quote
// Note: Used for both Cross Chain & Single Chain swaps only
try {
const deBridgeParams = {
srcChain: params.fromChain,
srcChainTokenIn: params.fromToken,
srcChainTokenInAmount: params.amount.toString(),
srcTokenDecimals: params.srcTokenDecimals,
dstChain: params.toChain,
dstChainTokenOut: params.toToken,
slippage: params.slippage,
affiliateFeeRecipient: params.referrerAddress,
affiliateFeePercent: Number(params.referrerBps),
};
const deBridgeQuote = await (0, deBridge_1.getDeBridgeQuote)(deBridgeParams);
quotes.push(formatQuote(types_1.AccretSupportedProvider.DEBRIDGE, deBridgeQuote, params));
}
catch (error) {
errors.push(`deBridge: ${error instanceof Error ? error.message : "Unknown error"}`);
}
// Get Jupiter Quote
// Note: Used for Single Chain Solana swaps only
if (params.fromChain === types_1.AccretSupportedChain.SOLANA_CHAIN &&
params.toChain === types_1.AccretSupportedChain.SOLANA_CHAIN) {
try {
console.log("Fetching Jupiter quote...");
const jupiterQuote = await (0, jupiter_1.getJupiterQuote)(params.fromToken, params.toToken, params.amount);
quotes.push(formatQuote(types_1.AccretSupportedProvider.JUPITER, jupiterQuote, params));
}
catch (error) {
errors.push(`Jupiter: ${error instanceof Error ? error.message : "Unknown error"}`);
}
}
// Get Mayan Quote
// Note: Used for cross-chain swaps only
try {
const mayanParams = {
fromChain: params.fromChain,
fromToken: params.fromToken,
toChain: params.toChain,
toToken: params.toToken,
amount: params.amount,
slippageBps: params.slippage || 50,
referrer: params.referrer,
referrerBps: params.referrerBps,
referrerAddress: params.referrerAddress,
};
const mayanQuote = await (0, mayan_1.getMayanQuote)(mayanParams);
quotes.push(formatQuote(types_1.AccretSupportedProvider.MAYAN, mayanQuote, params));
}
catch (error) {
errors.push(`Mayan: ${error instanceof Error ? error.message : "Unknown error"}`);
}
if (quotes.length === 0) {
throw new Error(`No quotes available from any bridge. Errors: ${errors.join(", ")}`);
}
const bestQuote = findBestQuote(quotes);
return {
bestQuote,
allQuotes: quotes,
};
}
/**
* @description Executes a swap on the specified provider
* @param params - The parameters for executing a swap
* @param params.provider - The provider to use for the swap
* @param params.data - The data required for the swap, which can vary by provider
* @returns A promise that resolves to the swap response
*/
async function executeSwap(params) {
switch (params.provider) {
case types_1.AccretSupportedProvider.JUPITER:
return await (0, jupiter_1.executeJupiterTransaction)({
userPublicKey: params.data.privateKey,
quoteResponse: params.data.quote,
});
case types_1.AccretSupportedProvider.MAYAN:
return await (0, mayan_1.executeMayanSwap)({
quote: params.data.quote,
destAddr: params.data.destAddr,
privateKey: params.data.privateKey,
});
case types_1.AccretSupportedProvider.DEBRIDGE:
return await (0, deBridge_1.executeDeBridgeSwap)({
privateKey: params.data.privateKey,
srcNetwork: params.data.srcNetwork,
srcTokenAddress: params.data
.srcTokenAddress,
srcTokenDecimals: params.data
.srcTokenDecimals,
amountToSwap: params.data.amountToSwap,
dstTokenAddress: params.data
.dstTokenAddress,
dstNetwork: params.data.dstNetwork,
recipientAddress: params.data
.recipientAddress,
srcChainRpcUrl: params.data
.srcChainRpcUrl,
// Optional deBridge parameters
slippage: params.data.slippage || 10,
referralCode: params.data.referralCode || "",
srcChainOrderAuthorityAddress: params.data
.srcChainOrderAuthorityAddress || "",
dstChainOrderAuthorityAddress: params.data
.dstChainOrderAuthorityAddress || "",
dstChainTokenOutAmount: params.data.dstChainTokenOutAmount ||
"",
// Optional logging
enableLogging: params.data.enableLogging || false,
// Optional parameters
affiliateFeeRecipient: params.data.affiliateFeeRecipient ||
"",
affiliateFeePercent: params.data.affiliateFeePercent || 0,
});
default:
throw new Error(`Unsupported provider: ${params.provider}`);
}
}
/**
* @description Fetches the token list from the specified provider
* @param params - The parameters for fetching the token list
* @returns A promise that resolves to the token list
*/
async function getTokenList(params) {
switch (params.provider) {
case types_1.AccretSupportedProvider.JUPITER:
return await (0, jupiter_1.getJupiterTokenList)();
case types_1.AccretSupportedProvider.MAYAN:
return await (0, mayan_1.getMayanTokenList)(params.chainId);
case types_1.AccretSupportedProvider.DEBRIDGE:
return await (0, deBridge_1.getDeBridgeTokenList)(params.chainId);
default:
throw new Error(`Unsupported provider: ${params.provider}`);
}
}
//# sourceMappingURL=index.js.map