@shogun-sdk/money-legos
Version:
Shogun Money Legos: clients and types for quotes, memes, prices, balances, fees, validations, etc.
110 lines (97 loc) • 3.17 kB
text/typescript
import { parseUnits } from 'viem';
import { base } from 'viem/chains';
import { isSolanaChain } from '../config/chains.js';
import { getQuote } from '../lib/getQuote.js';
import { DEFAULT_JITO_TIP } from '../lib/jito.js';
import { getNormalizedSolanaToken } from '../lib/solana.js';
import { MAX_AFFILIATE_FEE_PERCENT } from '../services/AffiliateFeeService.js';
import type { QuoteTypes, Token } from '../types/index.js';
import { NATIVE_TOKEN } from '../config/addresses.js';
export interface QuoteParams {
srcChain: number;
destChain: number;
srcToken: string;
destToken: string;
amount: string;
senderAddress: string;
affiliateWallet: string;
affiliateFee: string;
slippage: number;
destinationAddress: string;
dstChainOrderAuthorityAddress: string;
jitoTip?: number;
gasRefuel?: number;
dynamicSlippage?: boolean;
externalCall?: string;
}
export function getSwapWeiAmount(amount: string, decimals: number) {
return parseUnits(amount || '0', decimals);
}
export function getRecipientAddress(
fromToken: Token,
toToken: Token,
senderAddress: string,
destinationAddress: string,
): string {
const recipientAddress = senderAddress || destinationAddress;
const finalRecipient = fromToken.chainId === toToken.chainId ? senderAddress : destinationAddress || recipientAddress;
return finalRecipient;
}
export function createQuoteParams(
fromToken: Token,
toToken: Token,
amount: string,
destinationAddress: string | null,
senderAddress: string,
slippage: number,
totalFeePercent: number,
affiliateWallets: {
solana: string;
evm: string;
},
dynamicSlippage?: boolean,
): QuoteParams {
const amountWei = getSwapWeiAmount(amount, fromToken.decimals);
const finalRecipient = getRecipientAddress(fromToken, toToken, senderAddress, destinationAddress ?? '');
const quoteParams: QuoteParams = {
srcChain: fromToken.chainId,
destChain: toToken.chainId,
srcToken: getNormalizedSolanaToken(fromToken.address),
destToken: getNormalizedSolanaToken(toToken.address),
amount: String(amountWei),
senderAddress: senderAddress,
affiliateWallet: affiliateWallets[isSolanaChain(fromToken.chainId) ? 'solana' : 'evm'],
slippage,
dstChainOrderAuthorityAddress: finalRecipient ?? '',
destinationAddress: finalRecipient ?? '',
affiliateFee: Math.min(totalFeePercent || 1, MAX_AFFILIATE_FEE_PERCENT).toString(),
dynamicSlippage: dynamicSlippage ? true : false,
};
// Include jitoTip only if the source chain is Solana
if (isSolanaChain(fromToken.chainId)) {
quoteParams.jitoTip = Number(DEFAULT_JITO_TIP);
}
return quoteParams;
}
export async function fetchQuote(
api: { key: string; url: string },
params: QuoteParams,
signal: AbortSignal,
): Promise<QuoteTypes> {
const quote = await getQuote(api, params, signal);
if (!quote) {
throw new Error('No quote data for swap');
}
return quote;
}
export interface BaseQuoteContextValue {
isLoading: boolean;
isRefetching: boolean;
}
export const BRIDGE_TOKEN: Token = {
address: NATIVE_TOKEN.ETH,
chainId: base.id,
decimals: 6,
symbol: 'ETH',
name: 'Ether',
};