@orca-so/whirlpool-sdk
Version:
Whirlpool SDK for the Orca protocol.
516 lines (515 loc) • 30 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.WhirlpoolImpl = void 0;
const sdk_1 = require("@orca-so/sdk");
const whirlpool_client_sdk_1 = require("@orca-so/whirlpool-client-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 bn_js_1 = __importDefault(require("bn.js"));
const tiny_invariant_1 = __importDefault(require("tiny-invariant"));
const fees_and_rewards_1 = require("../position/txs/fees-and-rewards");
const address_1 = require("../utils/address");
const public_1 = require("../utils/public");
const ata_utils_1 = require("../utils/web3/ata-utils");
const pool_util_1 = require("../utils/whirlpool/pool-util");
const tick_util_1 = require("../utils/whirlpool/tick-util");
const liquidity_distribution_1 = require("./liquidity-distribution");
class WhirlpoolImpl {
constructor(ctx, address) {
this.ctx = ctx;
this.address = address;
}
getAddress() {
return this.address;
}
getAccount(refresh) {
return this.ctx.accountFetcher.getPool(this.address, refresh);
}
init(param) {
const { initSqrtPrice, tokenMintA, tokenMintB, tickSpacing } = param;
const programId = this.ctx.program.programId;
const client = new whirlpool_client_sdk_1.WhirlpoolClient(this.ctx);
// TODO: Ordering should be done by client-sdk
const [_tokenMintA, _tokenMintB] = pool_util_1.PoolUtil.orderMints(tokenMintA, tokenMintB);
const whirlpoolPda = (0, whirlpool_client_sdk_1.getWhirlpoolPda)(programId, this.ctx.configAddress, (0, address_1.toPubKey)(tokenMintA), (0, address_1.toPubKey)(tokenMintB), tickSpacing);
// TODO: Handle missing feeTier PDA
const feeTierPda = (0, whirlpool_client_sdk_1.getFeeTierPda)(programId, this.ctx.configAddress, tickSpacing);
const tx = client.initPoolTx({
initSqrtPrice,
whirlpoolConfigKey: this.ctx.configAddress,
tokenMintA: (0, address_1.toPubKey)(tokenMintA),
tokenMintB: (0, address_1.toPubKey)(tokenMintB),
whirlpoolPda,
tokenVaultAKeypair: web3_js_1.Keypair.generate(),
tokenVaultBKeypair: web3_js_1.Keypair.generate(),
tickSpacing,
feeTierKey: feeTierPda.publicKey,
funder: this.ctx.provider.wallet.publicKey,
});
return { tx, address: whirlpoolPda.publicKey };
}
setFeeRate(feeRate) {
return __awaiter(this, void 0, void 0, function* () {
const client = new whirlpool_client_sdk_1.WhirlpoolClient(this.ctx);
const whirlpoolsConfigAccount = yield this.ctx.accountFetcher.getConfig(this.ctx.configAddress, true);
(0, tiny_invariant_1.default)(!!whirlpoolsConfigAccount, `Whirlpool config doesn't exist ${this.ctx.configAddress.toBase58()}`);
return client.setFeeRateIx({
whirlpool: this.address,
whirlpoolsConfig: this.ctx.configAddress,
feeAuthority: whirlpoolsConfigAccount.feeAuthority,
feeRate,
});
});
}
setProtocolFeeRate(protocolFeeRate) {
return __awaiter(this, void 0, void 0, function* () {
const client = new whirlpool_client_sdk_1.WhirlpoolClient(this.ctx);
const whirlpoolsConfigAccount = yield this.ctx.accountFetcher.getConfig(this.ctx.configAddress, true);
(0, tiny_invariant_1.default)(!!whirlpoolsConfigAccount, `Whirlpool config doesn't exist ${this.ctx.configAddress.toBase58()}`);
return client.setProtocolFeeRateIx({
whirlpool: this.address,
whirlpoolsConfig: this.ctx.configAddress,
feeAuthority: whirlpoolsConfigAccount.feeAuthority,
protocolFeeRate,
});
});
}
collectProtocolFee() {
return __awaiter(this, void 0, void 0, function* () {
const client = new whirlpool_client_sdk_1.WhirlpoolClient(this.ctx);
const whirlpool = yield this.ctx.accountFetcher.getPool(this.address, true);
(0, tiny_invariant_1.default)(!!whirlpool, "Whirlpool does not exist");
const _a = yield (0, ata_utils_1.resolveOrCreateATA)(this.ctx.provider.connection, this.ctx.provider.wallet.publicKey, whirlpool.tokenMintA), { address: tokenDestinationA } = _a, createTokenAAtaIx = __rest(_a, ["address"]);
const _b = yield (0, ata_utils_1.resolveOrCreateATA)(this.ctx.provider.connection, this.ctx.provider.wallet.publicKey, whirlpool.tokenMintB), { address: tokenDestinationB } = _b, createTokenBAtaIx = __rest(_b, ["address"]);
const collectFeesIx = client
.collectProtocolFeesTx({
whirlpoolsConfig: this.ctx.configAddress,
whirlpool: this.address,
collectProtocolFeesAuthority: this.ctx.provider.wallet.publicKey,
tokenVaultA: whirlpool.tokenVaultA,
tokenVaultB: whirlpool.tokenVaultB,
tokenDestinationA: (0, address_1.toPubKey)(tokenDestinationA),
tokenDestinationB: (0, address_1.toPubKey)(tokenDestinationB),
})
.compressIx(false);
return new whirlpool_client_sdk_1.TransactionBuilder(this.ctx.provider)
.addInstruction(createTokenAAtaIx)
.addInstruction(createTokenBAtaIx)
.addInstruction(collectFeesIx);
});
}
initReward(param) {
const { rewardAuthority, rewardMint, rewardIndex } = param;
const client = new whirlpool_client_sdk_1.WhirlpoolClient(this.ctx);
(0, tiny_invariant_1.default)(rewardIndex < whirlpool_client_sdk_1.NUM_REWARDS, "invalid rewardIndex");
const rewardVaultKeypair = web3_js_1.Keypair.generate();
const tx = client.initializeRewardTx({
rewardAuthority: (0, address_1.toPubKey)(rewardAuthority),
funder: this.ctx.provider.wallet.publicKey,
whirlpool: this.address,
rewardMint: (0, address_1.toPubKey)(rewardMint),
rewardVaultKeypair,
rewardIndex,
});
return { tx, rewardVault: rewardVaultKeypair.publicKey };
}
setRewardAuthority(newRewardAuthority, rewardIndex) {
const client = new whirlpool_client_sdk_1.WhirlpoolClient(this.ctx);
(0, tiny_invariant_1.default)(rewardIndex < whirlpool_client_sdk_1.NUM_REWARDS, "invalid rewardIndex");
return client.setRewardAuthorityTx({
whirlpool: this.address,
rewardAuthority: this.ctx.provider.wallet.publicKey,
newRewardAuthority: (0, address_1.toPubKey)(newRewardAuthority),
rewardIndex,
});
}
setRewardEmissions(rewardIndex, emissionsPerSecondX64) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
const client = new whirlpool_client_sdk_1.WhirlpoolClient(this.ctx);
(0, tiny_invariant_1.default)(rewardIndex < whirlpool_client_sdk_1.NUM_REWARDS, "invalid rewardIndex");
const whirlpool = yield this.ctx.accountFetcher.getPool(this.address, true);
const rewardVault = (_a = whirlpool === null || whirlpool === void 0 ? void 0 : whirlpool.rewardInfos[rewardIndex]) === null || _a === void 0 ? void 0 : _a.vault;
(0, tiny_invariant_1.default)(!!rewardVault, "reward vault doeos not exist");
return client.setRewardEmissionsTx({
rewardAuthority: this.ctx.provider.wallet.publicKey,
whirlpool: this.address,
rewardIndex,
emissionsPerSecondX64,
rewardVault,
});
});
}
getLiquidityDistribution(tickLower, tickUpper, refresh = true) {
return __awaiter(this, void 0, void 0, function* () {
return (0, liquidity_distribution_1.getLiquidityDistribution)(this.ctx, this.address, tickLower, tickUpper, refresh);
});
}
/**
* Construct a transaction for opening an new position
*/
openPosition(quote) {
return __awaiter(this, void 0, void 0, function* () {
return this.getOpenPositionWithOptMetadataTx(quote);
});
}
getOpenPositionWithMetadataTx(quote) {
return __awaiter(this, void 0, void 0, function* () {
return this.getOpenPositionWithOptMetadataTx(quote, true);
});
}
getOpenPositionWithOptMetadataTx(quote, withMetadata = false) {
return __awaiter(this, void 0, void 0, function* () {
const { maxTokenA, maxTokenB, liquidity, tickLowerIndex, tickUpperIndex, poolAddress } = quote;
(0, tiny_invariant_1.default)(liquidity.gt(new spl_token_1.u64(0)), "liquidity must be greater than zero");
const client = new whirlpool_client_sdk_1.WhirlpoolClient(this.ctx);
const whirlpool = yield this.ctx.accountFetcher.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.ctx.program.programId, positionMintKeypair.publicKey);
const metadataPda = (0, whirlpool_client_sdk_1.getPositionMetadataPda)(positionMintKeypair.publicKey);
const positionTokenAccountAddress = yield (0, ata_utils_1.deriveATA)(this.ctx.provider.wallet.publicKey, positionMintKeypair.publicKey);
const txBuilder = new whirlpool_client_sdk_1.TransactionBuilder(this.ctx.provider);
const preTxBuilder = new whirlpool_client_sdk_1.TransactionBuilder(this.ctx.provider);
const positionIx = (withMetadata ? client.openPositionWithMetadataTx : client.openPositionTx)
.bind(client)({
funder: this.ctx.provider.wallet.publicKey,
ownerKey: this.ctx.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 _a = yield (0, ata_utils_1.resolveOrCreateATA)(this.ctx.provider.connection, this.ctx.provider.wallet.publicKey, whirlpool.tokenMintA, maxTokenA), { address: tokenOwnerAccountA } = _a, tokenOwnerAccountAIx = __rest(_a, ["address"]);
const _b = yield (0, ata_utils_1.resolveOrCreateATA)(this.ctx.provider.connection, this.ctx.provider.wallet.publicKey, whirlpool.tokenMintB, maxTokenB), { 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.ctx.program.programId);
const tickArrayUpperPda = tick_util_1.TickUtil.getPdaWithTickIndex(tickUpperIndex, whirlpool.tickSpacing, poolAddress, this.ctx.program.programId);
const [tickArrayLower, tickArrayUpper] = yield this.ctx.accountFetcher.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: this.ctx.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: this.ctx.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: this.ctx.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 public_1.MultiTransactionBuilder(this.ctx.provider, []);
if (requirePreTx) {
tx.addTxBuilder(preTxBuilder);
}
tx.addTxBuilder(txBuilder);
return {
mint: positionMintKeypair.publicKey,
tx,
};
});
}
initTickArray(startTick) {
return __awaiter(this, void 0, void 0, function* () {
const client = new whirlpool_client_sdk_1.WhirlpoolClient(this.ctx);
const whirlpoolAddress = (0, anchor_1.translateAddress)(this.address);
const tickArrayPda = (0, whirlpool_client_sdk_1.getTickArrayPda)(this.ctx.program.programId, whirlpoolAddress, startTick);
// TODO: Where can we allow the user to pass in funder?
return client.initTickArrayTx({
startTick,
tickArrayPda,
whirlpool: whirlpoolAddress,
funder: this.ctx.provider.wallet.publicKey,
});
});
}
closePosition(quote) {
return __awaiter(this, void 0, void 0, function* () {
const client = new whirlpool_client_sdk_1.WhirlpoolClient(this.ctx);
const position = yield this.ctx.accountFetcher.getPosition(quote.positionAddress, true);
if (!position) {
throw new Error(`Position not found: ${(0, anchor_1.translateAddress)(quote.positionAddress).toBase58()}`);
}
const whirlpool = yield this.ctx.accountFetcher.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.ctx.program.programId).publicKey;
const tickArrayUpper = tick_util_1.TickUtil.getPdaWithTickIndex(position.tickUpperIndex, whirlpool.tickSpacing, position.whirlpool, this.ctx.program.programId).publicKey;
const positionTokenAccount = yield (0, ata_utils_1.deriveATA)(this.ctx.provider.wallet.publicKey, position.positionMint);
const txBuilder = new whirlpool_client_sdk_1.TransactionBuilder(this.ctx.provider);
const resolvedAssociatedTokenAddresses = {};
const _a = yield (0, ata_utils_1.resolveOrCreateATA)(this.ctx.provider.connection, this.ctx.provider.wallet.publicKey, whirlpool.tokenMintA), { address: tokenOwnerAccountA } = _a, createTokenOwnerAccountAIx = __rest(_a, ["address"]);
const _b = yield (0, ata_utils_1.resolveOrCreateATA)(this.ctx.provider.connection, this.ctx.provider.wallet.publicKey, whirlpool.tokenMintB), { 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.ctx, {
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: this.ctx.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: this.ctx.provider.wallet.publicKey,
receiver: this.ctx.provider.wallet.publicKey,
positionTokenAccount,
position: (0, address_1.toPubKey)(quote.positionAddress),
positionMint: position.positionMint,
})
.compressIx(false);
txBuilder.addInstruction(positionIx);
return txBuilder;
});
}
getLowestInitializedTickArrayTickIndex(ctx, 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, ctx.program.programId, offset);
// Throttle to prevent being rate-limited
yield new Promise((resolve) => setTimeout(resolve, 1000));
const tickArray = yield ctx.accountFetcher.getTickArray(tickArrayPda.publicKey, false);
if (!tickArray) {
offset++;
continue;
}
return tick_util_1.TickUtil.getStartTickIndex(whirlpool_client_sdk_1.MIN_TICK_INDEX, tickSpacing, offset);
}
});
}
getHighestInitializedTickArrayTickIndex(ctx, 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, ctx.program.programId, offset);
yield new Promise((resolve) => setTimeout(resolve, 1000));
const tickArray = yield ctx.accountFetcher.getTickArray(tickArrayPda.publicKey, false);
if (!tickArray) {
offset--;
continue;
}
return tick_util_1.TickUtil.getStartTickIndex(whirlpool_client_sdk_1.MAX_TICK_INDEX, tickSpacing, offset);
}
});
}
initTickArrayGap() {
return __awaiter(this, void 0, void 0, function* () {
const client = new whirlpool_client_sdk_1.WhirlpoolClient(this.ctx);
const whirlpool = yield this.ctx.accountFetcher.getPool(this.address, true);
if (!whirlpool) {
throw new Error(`Whirlpool not found: ${(0, anchor_1.translateAddress)(this.address).toBase58()}`);
}
const firstTickIndex = yield this.getLowestInitializedTickArrayTickIndex(this.ctx, this.address, whirlpool.tickSpacing);
const lastTickIndex = yield this.getHighestInitializedTickArrayTickIndex(this.ctx, this.address, whirlpool.tickSpacing);
// get all lowest and highest tick array
let numIxs = 0;
let txBuilder = new whirlpool_client_sdk_1.TransactionBuilder(this.ctx.provider);
const multiTxBuilder = new public_1.MultiTransactionBuilder(this.ctx.provider, []);
let offset = 1;
while (true) {
const tickArrayPda = tick_util_1.TickUtil.getPdaWithTickIndex(firstTickIndex, whirlpool.tickSpacing, this.address, this.ctx.program.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.ctx.accountFetcher.getTickArray(tickArrayPda.publicKey, false);
if (!tickArray) {
txBuilder.addInstruction(client
.initTickArrayTx({
whirlpool: (0, address_1.toPubKey)(this.address),
tickArrayPda,
startTick,
funder: this.ctx.provider.wallet.publicKey,
})
.compressIx(false));
numIxs++;
if (!(numIxs % 7)) {
multiTxBuilder.addTxBuilder(txBuilder);
txBuilder = new whirlpool_client_sdk_1.TransactionBuilder(this.ctx.provider);
}
}
offset++;
}
if (numIxs % 7) {
multiTxBuilder.addTxBuilder(txBuilder);
}
return multiTxBuilder;
});
}
/**
* Construct a transaction for a swap
*/
swap(quote) {
return __awaiter(this, void 0, void 0, function* () {
const { sqrtPriceLimitX64, otherAmountThreshold, amountIn, amountOut, aToB, fixedInput, poolAddress, } = quote;
const client = new whirlpool_client_sdk_1.WhirlpoolClient(this.ctx);
const whirlpool = yield this.ctx.accountFetcher.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(this.ctx.provider);
const _a = yield (0, ata_utils_1.resolveOrCreateATA)(this.ctx.provider.connection, this.ctx.provider.wallet.publicKey, whirlpool.tokenMintA, aToB ? amountIn : sdk_1.ZERO), { address: tokenOwnerAccountA } = _a, tokenOwnerAccountAIx = __rest(_a, ["address"]);
txBuilder.addInstruction(tokenOwnerAccountAIx);
const _b = yield (0, ata_utils_1.resolveOrCreateATA)(this.ctx.provider.connection, this.ctx.provider.wallet.publicKey, whirlpool.tokenMintB, !aToB ? amountIn : sdk_1.ZERO), { address: tokenOwnerAccountB } = _b, tokenOwnerAccountBIx = __rest(_b, ["address"]);
txBuilder.addInstruction(tokenOwnerAccountBIx);
const targetSqrtPriceLimitX64 = sqrtPriceLimitX64 || this.getDefaultSqrtPriceLimit(aToB);
const tickArrayAddresses = yield this.getTickArrayPublicKeysForSwap(this.ctx, whirlpool.sqrtPrice, targetSqrtPriceLimitX64, whirlpool.tickSpacing, (0, address_1.toPubKey)(poolAddress), this.ctx.program.programId);
const oraclePda = (0, whirlpool_client_sdk_1.getOraclePda)(this.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: this.ctx.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 public_1.MultiTransactionBuilder(this.ctx.provider, [txBuilder]);
});
}
getDefaultSqrtPriceLimit(aToB) {
return new bn_js_1.default(aToB ? whirlpool_client_sdk_1.MIN_SQRT_PRICE : whirlpool_client_sdk_1.MAX_SQRT_PRICE);
}
getTickArrayPublicKeysForSwap(ctx, currentSqrtPriceX64, targetSqrtPriceX64, tickSpacing, poolAddress, programId) {
return __awaiter(this, void 0, void 0, function* () {
const currentTickIndex = (0, whirlpool_client_sdk_1.sqrtPriceX64ToTickIndex)(currentSqrtPriceX64);
const targetTickIndex = (0, whirlpool_client_sdk_1.sqrtPriceX64ToTickIndex)(targetSqrtPriceX64);
let currentStartTickIndex = tick_util_1.TickUtil.getStartTickIndex(currentTickIndex, tickSpacing);
const targetStartTickIndex = tick_util_1.TickUtil.getStartTickIndex(targetTickIndex, tickSpacing);
const offset = currentTickIndex < 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(currentTickIndex, tickSpacing, offset * count);
const nextTickArrayAddress = (0, whirlpool_client_sdk_1.getTickArrayPda)(programId, poolAddress, nextStartTickIndex).publicKey;
const nextTickArray = yield ctx.accountFetcher.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;
});
}
setRewardAuthorityBySuperAuthority(newRewardAuthority, rewardIndex) {
(0, tiny_invariant_1.default)(rewardIndex < whirlpool_client_sdk_1.NUM_REWARDS, "invalid rewardIndex");
const client = new whirlpool_client_sdk_1.WhirlpoolClient(this.ctx);
return client.setRewardAuthorityBySuperAuthorityTx({
whirlpoolsConfig: this.ctx.configAddress,
whirlpool: this.address,
rewardEmissionsSuperAuthority: this.ctx.provider.wallet.publicKey,
newRewardAuthority: (0, address_1.toPubKey)(newRewardAuthority),
rewardIndex,
});
}
}
exports.WhirlpoolImpl = WhirlpoolImpl;