Skip to content

Instantly share code, notes, and snippets.

@olegpetroveth
Created May 19, 2025 19:35
Show Gist options
  • Save olegpetroveth/88ffd4d1d4c35cdc39352835a0ac3304 to your computer and use it in GitHub Desktop.
Save olegpetroveth/88ffd4d1d4c35cdc39352835a0ac3304 to your computer and use it in GitHub Desktop.
PancakeSwap
async function ({
sourceAddress,
destinationAddress,
sellAssetAmount,
buyAssetAmount,
// affiliateFee,
slipPercentage,
}: ProviderQuoteRequest): Promise<ProviderQuoteResponse> {
try {
// Check provider chain action enabled status
const shouldQuote = await isActionEnabled({
action: ProviderAction.swap,
provider: name,
chains: [sellAssetAmount.chain, buyAssetAmount.chain],
});
if (!shouldQuote) {
throw new SwapKitError({
code: ErrorCode.quoteUnavailable,
args: [name],
});
}
const sellProviderToken = pancakeSwapApi.helpers.toProviderToken(sellAssetAmount);
const buyProviderToken = pancakeSwapApi.helpers.toProviderToken(buyAssetAmount);
const sellTokenAmount = CurrencyAmount.fromRawAmount(
sellProviderToken,
sellAssetAmount.getBaseValue("string"),
);
// consider caching this in config?
const [v2Pools, v3Pools] = await Promise.all([
SmartRouter.getV2CandidatePools({
// @ts-expect-error ignore viem
onChainProvider: () => publicClient,
currencyA: sellProviderToken,
currencyB: buyProviderToken,
}),
SmartRouter.getV3CandidatePools({
// @ts-expect-error ignore viem
onChainProvider: () => publicClient,
currencyA: sellProviderToken,
currencyB: buyProviderToken,
}),
]);
const bestTrade = await SmartRouter.getBestTrade(
sellTokenAmount,
buyProviderToken,
TradeType.EXACT_INPUT,
{
gasPriceWei: () => publicClient.getGasPrice(),
maxHops: 3,
maxSplits: 3,
poolProvider: SmartRouter.createStaticPoolProvider([...v2Pools, ...v3Pools]),
quoteProvider,
quoterOptimization: false,
},
);
if (!bestTrade) {
throw new SwapKitError({
code: ErrorCode.noQuoteResponse,
args: [this.name, "No quote response from Pancakeswap."],
});
}
const { value, calldata } = SwapRouter.swapCallParameters(
{ ...bestTrade, gasEstimate: bestTrade.gasEstimate },
{
recipient: destinationAddress as `0x${string}`,
slippageTolerance: new Percent(slipPercentage, 100),
//TODO - figure out comprehensive strategy for fee sharing between SK and partners for single chain fees
// fee: {
// fee: new Percent(Number(0), 100),
// recipient: "0x9F9A7D3e131eD45225396613E383D59a732f7BeB",
// },
},
);
const router = pancakeswapProvider.getRouterAddress({ chainId: sellAssetAmount.chainId });
if (!router) {
throw new SwapKitError({
code: ErrorCode.noRouterAddressFound,
args: [name, sellAssetAmount.chainId],
});
}
const tx = buildTx({
sellAssetAmount,
sourceAddress,
destinationAddress,
calldata,
value,
});
const quoteAmount = bestTrade.outputAmount.toFixed();
const quoteAssetAmount = buyAssetAmount.set(quoteAmount);
return {
sellAssetAmount,
buyAssetAmount: quoteAssetAmount,
buyAssetAmountMaxSlippage: quoteAssetAmount,
slippageBps: slipPercentage * 100,
sourceAddress,
destinationAddress,
routerAddress: router,
tx,
estimatedTime: this.estimateTime!({
inboundAsset: sellAssetAmount,
outboundAsset: buyAssetAmount,
}),
};
} catch (error) {
logger.error({ error }, `${name}: Error fetching quote`);
throw error;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment