UNPKG

@robertprp/intents-sdk

Version:

Shogun Network Intent-based cross-chain swaps SDK

104 lines 4.29 kB
import { ChainID } from '../chains.js'; import { NATIVE_EVM_ETH_ADDRESSES, NATIVE_SOLANA_TOKEN_ADDRESS, WRAPPED_SOL_MINT_ADDRESS } from '../constants.js'; import { Parsers } from './parsers.js'; import { QuoteProvider } from './quote/aggregator.js'; const TOKEN_PRICE_BASE_URL = 'https://coins.llama.fi/prices/current/'; const STABLECOIN_DECIMALS = 6; // USDC/USDT typically use 6 decimals /** * Maps chain IDs to their corresponding chain types * Used to determine which SDK implementation to use for a given chain */ export const chainIdToDefiLlamaChainMap = { [ChainID.Arbitrum]: 'arbitrum', [ChainID.Base]: 'base', [ChainID.Optimism]: 'optimism', [ChainID.Hyperliquid]: 'hyperliquid', [ChainID.Solana]: 'solana', [ChainID.Sui]: 'sui', }; /** * Creates DefiLlama coin key from chain ID and token address * Format: "chainName:tokenAddress" */ export const createDefiLlamaCoinKey = (chainId, tokenAddress) => { const chainName = chainIdToDefiLlamaChainMap[chainId]; return `${chainName}:${toDefiLlamaToken(tokenAddress)}`; }; /** * Retrieves token data from DefiLlama response by chain and address */ export const getCoinFromResponse = (response, chainId, tokenAddress) => { const key = createDefiLlamaCoinKey(chainId, tokenAddress); const coin = response.coins[key]; if (!coin) { throw new Error(`DefiLlama coin not found for ${key}`); } return coin; }; /** * Converts Solana native token address to wrapped SOL mint address * DefiLlama uses wrapped SOL mint address for native SOL * * @param tokenAddress The token address to convert * @returns The DefiLlama-compatible token address */ function toDefiLlamaToken(tokenAddress) { if (isNativeTokenEvmAddress(tokenAddress)) { return '0x0000000000000000000000000000000000000000'; } if (tokenAddress === NATIVE_SOLANA_TOKEN_ADDRESS) { return WRAPPED_SOL_MINT_ADDRESS; } return tokenAddress; } function isNativeTokenEvmAddress(tokenAddress) { const normalizedAddress = tokenAddress.toLowerCase(); return NATIVE_EVM_ETH_ADDRESSES.some((addr) => addr.toLowerCase() === normalizedAddress); } /** * Builds a comma-separated query string for DefiLlama API token requests * * Converts an array of chain/token pairs into the format expected by DefiLlama's * bulk price endpoint: "chain1:token1,chain2:token2,..." * * @param tokens - Array of [ChainID, token address] tuples to query * @returns Comma-separated string of DefiLlama coin keys */ function buildTokensQueryString(tokens) { return tokens.map(([chainId, tokenAddress]) => createDefiLlamaCoinKey(chainId, tokenAddress)).join(','); } /** * Fetch tokens data for array of coins * * @param tokens Array of [ChainID, Token Address] tuples * @returns Promise resolving to DefiLlama tokens response */ export async function getTokensData(tokens) { const tokensStr = buildTokensQueryString(tokens); const url = `${TOKEN_PRICE_BASE_URL}${tokensStr}`; const response = await fetch(url, { method: 'GET', headers: { 'Content-Type': 'application/json', }, }); return response.json(); } export async function calculateAmounts({ srcChainId, tokenIn, amountIn, destChainId, tokenOut, }) { // Fetch token data from DefiLlama const tokensResponse = await getTokensData([ [srcChainId, tokenIn], [destChainId, tokenOut], ]); const tokenInData = getCoinFromResponse(tokensResponse, srcChainId, tokenIn); const tokenOutData = getCoinFromResponse(tokensResponse, destChainId, tokenOut); // Calculate 80% of the amount_in value as amount_out_min and min_stablecoins_amount const tokenInUsdAmount = Parsers.bigintToFloat(amountIn, tokenInData.decimals) * tokenInData.price; const reductionFactor = QuoteProvider.calculateWeightedReductionFactorForUsd(tokenInUsdAmount); const amountInUsdReduced = tokenInUsdAmount * reductionFactor; const amountOutReduced = amountInUsdReduced / tokenOutData.price; const amountOut = Parsers.floatToBigint(amountOutReduced, tokenOutData.decimals); const minStablecoinsAmount = Parsers.floatToBigint(amountInUsdReduced, STABLECOIN_DECIMALS); return { amountOut, minStablecoinsAmount }; } //# sourceMappingURL=defillama.js.map