@orca-so/whirlpool-sdk
Version:
Whirlpool SDK for the Orca protocol.
216 lines (215 loc) • 11.4 kB
JavaScript
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;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.OrcaPosition = void 0;
const common_sdk_1 = require("@orca-so/common-sdk");
const defaults_1 = require("../constants/public/defaults");
const tick_util_1 = require("../utils/whirlpool/tick-util");
const add_liquidity_1 = require("./quotes/add-liquidity");
const remove_liquidity_1 = require("./quotes/remove-liquidity");
const anchor_1 = require("@project-serum/anchor");
const address_1 = require("../utils/address");
const whirlpool_client_sdk_1 = require("@orca-so/whirlpool-client-sdk");
const fees_and_rewards_1 = require("./txs/fees-and-rewards");
class OrcaPosition {
constructor(dal) {
this.dal = dal;
}
/*** Utilities ***/
/**
* Derive the position pda given position mint
*
* @param positionMint
* @returns
*/
derivePDA(positionMint) {
return (0, whirlpool_client_sdk_1.getPositionPda)(this.dal.programId, (0, address_1.toPubKey)(positionMint));
}
/*** Transactions ***/
/**
* Construct a transaction for adding liquidity to an existing pool
*/
getAddLiquidityTx(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, false);
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, tickArrayUpper] = tick_util_1.TickUtil.getLowerAndUpperTickArrayAddresses(position.tickLowerIndex, position.tickUpperIndex, whirlpool.tickSpacing, position.whirlpool, this.dal.programId);
const positionTokenAccount = yield (0, common_sdk_1.deriveATA)(provider.wallet.publicKey, position.positionMint);
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: quote.maxTokenA },
{ tokenMint: whirlpool.tokenMintB, wrappedSolAmountIn: quote.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 addLiquidityIx = client
.increaseLiquidityTx({
liquidityAmount: quote.liquidity,
tokenMaxA: quote.maxTokenA,
tokenMaxB: quote.maxTokenB,
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(addLiquidityIx);
return txBuilder;
});
}
/**
* Construct a transaction for removing liquidity from an existing pool
*/
getRemoveLiquidityTx(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, false);
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, tickArrayUpper] = tick_util_1.TickUtil.getLowerAndUpperTickArrayAddresses(position.tickLowerIndex, position.tickUpperIndex, whirlpool.tickSpacing, position.whirlpool, this.dal.programId);
const positionTokenAccount = yield (0, common_sdk_1.deriveATA)(provider.wallet.publicKey, position.positionMint);
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 }, { tokenMint: whirlpool.tokenMintB }], () => 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 removeLiquidityIx = client
.decreaseLiquidityTx({
liquidityAmount: quote.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(removeLiquidityIx);
return txBuilder;
});
}
/**
* Construct a transaction for collecting fees and rewards from an existing pool
*/
getCollectFeesAndRewardsTx(param) {
return __awaiter(this, void 0, void 0, function* () {
return (0, fees_and_rewards_1.buildCollectFeesAndRewardsTx)(this.dal, {
provider: param.provider,
positionAddress: param.positionAddress,
});
});
}
/**
* Construct a transaction for collecting fees and rewards from a list of existing pools
*/
getCollectMultipleFeesAndRewardsTx(param) {
return __awaiter(this, void 0, void 0, function* () {
return (0, fees_and_rewards_1.buildMultipleCollectFeesAndRewardsTx)(this.dal, param);
});
}
/*** Quotes ***/
/**
* Construct a quote for adding liquidity to an existing pool
*/
getAddLiquidityQuote(param) {
return __awaiter(this, void 0, void 0, function* () {
const { positionAddress, tokenMint, tokenAmount, 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()}`);
}
const internalParam = {
tokenMintA: whirlpool.tokenMintA,
tokenMintB: whirlpool.tokenMintB,
tickCurrentIndex: whirlpool.tickCurrentIndex,
sqrtPrice: whirlpool.sqrtPrice,
inputTokenMint: (0, address_1.toPubKey)(tokenMint),
inputTokenAmount: tokenAmount,
tickLowerIndex: position.tickLowerIndex,
tickUpperIndex: position.tickUpperIndex,
slippageTolerance: slippageTolerance || defaults_1.defaultSlippagePercentage,
};
return Object.assign({ positionAddress }, (0, add_liquidity_1.getAddLiquidityQuote)(internalParam));
});
}
/**
* Construct a quote for removing liquidity from an existing pool
*/
getRemoveLiquidityQuote(param) {
return __awaiter(this, void 0, void 0, function* () {
const { positionAddress, liquidity, refresh, slippageTolerance } = param;
const position = yield this.dal.getPosition(positionAddress, refresh);
if (!position) {
throw new Error(`Position not found: {$translateAddress(positionAddress).toBase58()}`);
}
const whirlpool = yield this.dal.getPool(position.whirlpool, refresh);
if (!whirlpool) {
throw new Error(`Whirlpool not found: {$translateAddress(poolAddress).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,
slippageTolerance: slippageTolerance || defaults_1.defaultSlippagePercentage,
});
});
}
}
exports.OrcaPosition = OrcaPosition;
;