UNPKG

@orca-so/whirlpool-sdk

Version:

Whirlpool SDK for the Orca protocol.

216 lines (215 loc) 11.4 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; }; 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;