Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@orca-so/whirlpools-sdk

Package Overview
Dependencies
Maintainers
4
Versions
87
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@orca-so/whirlpools-sdk - npm Package Compare versions

Comparing version 0.6.1 to 0.7.1

dist/instructions/composites/resolve-atas-ix.d.ts

13

dist/impl/position-impl.d.ts

@@ -6,3 +6,3 @@ import { TransactionBuilder } from "@orca-so/common-sdk";

import { DecreaseLiquidityInput, IncreaseLiquidityInput } from "../instructions";
import { PositionData } from "../types/public";
import { PositionData, TickArrayData, TickData, WhirlpoolData } from "../types/public";
import { Position } from "../whirlpool-client";

@@ -13,9 +13,18 @@ export declare class PositionImpl implements Position {

private data;
constructor(ctx: WhirlpoolContext, address: PublicKey, data: PositionData);
private whirlpoolData;
private lowerTickArrayData;
private upperTickArrayData;
constructor(ctx: WhirlpoolContext, address: PublicKey, data: PositionData, whirlpoolData: WhirlpoolData, lowerTickArrayData: TickArrayData, upperTickArrayData: TickArrayData);
getAddress(): PublicKey;
getData(): PositionData;
getWhirlpoolData(): WhirlpoolData;
getLowerTickData(): TickData;
getUpperTickData(): TickData;
refreshData(): Promise<PositionData>;
increaseLiquidity(liquidityInput: IncreaseLiquidityInput, resolveATA?: boolean, sourceWallet?: Address, positionWallet?: Address, ataPayer?: Address): Promise<TransactionBuilder>;
decreaseLiquidity(liquidityInput: DecreaseLiquidityInput, resolveATA?: boolean, sourceWallet?: Address, positionWallet?: Address, ataPayer?: Address): Promise<TransactionBuilder>;
collectFees(updateFeesAndRewards?: boolean, resolveATA?: boolean, destinationWallet?: Address, positionWallet?: Address, ataPayer?: Address, refresh?: boolean): Promise<TransactionBuilder>;
collectRewards(rewardsToCollect?: Address[], updateFeesAndRewards?: boolean, resolveATA?: boolean, destinationWallet?: Address, positionWallet?: Address, ataPayer?: Address, refresh?: boolean): Promise<TransactionBuilder>;
private refresh;
private updateFeesAndRewards;
}

@@ -26,8 +26,13 @@ "use strict";

const instructions_1 = require("../instructions");
const position_builder_util_1 = require("../utils/builder/position-builder-util");
const public_1 = require("../utils/public");
const whirlpool_ata_utils_1 = require("../utils/whirlpool-ata-utils");
class PositionImpl {
constructor(ctx, address, data) {
constructor(ctx, address, data, whirlpoolData, lowerTickArrayData, upperTickArrayData) {
this.ctx = ctx;
this.address = address;
this.data = data;
this.whirlpoolData = whirlpoolData;
this.lowerTickArrayData = lowerTickArrayData;
this.upperTickArrayData = upperTickArrayData;
}

@@ -40,2 +45,11 @@ getAddress() {

}
getWhirlpoolData() {
return this.whirlpoolData;
}
getLowerTickData() {
return public_1.TickArrayUtil.getTickFromArray(this.lowerTickArrayData, this.data.tickLowerIndex, this.whirlpoolData.tickSpacing);
}
getUpperTickData() {
return public_1.TickArrayUtil.getTickFromArray(this.upperTickArrayData, this.data.tickUpperIndex, this.whirlpoolData.tickSpacing);
}
refreshData() {

@@ -122,11 +136,133 @@ return __awaiter(this, void 0, void 0, function* () {

}
collectFees(updateFeesAndRewards = true, resolveATA = true, destinationWallet, positionWallet, ataPayer, refresh = false) {
return __awaiter(this, void 0, void 0, function* () {
const [destinationWalletKey, positionWalletKey, ataPayerKey] = common_sdk_1.AddressUtil.toPubKeys([
destinationWallet !== null && destinationWallet !== void 0 ? destinationWallet : this.ctx.wallet.publicKey,
positionWallet !== null && positionWallet !== void 0 ? positionWallet : this.ctx.wallet.publicKey,
ataPayer !== null && ataPayer !== void 0 ? ataPayer : this.ctx.wallet.publicKey,
]);
const whirlpool = yield this.ctx.fetcher.getPool(this.data.whirlpool, refresh);
if (!whirlpool) {
throw new Error(`Unable to fetch whirlpool (${this.data.whirlpool}) for this position (${this.address}).`);
}
let txBuilder = new common_sdk_1.TransactionBuilder(this.ctx.provider.connection, this.ctx.provider.wallet);
const accountExemption = yield this.ctx.fetcher.getAccountRentExempt();
const { ataTokenAddresses, resolveAtaIxs } = yield (0, whirlpool_ata_utils_1.resolveAtaForMints)(this.ctx, {
mints: [whirlpool.tokenMintA, whirlpool.tokenMintB],
accountExemption,
receiver: destinationWalletKey,
payer: ataPayerKey,
});
const tokenOwnerAccountA = ataTokenAddresses[whirlpool.tokenMintA.toBase58()];
const tokenOwnerAccountB = ataTokenAddresses[whirlpool.tokenMintB.toBase58()];
if (resolveATA) {
txBuilder.addInstructions(resolveAtaIxs);
}
const positionTokenAccount = yield (0, common_sdk_1.deriveATA)(positionWalletKey, this.data.positionMint);
if (updateFeesAndRewards) {
const updateIx = yield this.updateFeesAndRewards();
txBuilder.addInstruction(updateIx);
}
const ix = (0, instructions_1.collectFeesIx)(this.ctx.program, {
whirlpool: this.data.whirlpool,
position: this.address,
positionTokenAccount,
tokenOwnerAccountA,
tokenOwnerAccountB,
tokenVaultA: whirlpool.tokenVaultA,
tokenVaultB: whirlpool.tokenVaultB,
positionAuthority: positionWalletKey,
});
txBuilder.addInstruction(ix);
return txBuilder;
});
}
collectRewards(rewardsToCollect, updateFeesAndRewards = true, resolveATA = true, destinationWallet, positionWallet, ataPayer, refresh = true) {
return __awaiter(this, void 0, void 0, function* () {
const [destinationWalletKey, positionWalletKey, ataPayerKey] = common_sdk_1.AddressUtil.toPubKeys([
destinationWallet !== null && destinationWallet !== void 0 ? destinationWallet : this.ctx.wallet.publicKey,
positionWallet !== null && positionWallet !== void 0 ? positionWallet : this.ctx.wallet.publicKey,
ataPayer !== null && ataPayer !== void 0 ? ataPayer : this.ctx.wallet.publicKey,
]);
const whirlpool = yield this.ctx.fetcher.getPool(this.data.whirlpool, refresh);
if (!whirlpool) {
throw new Error(`Unable to fetch whirlpool (${this.data.whirlpool}) for this position (${this.address}).`);
}
const initializedRewards = whirlpool.rewardInfos.filter((info) => public_1.PoolUtil.isRewardInitialized(info));
const txBuilder = new common_sdk_1.TransactionBuilder(this.ctx.provider.connection, this.ctx.provider.wallet);
const accountExemption = yield this.ctx.fetcher.getAccountRentExempt();
const { ataTokenAddresses, resolveAtaIxs } = yield (0, whirlpool_ata_utils_1.resolveAtaForMints)(this.ctx, {
mints: initializedRewards.map((r) => r.mint),
accountExemption,
receiver: destinationWalletKey,
payer: ataPayerKey,
});
if (resolveATA) {
txBuilder.addInstructions(resolveAtaIxs);
}
const positionTokenAccount = yield (0, common_sdk_1.deriveATA)(positionWalletKey, this.data.positionMint);
if (updateFeesAndRewards) {
const updateIx = yield this.updateFeesAndRewards();
txBuilder.addInstruction(updateIx);
}
initializedRewards.forEach((info, index) => {
if (rewardsToCollect &&
!rewardsToCollect.some((r) => r.toString() === info.mint.toBase58())) {
// If rewardsToCollect is specified and this reward is not in it,
// don't include collectIX for that in TX
return;
}
const ix = (0, instructions_1.collectRewardIx)(this.ctx.program, {
whirlpool: this.data.whirlpool,
position: this.address,
positionTokenAccount,
rewardIndex: index,
rewardOwnerAccount: ataTokenAddresses[info.mint.toBase58()],
rewardVault: info.vault,
positionAuthority: positionWalletKey,
});
txBuilder.addInstruction(ix);
});
return txBuilder;
});
}
refresh() {
return __awaiter(this, void 0, void 0, function* () {
const account = yield this.ctx.fetcher.getPosition(this.address, true);
if (!!account) {
this.data = account;
const positionAccount = yield this.ctx.fetcher.getPosition(this.address, true);
if (!!positionAccount) {
this.data = positionAccount;
}
const whirlpoolAccount = yield this.ctx.fetcher.getPool(this.data.whirlpool, true);
if (!!whirlpoolAccount) {
this.whirlpoolData = whirlpoolAccount;
}
const [lowerTickArray, upperTickArray] = yield (0, position_builder_util_1.getTickArrayDataForPosition)(this.ctx, this.data, this.whirlpoolData, true);
if (lowerTickArray) {
this.lowerTickArrayData = lowerTickArray;
}
if (upperTickArray) {
this.upperTickArrayData = upperTickArray;
}
});
}
updateFeesAndRewards() {
return __awaiter(this, void 0, void 0, function* () {
const whirlpool = yield this.ctx.fetcher.getPool(this.data.whirlpool);
if (!whirlpool) {
throw new Error(`Unable to fetch whirlpool (${this.data.whirlpool}) for this position (${this.address}).`);
}
const [tickArrayLowerPda, tickArrayUpperPda] = [
this.data.tickLowerIndex,
this.data.tickUpperIndex,
].map((tickIndex) => public_1.PDAUtil.getTickArrayFromTickIndex(tickIndex, whirlpool.tickSpacing, this.data.whirlpool, this.ctx.program.programId));
const updateIx = (0, instructions_1.updateFeesAndRewardsIx)(this.ctx.program, {
whirlpool: this.data.whirlpool,
position: this.address,
tickArrayLower: tickArrayLowerPda.publicKey,
tickArrayUpper: tickArrayUpperPda.publicKey,
});
return updateIx;
});
}
}
exports.PositionImpl = PositionImpl;

@@ -22,2 +22,3 @@ "use strict";

const ix_1 = require("../ix");
const position_builder_util_1 = require("../utils/builder/position-builder-util");
const public_1 = require("../utils/public");

@@ -88,3 +89,11 @@ const position_impl_1 = require("./position-impl");

}
return new position_impl_1.PositionImpl(this.ctx, common_sdk_1.AddressUtil.toPubKey(positionAddress), account);
const whirlAccount = yield this.ctx.fetcher.getPool(account.whirlpool, refresh);
if (!whirlAccount) {
throw new Error(`Unable to fetch Whirlpool for Position at address at ${positionAddress}`);
}
const [lowerTickArray, upperTickArray] = yield (0, position_builder_util_1.getTickArrayDataForPosition)(this.ctx, account, whirlAccount, refresh);
if (!lowerTickArray || !upperTickArray) {
throw new Error(`Unable to fetch TickArrays for Position at address at ${positionAddress}`);
}
return new position_impl_1.PositionImpl(this.ctx, common_sdk_1.AddressUtil.toPubKey(positionAddress), account, whirlAccount, lowerTickArray, upperTickArray);
});

@@ -94,10 +103,31 @@ }

return __awaiter(this, void 0, void 0, function* () {
const accounts = yield this.ctx.fetcher.listPositions(positionAddresses, refresh);
const results = accounts.map((positionAccount, index) => {
const address = positionAddresses[index];
if (!positionAccount) {
return [address, null];
// TODO: Prefetch and use fetcher as a cache - Think of a cleaner way to prefetch
const positions = yield this.ctx.fetcher.listPositions(positionAddresses, refresh);
const whirlpoolAddrs = positions
.map((position) => position === null || position === void 0 ? void 0 : position.whirlpool.toBase58())
.flatMap((x) => (!!x ? x : []));
yield this.ctx.fetcher.listPools(whirlpoolAddrs, refresh);
const tickArrayAddresses = new Set();
yield Promise.all(positions.map((pos) => __awaiter(this, void 0, void 0, function* () {
if (pos) {
const pool = yield this.ctx.fetcher.getPool(pos.whirlpool, false);
if (pool) {
const lowerTickArrayPda = public_1.PDAUtil.getTickArrayFromTickIndex(pos.tickLowerIndex, pool.tickSpacing, pos.whirlpool, this.ctx.program.programId).publicKey;
const upperTickArrayPda = public_1.PDAUtil.getTickArrayFromTickIndex(pos.tickUpperIndex, pool.tickSpacing, pos.whirlpool, this.ctx.program.programId).publicKey;
tickArrayAddresses.add(lowerTickArrayPda);
tickArrayAddresses.add(upperTickArrayPda);
}
}
return [address, new position_impl_1.PositionImpl(this.ctx, common_sdk_1.AddressUtil.toPubKey(address), positionAccount)];
});
})));
yield this.ctx.fetcher.listTickArrays(Array.from(tickArrayAddresses), true);
// Use getPosition and the prefetched values to generate the Positions
const results = yield Promise.all(positionAddresses.map((pos) => __awaiter(this, void 0, void 0, function* () {
try {
const position = yield this.getPosition(pos, false);
return [pos, position];
}
catch (_a) {
return [pos, null];
}
})));
return Object.fromEntries(results);

@@ -104,0 +134,0 @@ });

4

dist/impl/whirlpool-impl.d.ts

@@ -35,3 +35,3 @@ import { Percentage, TransactionBuilder } from "@orca-so/common-sdk";

initTickArrayForTicks(ticks: number[], funder?: Address, refresh?: boolean): Promise<TransactionBuilder | null>;
closePosition(positionAddress: Address, slippageTolerance: Percentage, destinationWallet?: Address, positionWallet?: Address, payer?: Address): Promise<TransactionBuilder>;
closePosition(positionAddress: Address, slippageTolerance: Percentage, destinationWallet?: Address, positionWallet?: Address, payer?: Address): Promise<TransactionBuilder[]>;
swap(quote: SwapInput, sourceWallet?: Address): Promise<TransactionBuilder>;

@@ -46,5 +46,5 @@ swapWithDevFees(quote: DevFeeSwapInput, devFeeWallet: PublicKey, wallet?: PublicKey | undefined, payer?: PublicKey | undefined): Promise<TransactionBuilder>;

}>;
getClosePositionIx(positionAddress: PublicKey, slippageTolerance: Percentage, destinationWallet: PublicKey, positionWallet: PublicKey, payerKey: PublicKey): Promise<TransactionBuilder>;
getClosePositionIx(positionAddress: PublicKey, slippageTolerance: Percentage, destinationWallet: PublicKey, positionWallet: PublicKey, payerKey: PublicKey): Promise<TransactionBuilder[]>;
private getSwapTx;
private refresh;
}

@@ -33,3 +33,6 @@ "use strict";

const public_1 = require("../quotes/public");
const position_builder_util_1 = require("../utils/builder/position-builder-util");
const public_2 = require("../utils/public");
const whirlpool_ata_utils_1 = require("../utils/whirlpool-ata-utils");
const position_impl_1 = require("./position-impl");
const util_1 = require("./util");

@@ -203,36 +206,57 @@ class WhirlpoolImpl {

return __awaiter(this, void 0, void 0, function* () {
const position = yield this.ctx.fetcher.getPosition(positionAddress, true);
if (!position) {
const positionData = yield this.ctx.fetcher.getPosition(positionAddress, true);
if (!positionData) {
throw new Error(`Position not found: ${positionAddress.toBase58()}`);
}
const whirlpool = this.data;
(0, tiny_invariant_1.default)(position.whirlpool.equals(this.address), `Position ${positionAddress.toBase58()} is not a position for Whirlpool ${this.address.toBase58()}`);
const tickArrayLower = public_2.PDAUtil.getTickArrayFromTickIndex(position.tickLowerIndex, whirlpool.tickSpacing, position.whirlpool, this.ctx.program.programId).publicKey;
const tickArrayUpper = public_2.PDAUtil.getTickArrayFromTickIndex(position.tickUpperIndex, whirlpool.tickSpacing, position.whirlpool, this.ctx.program.programId).publicKey;
const positionTokenAccount = yield (0, common_sdk_1.deriveATA)(positionWallet, position.positionMint);
(0, tiny_invariant_1.default)(positionData.whirlpool.equals(this.address), `Position ${positionAddress.toBase58()} is not a position for Whirlpool ${this.address.toBase58()}`);
const positionTokenAccount = yield (0, common_sdk_1.deriveATA)(positionWallet, positionData.positionMint);
const ataTxBuilder = new common_sdk_1.TransactionBuilder(this.ctx.provider.connection, this.ctx.provider.wallet);
const affiliatedMints = (0, whirlpool_ata_utils_1.getTokenMintsFromWhirlpools)([whirlpool]);
const accountExemption = yield this.ctx.fetcher.getAccountRentExempt();
const { ataTokenAddresses, resolveAtaIxs } = yield (0, whirlpool_ata_utils_1.resolveAtaForMints)(this.ctx, {
mints: affiliatedMints,
accountExemption,
receiver: destinationWallet,
payer: payerKey,
});
ataTxBuilder.addInstructions(resolveAtaIxs);
const txBuilder = new common_sdk_1.TransactionBuilder(this.ctx.provider.connection, this.ctx.provider.wallet);
const resolvedAssociatedTokenAddresses = {};
const [ataA, ataB] = yield (0, common_sdk_1.resolveOrCreateATAs)(this.ctx.connection, destinationWallet, [{ tokenMint: whirlpool.tokenMintA }, { tokenMint: whirlpool.tokenMintB }], () => this.ctx.fetcher.getAccountRentExempt(), payerKey);
const { address: tokenOwnerAccountA } = ataA, createTokenOwnerAccountAIx = __rest(ataA, ["address"]);
const { address: tokenOwnerAccountB } = ataB, createTokenOwnerAccountBIx = __rest(ataB, ["address"]);
txBuilder.addInstruction(createTokenOwnerAccountAIx).addInstruction(createTokenOwnerAccountBIx);
resolvedAssociatedTokenAddresses[whirlpool.tokenMintA.toBase58()] = tokenOwnerAccountA;
resolvedAssociatedTokenAddresses[whirlpool.tokenMintB.toBase58()] = tokenOwnerAccountB;
// TODO: Collect all Fees and rewards for the position.
// TODO: Optimize - no need to call updateFee if we call decreaseLiquidity first.
// const collectTx = await buildCollectFeesAndRewardsTx(this.dal, {
// provider,
// positionAddress: positionAddress,
// resolvedAssociatedTokenAddresses,
// });
// txBuilder.addInstruction(collectTx.compressIx(false));
/* Remove all liquidity remaining in the position */
if (position.liquidity.gt(new anchor_1.BN(0))) {
const tickArrayLower = public_2.PDAUtil.getTickArrayFromTickIndex(positionData.tickLowerIndex, whirlpool.tickSpacing, positionData.whirlpool, this.ctx.program.programId).publicKey;
const tickArrayUpper = public_2.PDAUtil.getTickArrayFromTickIndex(positionData.tickUpperIndex, whirlpool.tickSpacing, positionData.whirlpool, this.ctx.program.programId).publicKey;
const [tickArrayLowerData, tickArrayUpperData] = yield (0, position_builder_util_1.getTickArrayDataForPosition)(this.ctx, positionData, whirlpool, true);
(0, tiny_invariant_1.default)(!!tickArrayLowerData, `Tick array ${tickArrayLower} expected to be initialized for whirlpool ${this.address}`);
(0, tiny_invariant_1.default)(!!tickArrayUpperData, `Tick array ${tickArrayUpper} expected to be initialized for whirlpool ${this.address}`);
const position = new position_impl_1.PositionImpl(this.ctx, positionAddress, positionData, whirlpool, tickArrayLowerData, tickArrayUpperData);
const tickLower = position.getLowerTickData();
const tickUpper = position.getUpperTickData();
const feesQuote = (0, public_1.collectFeesQuote)({
position: positionData,
whirlpool,
tickLower,
tickUpper,
});
const rewardsQuote = (0, public_1.collectRewardsQuote)({
position: positionData,
whirlpool,
tickLower,
tickUpper,
});
const shouldCollectFees = feesQuote.feeOwedA.gtn(0) || feesQuote.feeOwedB.gtn(0);
(0, tiny_invariant_1.default)(this.data.rewardInfos.length === rewardsQuote.length, "Rewards quote does not match reward infos length");
const rewardsToCollect = this.data.rewardInfos
.filter((_, i) => { var _a; return ((_a = rewardsQuote[i]) !== null && _a !== void 0 ? _a : common_sdk_1.ZERO).gtn(0); })
.map((info) => info.mint);
const shouldCollectRewards = rewardsToCollect.length > 0;
if (positionData.liquidity.gtn(0)) {
/* Remove all liquidity remaining in the position */
const tokenOwnerAccountA = ataTokenAddresses[whirlpool.tokenMintA.toBase58()];
const tokenOwnerAccountB = ataTokenAddresses[whirlpool.tokenMintB.toBase58()];
const decreaseLiqQuote = (0, public_1.decreaseLiquidityQuoteByLiquidityWithParams)({
liquidity: position.liquidity,
liquidity: positionData.liquidity,
slippageTolerance,
sqrtPrice: whirlpool.sqrtPrice,
tickCurrentIndex: whirlpool.tickCurrentIndex,
tickLowerIndex: position.tickLowerIndex,
tickUpperIndex: position.tickUpperIndex,
tickLowerIndex: positionData.tickLowerIndex,
tickUpperIndex: positionData.tickUpperIndex,
});

@@ -243,3 +267,3 @@ const liquidityIx = (0, instructions_1.decreaseLiquidityIx)(this.ctx.program, {

tokenMinB: decreaseLiqQuote.tokenMinB,
whirlpool: position.whirlpool,
whirlpool: positionData.whirlpool,
positionAuthority: positionWallet,

@@ -257,2 +281,21 @@ position: positionAddress,

}
else {
if (shouldCollectFees || shouldCollectRewards) {
// We need to manually udpate the fees/rewards since there is no liquidity IX to do so
txBuilder.addInstruction((0, instructions_1.updateFeesAndRewardsIx)(this.ctx.program, {
whirlpool: positionData.whirlpool,
position: positionAddress,
tickArrayLower,
tickArrayUpper,
}));
}
}
if (shouldCollectFees) {
const collectFeexTx = yield position.collectFees(false, false, destinationWallet, positionWallet, payerKey);
txBuilder.addInstruction(collectFeexTx.compressIx(false));
}
if (shouldCollectRewards) {
const collectRewardsTx = yield position.collectRewards(rewardsToCollect, false, false, destinationWallet, positionWallet, payerKey);
txBuilder.addInstruction(collectRewardsTx.compressIx(false));
}
/* Close position */

@@ -264,6 +307,11 @@ const positionIx = (0, instructions_1.closePositionIx)(this.ctx.program, {

position: positionAddress,
positionMint: position.positionMint,
positionMint: positionData.positionMint,
});
txBuilder.addInstruction(positionIx);
return txBuilder;
const txBuilders = [];
if (!ataTxBuilder.isEmpty()) {
txBuilders.push(ataTxBuilder);
}
txBuilders.push(txBuilder);
return txBuilders;
});

@@ -270,0 +318,0 @@ }

import { TransactionBuilder } from "@orca-so/common-sdk";
import { Address } from "@project-serum/anchor";
import { PublicKey } from "@solana/web3.js";
import { WhirlpoolContext } from "../..";
import { Position } from "../../whirlpool-client";
import { PositionData, WhirlpoolContext } from "../..";
/**

@@ -30,3 +29,3 @@ * Parameters to collect all fees and rewards from a list of positions.

export type CollectAllPositionParams = {
positions: Position[];
positions: Record<string, PositionData>;
} & CollectAllParams;

@@ -33,0 +32,0 @@ type CollectAllParams = {

@@ -28,3 +28,2 @@ "use strict";

const web3_js_1 = require("@solana/web3.js");
const position_impl_1 = require("../../impl/position-impl");
const ix_1 = require("../../ix");

@@ -50,10 +49,10 @@ const public_1 = require("../../utils/public");

const { positions } = params, rest = __rest(params, ["positions"]);
const posDatas = yield ctx.fetcher.listPositions(positions, refresh);
const positionsObjs = posDatas.reduce((accu, curr, index) => {
if (curr) {
accu.push(new position_impl_1.PositionImpl(ctx, common_sdk_1.AddressUtil.toPubKey(positions[index]), curr));
const posData = (0, txn_utils_1.convertListToMap)(yield ctx.fetcher.listPositions(positions, refresh), positions.map((pos) => pos.toString()));
const positionMap = {};
Object.entries(posData).forEach(([addr, pos]) => {
if (pos) {
positionMap[addr] = pos;
}
return accu;
}, []);
return collectAllForPositionsTxns(ctx, Object.assign({ positions: positionsObjs }, rest));
});
return collectAllForPositionsTxns(ctx, Object.assign({ positions: positionMap }, rest));
});

@@ -77,6 +76,7 @@ }

const payerKey = payer !== null && payer !== void 0 ? payer : ctx.wallet.publicKey;
if (positions.length === 0) {
const positionList = Object.entries(positions);
if (positionList.length === 0) {
return [];
}
const whirlpoolAddrs = positions.map((pos) => pos.getData().whirlpool.toBase58());
const whirlpoolAddrs = positionList.map(([, pos]) => pos.whirlpool.toBase58());
const whirlpoolDatas = yield ctx.fetcher.listPools(whirlpoolAddrs, false);

@@ -97,6 +97,6 @@ const whirlpools = (0, txn_utils_1.convertListToMap)(whirlpoolDatas, whirlpoolAddrs);

let reattempt = false;
while (posIndex < positions.length) {
const position = positions[posIndex];
while (posIndex < positionList.length) {
const [positionAddr, position] = positionList[posIndex];
let positionTxBuilder = new common_sdk_1.TransactionBuilder(ctx.connection, ctx.wallet);
const { whirlpool: whirlpoolKey, positionMint } = position.getData();
const { whirlpool: whirlpoolKey, positionMint } = position;
const whirlpool = whirlpools[whirlpoolKey.toBase58()];

@@ -113,3 +113,3 @@ if (!whirlpool) {

// Build position instructions
const collectIxForPosition = constructCollectPositionIx(ctx, position, whirlpools, positionOwnerKey, positionAuthorityKey, affliatedTokenAtaMap);
const collectIxForPosition = constructCollectPositionIx(ctx, new web3_js_1.PublicKey(positionAddr), position, whirlpools, positionOwnerKey, positionAuthorityKey, affliatedTokenAtaMap);
positionTxBuilder.addInstructions(collectIxForPosition);

@@ -128,3 +128,3 @@ // Attempt to push the new instructions into the pending builder

if (reattempt) {
throw new Error(`Unable to fit collection ix for ${position.getAddress().toBase58()} in a Transaction.`);
throw new Error(`Unable to fit collection ix for ${position.positionMint.toBase58()} in a Transaction.`);
}

@@ -152,6 +152,5 @@ txBuilders.push(pendingTxBuilder);

// TODO: Once individual collect ix for positions is implemented, maybe migrate over if it can take custom ATA?
const constructCollectPositionIx = (ctx, position, whirlpools, positionOwner, positionAuthority, affliatedTokenAtaMap) => {
const constructCollectPositionIx = (ctx, positionKey, position, whirlpools, positionOwner, positionAuthority, affliatedTokenAtaMap) => {
const ixForPosition = [];
const { whirlpool: whirlpoolKey, liquidity, tickLowerIndex, tickUpperIndex, positionMint, rewardInfos: positionRewardInfos, } = position.getData();
const positionKey = common_sdk_1.AddressUtil.toPubKey(position.getAddress());
const { whirlpool: whirlpoolKey, liquidity, tickLowerIndex, tickUpperIndex, positionMint, rewardInfos: positionRewardInfos, } = position;
const whirlpool = whirlpools[whirlpoolKey.toBase58()];

@@ -158,0 +157,0 @@ if (!whirlpool) {

@@ -26,3 +26,3 @@ "use strict";

address: tickArray.address,
data: tickArray.data
data: tickArray.data,
});

@@ -29,0 +29,0 @@ }

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WHIRLPOOL_ACCOUNT_SIZE = exports.WHIRLPOOL_CODER = exports.AccountName = void 0;
const anchor_1 = require("@project-serum/anchor");
const whirlpool_1 = require("../../artifacts/whirlpool");
const whirlpool_json_1 = __importDefault(require("../../artifacts/whirlpool.json"));
/**

@@ -25,6 +28,7 @@ * This file contains the types that has the same structure as the types anchor functions returns.

})(AccountName = exports.AccountName || (exports.AccountName = {}));
exports.WHIRLPOOL_CODER = new anchor_1.BorshAccountsCoder(whirlpool_1.IDL);
const IDL = whirlpool_json_1.default;
exports.WHIRLPOOL_CODER = new anchor_1.BorshAccountsCoder(IDL);
/**
* Size of the Whirlpool account in bytes.
*/
exports.WHIRLPOOL_ACCOUNT_SIZE = exports.WHIRLPOOL_CODER.size(whirlpool_1.IDL.accounts[4]);
exports.WHIRLPOOL_ACCOUNT_SIZE = exports.WHIRLPOOL_CODER.size(IDL.accounts[4]);
import { PublicKey } from "@solana/web3.js";
import { AccountFetcher } from "../../network/public";
import { TickArrayData, TickData } from "../../types/public";
import { AccountFetcher } from "../../network/public";
/**

@@ -11,2 +11,11 @@ * A collection of utility functions when interacting with Ticks.

/**
* Get the offset index to access a tick at a given tick-index in a tick-array
*
* @param tickIndex The tick index for the tick that this offset would access
* @param arrayStartIndex The starting tick for the array that this tick-index resides in
* @param tickSpacing The tickSpacing for the Whirlpool that this tickArray belongs to
* @returns The offset index that can access the desired tick at the given tick-array
*/
static getOffsetIndex(tickIndex: number, arrayStartIndex: number, tickSpacing: number): number;
/**
* Get the startIndex of the tick array containing tickIndex.

@@ -13,0 +22,0 @@ *

@@ -31,2 +31,13 @@ "use strict";

/**
* Get the offset index to access a tick at a given tick-index in a tick-array
*
* @param tickIndex The tick index for the tick that this offset would access
* @param arrayStartIndex The starting tick for the array that this tick-index resides in
* @param tickSpacing The tickSpacing for the Whirlpool that this tickArray belongs to
* @returns The offset index that can access the desired tick at the given tick-array
*/
static getOffsetIndex(tickIndex, arrayStartIndex, tickSpacing) {
return Math.floor((tickIndex - arrayStartIndex) / tickSpacing);
}
/**
* Get the startIndex of the tick array containing tickIndex.

@@ -33,0 +44,0 @@ *

@@ -7,3 +7,3 @@ import { Percentage, TransactionBuilder } from "@orca-so/common-sdk";

import { AccountFetcher } from "./network/public";
import { DecreaseLiquidityInput, IncreaseLiquidityInput, PositionData, WhirlpoolData } from "./types/public";
import { DecreaseLiquidityInput, IncreaseLiquidityInput, PositionData, TickData, WhirlpoolData } from "./types/public";
import { TokenAccountInfo, TokenInfo, WhirlpoolRewardInfo } from "./types/public/client-types";

@@ -193,3 +193,3 @@ /**

*/
closePosition: (positionAddress: Address, slippageTolerance: Percentage, destinationWallet?: Address, positionWallet?: Address, payer?: Address) => Promise<TransactionBuilder>;
closePosition: (positionAddress: Address, slippageTolerance: Percentage, destinationWallet?: Address, positionWallet?: Address, payer?: Address) => Promise<TransactionBuilder[]>;
/**

@@ -230,2 +230,17 @@ * Perform a swap between tokenA and tokenB on this pool.

/**
* Return the most recently fetched Whirlpool account data for this position.
* @return most recently fetched WhirlpoolData for this position.
*/
getWhirlpoolData: () => WhirlpoolData;
/**
* Return the most recently fetched TickData account data for this position's lower tick.
* @return most recently fetched TickData for this position's lower tick.
*/
getLowerTickData: () => TickData;
/**
* Return the most recently fetched TickData account data for this position's upper tick.
* @return most recently fetched TickData for this position's upper tick.
*/
getUpperTickData: () => TickData;
/**
* Fetch and return the most recently fetched Position account data.

@@ -261,2 +276,31 @@ * @return the most up to date PositionData for this address.

decreaseLiquidity: (liquidityInput: DecreaseLiquidityInput, resolveATA?: boolean, destinationWallet?: Address, positionWallet?: Address, ataPayer?: Address) => Promise<TransactionBuilder>;
/**
* Collect fees from this position
*
* If `positionWallet` is provided, the wallet owners have to sign this transaction.
*
* @param resolveATA - if true, add instructions to create associated token accounts for tokenA,B for the destinationWallet if necessary. (RPC call required)
* @param updateFeesAndRewards - if true, add instructions to refresh the accumulated fees and rewards data (default to true unless you know that the collect fees quote and on-chain data match for the "feeOwedA" and "feeOwedB" fields in the Position account)
* @param destinationWallet - the wallet to deposit tokens into when withdrawing from the position. If null, the WhirlpoolContext wallet is used.
* @param positionWallet - the wallet to that houses the position token. If null, the WhirlpoolContext wallet is used.
* @param ataPayer - wallet that will fund the creation of the new associated token accounts
* @param refresh - set to true to bypass cached on-chain data
* @return the transaction that will collect fees from the position
*/
collectFees: (updateFeesAndRewards?: boolean, resolveATA?: boolean, destinationWallet?: Address, positionWallet?: Address, ataPayer?: Address, refresh?: boolean) => Promise<TransactionBuilder>;
/**
* Collect rewards from this position
*
* If `positionWallet` is provided, the wallet owners have to sign this transaction.
*
* @param rewardsToCollect - reward mints to collect (omitting this parameter means all rewards will be collected)
* @param updateFeesAndRewards - if true, add instructions to refresh the accumulated fees and rewards data (default to true unless you know that the collect fees quote and on-chain data match for the "feeOwedA" and "feeOwedB" fields in the Position account)
* @param resolveATA - if true, add instructions to create associated token accounts for the reward mints for the destinationWallet if necessary. (RPC call required)
* @param destinationWallet - the wallet to deposit tokens into when withdrawing from the position. If null, the WhirlpoolContext wallet is used.
* @param positionWallet - the wallet to that houses the position token. If null, the WhirlpoolContext wallet is used.
* @param ataPayer - wallet that will fund the creation of the new associated token accounts
* @param refresh - set to true to bypass cached on-chain data
* @return the transaction that will collect fees from the position
*/
collectRewards: (rewardsToCollect?: Address[], updateFeesAndRewards?: boolean, resolveATA?: boolean, destinationWallet?: Address, positionWallet?: Address, ataPayer?: Address, refresh?: boolean) => Promise<TransactionBuilder>;
}
{
"name": "@orca-so/whirlpools-sdk",
"version": "0.6.1",
"version": "0.7.1",
"description": "Typescript SDK to interact with Orca's Whirlpool program.",

@@ -5,0 +5,0 @@ "license": "Apache-2.0",

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc