@orca-so/whirlpool-sdk
Version:
Whirlpool SDK for the Orca protocol.
536 lines (535 loc) • 29.6 kB
JavaScript
"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;