UNPKG

@orca-so/whirlpool-sdk

Version:

Whirlpool SDK for the Orca protocol.

536 lines (535 loc) 29.6 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.OrcaPool = void 0; const common_sdk_1 = require("@orca-so/common-sdk"); const anchor_1 = require("@project-serum/anchor"); const spl_token_1 = require("@solana/spl-token"); const web3_js_1 = require("@solana/web3.js"); const tiny_invariant_1 = __importDefault(require("tiny-invariant")); const types_1 = require("./public/types"); const defaults_1 = require("../constants/public/defaults"); const add_liquidity_1 = require("../position/quotes/add-liquidity"); const remove_liquidity_1 = require("../position/quotes/remove-liquidity"); const address_1 = require("../utils/address"); const multi_transaction_builder_1 = require("../utils/public/multi-transaction-builder"); const pool_util_1 = require("../utils/whirlpool/pool-util"); const tick_util_1 = require("../utils/whirlpool/tick-util"); const liquidity_distribution_1 = require("./ux/liquidity-distribution"); const swap_quoter_1 = require("./quotes/swap-quoter"); const whirlpool_client_sdk_1 = require("@orca-so/whirlpool-client-sdk"); const fees_and_rewards_1 = require("../position/txs/fees-and-rewards"); const position_util_1 = require("../utils/public/position-util"); const math_utils_1 = require("../utils/web3/math-utils"); class OrcaPool { constructor(dal) { this.dal = dal; } /*** Utilities ***/ /** * Create liquidity distribution across three tick-arrays for a pool. * Useful for visualizing the liquidity in the pool. * * @param poolAddress * @param tickLower * @param tickUpper * @param refresh * @returns liquidity distribution */ getLiquidityDistribution(poolAddress, tickLower, tickUpper, refresh = true) { return __awaiter(this, void 0, void 0, function* () { return (0, liquidity_distribution_1.getLiquidityDistribution)(this.dal, poolAddress, tickLower, tickUpper, refresh); }); } /** * Derive the pool pda given token mints and tick spacing * * @param tokenMintA * @param tokenMintB * @param stable * @returns */ derivePDA(tokenMintA, tokenMintB, tickSpacing) { const [_tokenMintA, _tokenMintB] = pool_util_1.PoolUtil.orderMints(tokenMintA, tokenMintB); return (0, whirlpool_client_sdk_1.getWhirlpoolPda)(this.dal.programId, this.dal.whirlpoolsConfig, (0, address_1.toPubKey)(_tokenMintA), (0, address_1.toPubKey)(_tokenMintB), tickSpacing); } /*** Transactions ***/ /** * Construct a transaction for opening an new position */ getOpenPositionTx(param) { return __awaiter(this, void 0, void 0, function* () { return this.getOpenPositionWithOptMetadataTx(param); }); } /** * Construct a transaction for opening an new position */ getOpenPositionWithMetadataTx(param) { return __awaiter(this, void 0, void 0, function* () { return this.getOpenPositionWithOptMetadataTx(param, true); }); } /** * Construct a transaction for opening an new position with optional metadata */ getOpenPositionWithOptMetadataTx(param, withMetadata = false) { return __awaiter(this, void 0, void 0, function* () { const { provider, quote: { maxTokenA, maxTokenB, liquidity, tickLowerIndex, tickUpperIndex, poolAddress }, } = param; (0, tiny_invariant_1.default)(liquidity.gt(new spl_token_1.u64(0)), "liquidity must be greater than zero"); const ctx = whirlpool_client_sdk_1.WhirlpoolContext.withProvider(provider, this.dal.programId); const client = new whirlpool_client_sdk_1.WhirlpoolClient(ctx); const whirlpool = yield this.dal.getPool(poolAddress, false); if (!whirlpool) { throw new Error(`Whirlpool not found: ${(0, anchor_1.translateAddress)(poolAddress).toBase58()}`); } const positionMintKeypair = web3_js_1.Keypair.generate(); const positionPda = (0, whirlpool_client_sdk_1.getPositionPda)(this.dal.programId, positionMintKeypair.publicKey); const metadataPda = (0, whirlpool_client_sdk_1.getPositionMetadataPda)(positionMintKeypair.publicKey); const positionTokenAccountAddress = yield (0, common_sdk_1.deriveATA)(provider.wallet.publicKey, positionMintKeypair.publicKey); const txBuilder = new whirlpool_client_sdk_1.TransactionBuilder(provider); const preTxBuilder = new whirlpool_client_sdk_1.TransactionBuilder(provider); const positionIx = (withMetadata ? client.openPositionWithMetadataTx : client.openPositionTx) .bind(client)({ funder: provider.wallet.publicKey, ownerKey: provider.wallet.publicKey, positionPda, metadataPda, positionMintAddress: positionMintKeypair.publicKey, positionTokenAccountAddress, whirlpoolKey: (0, address_1.toPubKey)(poolAddress), tickLowerIndex, tickUpperIndex, }) .compressIx(false); txBuilder.addInstruction(positionIx).addSigner(positionMintKeypair); const [ataA, ataB] = yield (0, common_sdk_1.resolveOrCreateATAs)(provider.connection, provider.wallet.publicKey, [ { tokenMint: whirlpool.tokenMintA, wrappedSolAmountIn: maxTokenA }, { tokenMint: whirlpool.tokenMintB, wrappedSolAmountIn: maxTokenB }, ], () => this.dal.getAccountRentExempt()); const _a = ataA, { address: tokenOwnerAccountA } = _a, tokenOwnerAccountAIx = __rest(_a, ["address"]); const _b = ataB, { address: tokenOwnerAccountB } = _b, tokenOwnerAccountBIx = __rest(_b, ["address"]); txBuilder.addInstruction(tokenOwnerAccountAIx); txBuilder.addInstruction(tokenOwnerAccountBIx); const tickArrayLowerPda = tick_util_1.TickUtil.getPdaWithTickIndex(tickLowerIndex, whirlpool.tickSpacing, poolAddress, this.dal.programId); const tickArrayUpperPda = tick_util_1.TickUtil.getPdaWithTickIndex(tickUpperIndex, whirlpool.tickSpacing, poolAddress, this.dal.programId); const [tickArrayLower, tickArrayUpper] = yield this.dal.listTickArrays([tickArrayLowerPda.publicKey, tickArrayUpperPda.publicKey], true); let requirePreTx = false; if (tickArrayLower === null) { const tickArrayIx = client .initTickArrayTx({ whirlpool: (0, address_1.toPubKey)(poolAddress), tickArrayPda: tickArrayLowerPda, startTick: tick_util_1.TickUtil.getStartTickIndex(tickLowerIndex, whirlpool.tickSpacing), funder: provider.wallet.publicKey, }) .compressIx(false); preTxBuilder.addInstruction(tickArrayIx); requirePreTx = true; } if (tickArrayUpper === null && !tickArrayLowerPda.publicKey.equals(tickArrayUpperPda.publicKey)) { const tickArrayIx = client .initTickArrayTx({ whirlpool: (0, address_1.toPubKey)(poolAddress), tickArrayPda: tickArrayUpperPda, startTick: tick_util_1.TickUtil.getStartTickIndex(tickUpperIndex, whirlpool.tickSpacing), funder: provider.wallet.publicKey, }) .compressIx(false); preTxBuilder.addInstruction(tickArrayIx); requirePreTx = true; } const liquidityIx = client .increaseLiquidityTx({ liquidityAmount: liquidity, tokenMaxA: maxTokenA, tokenMaxB: maxTokenB, whirlpool: (0, address_1.toPubKey)(poolAddress), positionAuthority: provider.wallet.publicKey, position: positionPda.publicKey, positionTokenAccount: positionTokenAccountAddress, tokenOwnerAccountA, tokenOwnerAccountB, tokenVaultA: whirlpool.tokenVaultA, tokenVaultB: whirlpool.tokenVaultB, tickArrayLower: tickArrayLowerPda.publicKey, tickArrayUpper: tickArrayUpperPda.publicKey, }) .compressIx(false); txBuilder.addInstruction(liquidityIx); const tx = new multi_transaction_builder_1.MultiTransactionBuilder(provider, []); if (requirePreTx) { tx.addTxBuilder(preTxBuilder); } tx.addTxBuilder(txBuilder); return { mint: positionMintKeypair.publicKey, tx, }; }); } getInitTickArrayTx(provider, param) { return __awaiter(this, void 0, void 0, function* () { const ctx = whirlpool_client_sdk_1.WhirlpoolContext.withProvider(provider, this.dal.programId); const client = new whirlpool_client_sdk_1.WhirlpoolClient(ctx); return client.initTickArrayTx(param); }); } /** * Construct a transaction for closing an existing position */ getClosePositionTx(param) { return __awaiter(this, void 0, void 0, function* () { const { provider, quote } = param; const ctx = whirlpool_client_sdk_1.WhirlpoolContext.withProvider(provider, this.dal.programId); const client = new whirlpool_client_sdk_1.WhirlpoolClient(ctx); const position = yield this.dal.getPosition(quote.positionAddress, true); if (!position) { throw new Error(`Position not found: ${(0, anchor_1.translateAddress)(quote.positionAddress).toBase58()}`); } const whirlpool = yield this.dal.getPool(position.whirlpool, false); if (!whirlpool) { throw new Error(`Whirlpool not found: ${(0, anchor_1.translateAddress)(position.whirlpool).toBase58()}`); } const tickArrayLower = tick_util_1.TickUtil.getPdaWithTickIndex(position.tickLowerIndex, whirlpool.tickSpacing, position.whirlpool, this.dal.programId).publicKey; const tickArrayUpper = tick_util_1.TickUtil.getPdaWithTickIndex(position.tickUpperIndex, whirlpool.tickSpacing, position.whirlpool, this.dal.programId).publicKey; const positionTokenAccount = yield (0, common_sdk_1.deriveATA)(provider.wallet.publicKey, position.positionMint); const txBuilder = new whirlpool_client_sdk_1.TransactionBuilder(provider); const resolvedAssociatedTokenAddresses = {}; const [ataA, ataB] = yield (0, common_sdk_1.resolveOrCreateATAs)(provider.connection, provider.wallet.publicKey, [{ tokenMint: whirlpool.tokenMintA }, { tokenMint: whirlpool.tokenMintB }], () => this.dal.getAccountRentExempt()); const _a = ataA, { address: tokenOwnerAccountA } = _a, createTokenOwnerAccountAIx = __rest(_a, ["address"]); const _b = ataB, { address: tokenOwnerAccountB } = _b, createTokenOwnerAccountBIx = __rest(_b, ["address"]); txBuilder.addInstruction(createTokenOwnerAccountAIx).addInstruction(createTokenOwnerAccountBIx); resolvedAssociatedTokenAddresses[whirlpool.tokenMintA.toBase58()] = tokenOwnerAccountA; resolvedAssociatedTokenAddresses[whirlpool.tokenMintB.toBase58()] = tokenOwnerAccountB; const collectTx = yield (0, fees_and_rewards_1.buildCollectFeesAndRewardsTx)(this.dal, { provider, positionAddress: quote.positionAddress, resolvedAssociatedTokenAddresses, }); txBuilder.addInstruction(collectTx.compressIx(false)); /* Remove all liquidity remaining in the position */ if (position.liquidity.gt(new spl_token_1.u64(0))) { const liquidityIx = client .decreaseLiquidityTx({ liquidityAmount: position.liquidity, tokenMinA: quote.minTokenA, tokenMinB: quote.minTokenB, whirlpool: position.whirlpool, positionAuthority: provider.wallet.publicKey, position: (0, address_1.toPubKey)(quote.positionAddress), positionTokenAccount, tokenOwnerAccountA, tokenOwnerAccountB, tokenVaultA: whirlpool.tokenVaultA, tokenVaultB: whirlpool.tokenVaultB, tickArrayLower, tickArrayUpper, }) .compressIx(false); txBuilder.addInstruction(liquidityIx); } /* Close position */ const positionIx = client .closePositionTx({ positionAuthority: provider.wallet.publicKey, receiver: provider.wallet.publicKey, positionTokenAccount, position: (0, address_1.toPubKey)(quote.positionAddress), positionMint: position.positionMint, }) .compressIx(false); txBuilder.addInstruction(positionIx); return txBuilder; }); } getLowestInitializedTickArrayTickIndex(poolAddress, tickSpacing) { return __awaiter(this, void 0, void 0, function* () { let offset = 1; while (true) { const tickArrayPda = tick_util_1.TickUtil.getPdaWithTickIndex(whirlpool_client_sdk_1.MIN_TICK_INDEX, tickSpacing, poolAddress, this.dal.programId, offset); // Throttle to prevent being rate-limited yield new Promise((resolve) => setTimeout(resolve, 1000)); const tickArray = yield this.dal.getTickArray(tickArrayPda.publicKey, false); if (!tickArray) { offset++; continue; } return tick_util_1.TickUtil.getStartTickIndex(whirlpool_client_sdk_1.MIN_TICK_INDEX, tickSpacing, offset); } }); } getHighestInitializedTickArrayTickIndex(poolAddress, tickSpacing) { return __awaiter(this, void 0, void 0, function* () { let offset = -1; while (true) { const tickArrayPda = tick_util_1.TickUtil.getPdaWithTickIndex(whirlpool_client_sdk_1.MAX_TICK_INDEX, tickSpacing, poolAddress, this.dal.programId, offset); yield new Promise((resolve) => setTimeout(resolve, 1000)); const tickArray = yield this.dal.getTickArray(tickArrayPda.publicKey, false); if (!tickArray) { offset--; continue; } return tick_util_1.TickUtil.getStartTickIndex(whirlpool_client_sdk_1.MAX_TICK_INDEX, tickSpacing, offset); } }); } // Finds all uninitialized tick arrays inbetween the lowest and highest // initialized tick arrays for a given pool getInitializeGapTickArraysTx(param) { return __awaiter(this, void 0, void 0, function* () { const { provider, poolAddress } = param; const ctx = whirlpool_client_sdk_1.WhirlpoolContext.withProvider(provider, this.dal.programId); const client = new whirlpool_client_sdk_1.WhirlpoolClient(ctx); const whirlpool = yield this.dal.getPool(poolAddress, true); if (!whirlpool) { throw new Error(`Whirlpool not found: ${(0, anchor_1.translateAddress)(poolAddress).toBase58()}`); } const firstTickIndex = yield this.getLowestInitializedTickArrayTickIndex(poolAddress, whirlpool.tickSpacing); const lastTickIndex = yield this.getHighestInitializedTickArrayTickIndex(poolAddress, whirlpool.tickSpacing); // get all lowest and highest tick array let numIxs = 0; let txBuilder = new whirlpool_client_sdk_1.TransactionBuilder(provider); const multiTxBuilder = new multi_transaction_builder_1.MultiTransactionBuilder(provider, []); let offset = 1; while (true) { const tickArrayPda = tick_util_1.TickUtil.getPdaWithTickIndex(firstTickIndex, whirlpool.tickSpacing, poolAddress, this.dal.programId, offset); const startTick = tick_util_1.TickUtil.getStartTickIndex(firstTickIndex, whirlpool.tickSpacing, offset); if (startTick === lastTickIndex) { break; } // Throttle to prevent being rate-limited yield new Promise((resolve) => setTimeout(resolve, 1000)); const tickArray = yield this.dal.getTickArray(tickArrayPda.publicKey, false); if (!tickArray) { txBuilder.addInstruction(client .initTickArrayTx({ whirlpool: (0, address_1.toPubKey)(poolAddress), tickArrayPda, startTick, funder: provider.wallet.publicKey, }) .compressIx(false)); numIxs++; if (!(numIxs % 7)) { multiTxBuilder.addTxBuilder(txBuilder); txBuilder = new whirlpool_client_sdk_1.TransactionBuilder(provider); } } offset++; } if (numIxs % 7) { multiTxBuilder.addTxBuilder(txBuilder); } return multiTxBuilder; }); } /** * Construct a transaction for a swap */ getSwapTx(param) { return __awaiter(this, void 0, void 0, function* () { const { provider, quote: { sqrtPriceLimitX64, otherAmountThreshold, amountIn, amountOut, aToB, fixedInput, poolAddress, }, } = param; const ctx = whirlpool_client_sdk_1.WhirlpoolContext.withProvider(provider, this.dal.programId); const client = new whirlpool_client_sdk_1.WhirlpoolClient(ctx); const whirlpool = yield this.dal.getPool(poolAddress, true); if (!whirlpool) { throw new Error(`Whirlpool not found: ${(0, anchor_1.translateAddress)(poolAddress).toBase58()}`); } const txBuilder = new whirlpool_client_sdk_1.TransactionBuilder(ctx.provider); const [ataA, ataB] = yield (0, common_sdk_1.resolveOrCreateATAs)(provider.connection, provider.wallet.publicKey, [ { tokenMint: whirlpool.tokenMintA, wrappedSolAmountIn: aToB ? amountIn : math_utils_1.ZERO }, { tokenMint: whirlpool.tokenMintB, wrappedSolAmountIn: !aToB ? amountIn : math_utils_1.ZERO }, ], () => this.dal.getAccountRentExempt()); const _a = ataA, { address: tokenOwnerAccountA } = _a, tokenOwnerAccountAIx = __rest(_a, ["address"]); txBuilder.addInstruction(tokenOwnerAccountAIx); const _b = ataB, { address: tokenOwnerAccountB } = _b, tokenOwnerAccountBIx = __rest(_b, ["address"]); txBuilder.addInstruction(tokenOwnerAccountBIx); const targetSqrtPriceLimitX64 = sqrtPriceLimitX64 || this.getDefaultSqrtPriceLimit(aToB); const tickArrayAddresses = yield this.getTickArrayPublicKeysForSwap(whirlpool.tickCurrentIndex, targetSqrtPriceLimitX64, whirlpool.tickSpacing, (0, address_1.toPubKey)(poolAddress), this.dal.programId, aToB); const oraclePda = (0, whirlpool_client_sdk_1.getOraclePda)(ctx.program.programId, (0, anchor_1.translateAddress)(poolAddress)); txBuilder.addInstruction(client .swapTx({ amount: fixedInput ? amountIn : amountOut, otherAmountThreshold, sqrtPriceLimit: targetSqrtPriceLimitX64, amountSpecifiedIsInput: fixedInput, aToB, whirlpool: (0, address_1.toPubKey)(poolAddress), tokenAuthority: provider.wallet.publicKey, tokenOwnerAccountA, tokenVaultA: whirlpool.tokenVaultA, tokenOwnerAccountB, tokenVaultB: whirlpool.tokenVaultB, tickArray0: tickArrayAddresses[0], tickArray1: tickArrayAddresses[1], tickArray2: tickArrayAddresses[2], oracle: oraclePda.publicKey, }) .compressIx(false)); return new multi_transaction_builder_1.MultiTransactionBuilder(provider, [txBuilder]); }); } getDefaultSqrtPriceLimit(aToB) { return new anchor_1.BN(aToB ? whirlpool_client_sdk_1.MIN_SQRT_PRICE : whirlpool_client_sdk_1.MAX_SQRT_PRICE); } getTickArrayPublicKeysForSwap(tickCurrentIndex, targetSqrtPriceX64, tickSpacing, poolAddress, programId, aToB) { return __awaiter(this, void 0, void 0, function* () { const nextInitializableTickIndex = tick_util_1.TickUtil.getNextInitializableTickIndex(tickCurrentIndex, tickSpacing, aToB); const targetTickIndex = (0, whirlpool_client_sdk_1.sqrtPriceX64ToTickIndex)(targetSqrtPriceX64); let currentStartTickIndex = tick_util_1.TickUtil.getStartTickIndex(nextInitializableTickIndex, tickSpacing); const targetStartTickIndex = tick_util_1.TickUtil.getStartTickIndex(targetTickIndex, tickSpacing); const offset = nextInitializableTickIndex < targetTickIndex ? 1 : -1; let count = 1; const tickArrayAddresses = [ (0, whirlpool_client_sdk_1.getTickArrayPda)(programId, poolAddress, currentStartTickIndex).publicKey, web3_js_1.PublicKey.default, web3_js_1.PublicKey.default, ]; while (currentStartTickIndex !== targetStartTickIndex && count < 3) { const nextStartTickIndex = tick_util_1.TickUtil.getStartTickIndex(nextInitializableTickIndex, tickSpacing, offset * count); const nextTickArrayAddress = (0, whirlpool_client_sdk_1.getTickArrayPda)(programId, poolAddress, nextStartTickIndex).publicKey; const nextTickArray = yield this.dal.getTickArray(nextTickArrayAddress, false); if (!nextTickArray) { break; } tickArrayAddresses[count] = nextTickArrayAddress; count++; currentStartTickIndex = nextStartTickIndex; } while (count < 3) { tickArrayAddresses[count] = (0, whirlpool_client_sdk_1.getTickArrayPda)(programId, poolAddress, currentStartTickIndex).publicKey; count++; } return tickArrayAddresses; }); } /*** Quotes ***/ /** * Construct a quote for opening a new position */ getOpenPositionQuote(param) { return __awaiter(this, void 0, void 0, function* () { const { poolAddress, tokenMint, tokenAmount, slippageTolerance, refresh } = param; const whirlpool = yield this.dal.getPool(poolAddress, refresh); if (!whirlpool) { throw new Error(`Whirlpool not found: ${(0, anchor_1.translateAddress)(poolAddress).toBase58()}`); } let tickLowerIndex = undefined; let tickUpperIndex = undefined; if ((0, types_1.isQuoteByTickIndex)(param)) { tickLowerIndex = param.tickLowerIndex; tickUpperIndex = param.tickUpperIndex; } else { (0, tiny_invariant_1.default)((0, types_1.isQuoteByPrice)(param), "invalid OpenPositionQuoteParam"); tickLowerIndex = tick_util_1.TickUtil.toValid((0, whirlpool_client_sdk_1.sqrtPriceX64ToTickIndex)((0, whirlpool_client_sdk_1.toX64)(param.priceLower.sqrt())), whirlpool.tickSpacing); tickUpperIndex = tick_util_1.TickUtil.toValid((0, whirlpool_client_sdk_1.sqrtPriceX64ToTickIndex)((0, whirlpool_client_sdk_1.toX64)(param.priceUpper.sqrt())), whirlpool.tickSpacing); } const internalParam = { tokenMintA: whirlpool.tokenMintA, tokenMintB: whirlpool.tokenMintB, tickCurrentIndex: whirlpool.tickCurrentIndex, sqrtPrice: whirlpool.sqrtPrice, inputTokenMint: (0, address_1.toPubKey)(tokenMint), inputTokenAmount: tokenAmount, tickLowerIndex, tickUpperIndex, slippageTolerance: slippageTolerance || defaults_1.defaultSlippagePercentage, }; return Object.assign({ poolAddress, tickLowerIndex, tickUpperIndex }, (0, add_liquidity_1.getAddLiquidityQuote)(internalParam)); }); } /** * Construct a quote for closing an existing position */ getClosePositionQuote(param) { return __awaiter(this, void 0, void 0, function* () { const { positionAddress, refresh, slippageTolerance } = param; const position = yield this.dal.getPosition(positionAddress, refresh); if (!position) { throw new Error(`Position not found: ${(0, anchor_1.translateAddress)(positionAddress).toBase58()}`); } const whirlpool = yield this.dal.getPool(position.whirlpool, refresh); if (!whirlpool) { throw new Error(`Whirlpool not found: ${(0, anchor_1.translateAddress)(position.whirlpool).toBase58()}`); } return (0, remove_liquidity_1.getRemoveLiquidityQuote)({ positionAddress: (0, address_1.toPubKey)(positionAddress), tickCurrentIndex: whirlpool.tickCurrentIndex, sqrtPrice: whirlpool.sqrtPrice, tickLowerIndex: position.tickLowerIndex, tickUpperIndex: position.tickUpperIndex, liquidity: position.liquidity, slippageTolerance: slippageTolerance || defaults_1.defaultSlippagePercentage, }); }); } /** * Construct a quote for swap */ getSwapQuote(param) { return __awaiter(this, void 0, void 0, function* () { const { poolAddress, tokenMint, tokenAmount, isInput, slippageTolerance = defaults_1.defaultSlippagePercentage, refresh, } = param; const whirlpool = yield this.dal.getPool(poolAddress, refresh); if (!whirlpool) { throw new Error(`Whirlpool not found: ${(0, anchor_1.translateAddress)(poolAddress).toBase58()}`); } const swapDirection = (0, address_1.toPubKey)(tokenMint).equals(whirlpool.tokenMintA) === isInput ? swap_quoter_1.SwapDirection.AtoB : swap_quoter_1.SwapDirection.BtoA; const amountSpecified = isInput ? swap_quoter_1.AmountSpecified.Input : swap_quoter_1.AmountSpecified.Output; const swapSimulator = new swap_quoter_1.SwapSimulator(); // Return sqrtPriceLimit const { amountIn, amountOut, sqrtPriceLimitX64 } = yield swapSimulator.simulateSwap({ refresh, dal: this.dal, poolAddress, whirlpoolData: whirlpool, amountSpecified, swapDirection, }, { amount: tokenAmount, currentSqrtPriceX64: whirlpool.sqrtPrice, currentTickIndex: whirlpool.tickCurrentIndex, currentLiquidity: whirlpool.liquidity, }); const otherAmountThreshold = (0, position_util_1.adjustAmountForSlippage)(amountIn, amountOut, slippageTolerance, amountSpecified); return { poolAddress, otherAmountThreshold, sqrtPriceLimitX64, amountIn, amountOut, aToB: swapDirection === swap_quoter_1.SwapDirection.AtoB, fixedInput: isInput, }; }); } } exports.OrcaPool = OrcaPool;