@picon-finance/dlmm-sdk 1.7.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +28 -0
  2. package/dist/entities/dlmm_program.d.ts +3 -0
  3. package/dist/entities/dlmm_program.d.ts.map +1 -1
  4. package/dist/entities/pool.d.ts +9 -5
  5. package/dist/entities/pool.d.ts.map +1 -1
  6. package/dist/entities/pool.js +18 -11
  7. package/dist/entities/position.d.ts +1 -0
  8. package/dist/entities/position.d.ts.map +1 -1
  9. package/dist/entities/position.js +47 -14
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/quote/index.d.ts +3 -2
  13. package/dist/quote/index.d.ts.map +1 -1
  14. package/dist/quote/index.js +7 -0
  15. package/dist/quote/wasm-node/picon_dlmm_quote.d.ts +14 -0
  16. package/dist/quote/wasm-node/picon_dlmm_quote.js +14 -0
  17. package/dist/quote/wasm-node/picon_dlmm_quote_bg.wasm +0 -0
  18. package/dist/quote/wasm-node/picon_dlmm_quote_bg.wasm.d.ts +1 -0
  19. package/dist/quote/wasm-web/picon_dlmm_quote.d.ts +15 -0
  20. package/dist/quote/wasm-web/picon_dlmm_quote.js +14 -0
  21. package/dist/quote/wasm-web/picon_dlmm_quote_bg.wasm +0 -0
  22. package/dist/quote/wasm-web/picon_dlmm_quote_bg.wasm.d.ts +1 -0
  23. package/dist/utils/assert.d.ts +1 -0
  24. package/dist/utils/assert.d.ts.map +1 -1
  25. package/dist/utils/assert.js +5 -0
  26. package/dist/utils/constants.d.ts +2 -0
  27. package/dist/utils/constants.d.ts.map +1 -1
  28. package/dist/utils/constants.js +6 -0
  29. package/package.json +1 -1
  30. package/src/entities/dlmm_program.ts +3 -3
  31. package/src/entities/pool.ts +24 -5
  32. package/src/entities/position.ts +82 -21
  33. package/src/index.ts +1 -1
  34. package/src/quote/index.ts +10 -1
  35. package/src/quote/wasm-node/picon_dlmm_quote.d.ts +14 -0
  36. package/src/quote/wasm-node/picon_dlmm_quote.js +14 -0
  37. package/src/quote/wasm-node/picon_dlmm_quote_bg.wasm +0 -0
  38. package/src/quote/wasm-node/picon_dlmm_quote_bg.wasm.d.ts +1 -0
  39. package/src/quote/wasm-web/picon_dlmm_quote.d.ts +15 -0
  40. package/src/quote/wasm-web/picon_dlmm_quote.js +14 -0
  41. package/src/quote/wasm-web/picon_dlmm_quote_bg.wasm +0 -0
  42. package/src/quote/wasm-web/picon_dlmm_quote_bg.wasm.d.ts +1 -0
  43. package/src/utils/assert.ts +6 -0
  44. package/src/utils/constants.ts +7 -0
package/README.md CHANGED
@@ -117,6 +117,23 @@ Both are computed entirely from cached position + bin array data — `getBinInfo
117
117
  const { transferFeeX, transferFeeY } = await pool.getTransferFees();
118
118
  ```
119
119
 
120
+ `Pool.getFeeRates(now?)` returns the base/dynamic/total fee rate the pool would charge for a swap at `now` (defaults to the current time) — decays the dynamic fee state first, the same "clock sim" the on-chain program runs right before pricing a real swap, so this reflects what a swap would actually pay rather than the raw, potentially stale, stored volatility accumulator:
121
+
122
+ ```ts
123
+ const { baseFeeRate, dynamicFeeRate, totalFeeRate } = await pool.getFeeRates();
124
+ ```
125
+
126
+ `swap`/`quote`/`quoteAndSwap`/`sync` all accept an optional `binArrayCount` (default: the protocol max for that instruction) to cap how many bin arrays get included — useful for capping compute/account budget on a swap you know won't need the full range. It must be at least 2 (one below the active bin array's index and the active bin array itself, or vice versa — the active bin array is always required):
127
+
128
+ ```ts
129
+ const instructions = await pool.swap(userSigner, {
130
+ xToY: true,
131
+ amountIn: 1_000_000n,
132
+ minAmountOut: 0n,
133
+ binArrayCount: 4,
134
+ });
135
+ ```
136
+
120
137
  Refresh a position's cached state after it changes on-chain (e.g. after a deposit lands):
121
138
 
122
139
  ```ts
@@ -142,6 +159,17 @@ Or fetch a single position directly if you already know its address:
142
159
  const positionByAddress = await pool.getPosition(positionAddress);
143
160
  ```
144
161
 
162
+ Claim fees across many positions at once with `Position.claimAllFees()` — it skips positions with nothing pending (checked locally, no extra RPC) and batches the rest into `MAX_POSITIONS_PER_CLAIM`-sized (overridable via a third argument) instruction groups, one per transaction, sharing a single set of ATA setup/teardown instructions across the whole batch rather than repeating them per position. All positions must belong to the same pool:
163
+
164
+ ```ts
165
+ const positions = await pool.getAllPositionsByPositionMints(positionMints);
166
+ const claimTxs = await Position.claimAllFees(ownerSigner, positions);
167
+
168
+ for (const claimIxs of claimTxs) {
169
+ // build + send one transaction per entry
170
+ }
171
+ ```
172
+
145
173
  ### Events
146
174
 
147
175
  Event decoding and subscriptions are a separate, opt-in feature under the `events` namespace — independent of `DlmmProgram`/`Pool`/`Position`/`BinArray`:
@@ -22,16 +22,19 @@ export declare class DlmmProgram {
22
22
  xToY: boolean;
23
23
  amountIn: bigint;
24
24
  minAmountOut: bigint;
25
+ binArrayCount?: number;
25
26
  }, config?: FetchAccountConfig): Promise<Instruction[]>;
26
27
  quote(poolAddress: Address, params: {
27
28
  xToY: boolean;
28
29
  amountIn: bigint;
29
30
  slippageToleranceBps: number;
31
+ binArrayCount?: number;
30
32
  }, config?: FetchAccountConfig): Promise<QuoteOutput>;
31
33
  quoteAndSwap(user: TransactionSigner, poolAddress: Address, params: {
32
34
  xToY: boolean;
33
35
  amountIn: bigint;
34
36
  slippageToleranceBps: number;
37
+ binArrayCount?: number;
35
38
  }, config?: FetchAccountConfig): Promise<{
36
39
  quoteOutput: QuoteOutput;
37
40
  instructions: Instruction[];
@@ -1 +1 @@
1
- {"version":3,"file":"dlmm_program.d.ts","sourceRoot":"","sources":["../../src/entities/dlmm_program.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dlmm_program.d.ts","sourceRoot":"","sources":["../../src/entities/dlmm_program.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { createSolanaRpc, type Address, type Account, type Instruction, type TransactionSigner, type FetchAccountConfig, type FetchAccountsConfig } from "@solana/kit";
2
2
  import { generated } from "..";
3
- import { type QuoteOutput, type TransferFee } from "../quote";
3
+ import { type FeeRates, type QuoteOutput, type TransferFee } from "../quote";
4
4
  import { Position } from "./position";
5
5
  import { type ProgramConfig } from "./types";
6
6
  export declare class Pool {
@@ -23,6 +23,7 @@ export declare class Pool {
23
23
  transferFeeX?: TransferFee;
24
24
  transferFeeY?: TransferFee;
25
25
  }>;
26
+ getFeeRates(now?: bigint): Promise<FeeRates>;
26
27
  refresh(data: Account<generated.Pool>): Promise<void>;
27
28
  refresh(config?: FetchAccountConfig): Promise<void>;
28
29
  getPosition(address: Address, config?: FetchAccountsConfig): Promise<Position>;
@@ -33,25 +34,28 @@ export declare class Pool {
33
34
  upperBinId: number;
34
35
  }): Promise<Instruction[]>;
35
36
  closePosition(owner: TransactionSigner, positionMint: Address): Promise<Instruction>;
36
- swap(user: TransactionSigner, { xToY, amountIn, minAmountOut, }: {
37
+ swap(user: TransactionSigner, { xToY, amountIn, minAmountOut, binArrayCount, }: {
37
38
  xToY: boolean;
38
39
  amountIn: bigint;
39
40
  minAmountOut: bigint;
41
+ binArrayCount?: number;
40
42
  }): Promise<Instruction[]>;
41
- quote({ xToY, amountIn, slippageToleranceBps, }: {
43
+ quote({ xToY, amountIn, slippageToleranceBps, binArrayCount, }: {
42
44
  xToY: boolean;
43
45
  amountIn: bigint;
44
46
  slippageToleranceBps: number;
47
+ binArrayCount?: number;
45
48
  }): Promise<QuoteOutput>;
46
- quoteAndSwap(user: TransactionSigner, { xToY, amountIn, slippageToleranceBps, }: {
49
+ quoteAndSwap(user: TransactionSigner, { xToY, amountIn, slippageToleranceBps, binArrayCount, }: {
47
50
  xToY: boolean;
48
51
  amountIn: bigint;
49
52
  slippageToleranceBps: number;
53
+ binArrayCount?: number;
50
54
  }): Promise<{
51
55
  quoteOutput: QuoteOutput;
52
56
  instructions: Instruction[];
53
57
  }>;
54
- sync(user: TransactionSigner, desiredBinId: number): Promise<Instruction[]>;
58
+ sync(user: TransactionSigner, desiredBinId: number, binArrayCount?: number): Promise<Instruction[]>;
55
59
  setDynamicFeeConfig(authority: TransactionSigner, dynamicFeeConfig: generated.DynamicFeeConfig): Promise<Instruction>;
56
60
  setProtocolShare(authority: TransactionSigner, protocolShare: number): Promise<Instruction>;
57
61
  claimProtocolFee(authority: TransactionSigner): Promise<Instruction[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../../src/entities/pool.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../../src/entities/pool.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,14 @@
1
1
  import { AccountRole, } from "@solana/kit";
2
2
  import { fetchAllMint, } from "@solana-program/token-2022";
3
3
  import { generated } from "..";
4
- import { quote, } from "../quote";
4
+ import { quote, getPoolFeeRates, } from "../quote";
5
5
  import { isAccount } from "../utils/type_guards";
6
+ import { assertInRange } from "../utils/assert";
6
7
  import { resolveAdminConfigAddress } from "./admin_config";
7
8
  import { processAssociatedTokenAccountPair } from "../utils/ata";
8
9
  import { generateBinArrayIndicesForSwap, generateBinArrayIndicesForSync, } from "../utils/bin_location";
9
10
  import { resolveTransferFee } from "../utils/transfer_fee";
10
- import { MAX_BIN_ARRAYS_PER_SWAP, MAX_BIN_ARRAYS_PER_SYNC, } from "../utils/constants";
11
+ import { MAX_BIN_ARRAYS_PER_SWAP, MIN_BIN_ARRAYS_PER_SWAP, MAX_BIN_ARRAYS_PER_SYNC, MIN_BIN_ARRAYS_PER_SYNC, } from "../utils/constants";
11
12
  import { Position, openPosition, closePosition, findPositionAddress, findAllPositionAddresses, } from "./position";
12
13
  import { findAllBinArrayAddresses } from "./bin_array";
13
14
  export class Pool {
@@ -43,6 +44,9 @@ export class Pool {
43
44
  transferFeeY: resolveTransferFee(this.#mintY.data, epoch),
44
45
  };
45
46
  }
47
+ async getFeeRates(now = BigInt(Math.floor(Date.now() / 1000))) {
48
+ return await getPoolFeeRates(this.data, now);
49
+ }
46
50
  async refresh(arg) {
47
51
  if (!isAccount(arg)) {
48
52
  arg = await generated.fetchPool(this.#rpc, this.address, arg);
@@ -66,8 +70,9 @@ export class Pool {
66
70
  async closePosition(owner, positionMint) {
67
71
  return await closePosition({ owner, positionMint }, { programAddress: this.#programAddress });
68
72
  }
69
- async swap(user, { xToY, amountIn, minAmountOut, }) {
70
- const indices = generateBinArrayIndicesForSwap(this.activeBinId, xToY, MAX_BIN_ARRAYS_PER_SWAP);
73
+ async swap(user, { xToY, amountIn, minAmountOut, binArrayCount = MAX_BIN_ARRAYS_PER_SWAP, }) {
74
+ assertInRange(binArrayCount, MIN_BIN_ARRAYS_PER_SWAP, MAX_BIN_ARRAYS_PER_SWAP, "binArrayCount");
75
+ const indices = generateBinArrayIndicesForSwap(this.activeBinId, xToY, binArrayCount);
71
76
  const [binArrayAddresses, { ataX: tokenUserAccountX, ataY: tokenUserAccountY, preInstructions, postInstructions, }] = await Promise.all([
72
77
  findAllBinArrayAddresses({ pool: this.address, indices }, { programAddress: this.#programAddress }),
73
78
  processAssociatedTokenAccountPair({
@@ -99,8 +104,9 @@ export class Pool {
99
104
  const swapIxWithBinArrays = { ...swapIx, accounts: [...swapIx.accounts, ...remainingAccounts] };
100
105
  return [...preInstructions, swapIxWithBinArrays, ...postInstructions];
101
106
  }
102
- async quote({ xToY, amountIn, slippageToleranceBps, }) {
103
- const indices = generateBinArrayIndicesForSwap(this.activeBinId, xToY, MAX_BIN_ARRAYS_PER_SWAP);
107
+ async quote({ xToY, amountIn, slippageToleranceBps, binArrayCount = MAX_BIN_ARRAYS_PER_SWAP, }) {
108
+ assertInRange(binArrayCount, MIN_BIN_ARRAYS_PER_SWAP, MAX_BIN_ARRAYS_PER_SWAP, "binArrayCount");
109
+ const indices = generateBinArrayIndicesForSwap(this.activeBinId, xToY, binArrayCount);
104
110
  const binArrayAddresses = await findAllBinArrayAddresses({ pool: this.address, indices }, { programAddress: this.#programAddress });
105
111
  const [maybeBinArrays, { transferFeeX, transferFeeY }] = await Promise.all([
106
112
  generated.fetchAllMaybeBinArray(this.#rpc, binArrayAddresses),
@@ -118,13 +124,14 @@ export class Pool {
118
124
  binArrays,
119
125
  });
120
126
  }
121
- async quoteAndSwap(user, { xToY, amountIn, slippageToleranceBps, }) {
122
- const quoteOutput = await this.quote({ xToY, amountIn, slippageToleranceBps });
123
- const instructions = await this.swap(user, { xToY, amountIn, minAmountOut: quoteOutput.minAmountOut });
127
+ async quoteAndSwap(user, { xToY, amountIn, slippageToleranceBps, binArrayCount = MAX_BIN_ARRAYS_PER_SWAP, }) {
128
+ const quoteOutput = await this.quote({ xToY, amountIn, slippageToleranceBps, binArrayCount });
129
+ const instructions = await this.swap(user, { xToY, amountIn, minAmountOut: quoteOutput.minAmountOut, binArrayCount });
124
130
  return { quoteOutput, instructions };
125
131
  }
126
- async sync(user, desiredBinId) {
127
- const indices = generateBinArrayIndicesForSync(this.activeBinId, desiredBinId, MAX_BIN_ARRAYS_PER_SYNC);
132
+ async sync(user, desiredBinId, binArrayCount = MAX_BIN_ARRAYS_PER_SYNC) {
133
+ assertInRange(binArrayCount, MIN_BIN_ARRAYS_PER_SYNC, MAX_BIN_ARRAYS_PER_SYNC, "binArrayCount");
134
+ const indices = generateBinArrayIndicesForSync(this.activeBinId, desiredBinId, binArrayCount);
128
135
  const binArrayAddresses = await findAllBinArrayAddresses({ pool: this.address, indices }, { programAddress: this.#programAddress });
129
136
  const syncPoolIx = generated.getSyncPoolInstruction({ user, pool: this.address, desiredBinId }, { programAddress: this.#programAddress });
130
137
  const remainingAccounts = binArrayAddresses.map(address => ({ address, role: AccountRole.READONLY }));
@@ -33,6 +33,7 @@ export declare class Position {
33
33
  static load(pool: Pool, address: Address, config?: FetchAccountsConfig): Promise<Position>;
34
34
  static loadAll(pool: Pool, addresses: Address[], config?: FetchAccountsConfig): Promise<Position[]>;
35
35
  static refreshAll(rpc: ReturnType<typeof createSolanaRpc>, positions: Position[], config?: FetchAccountsConfig): Promise<void>;
36
+ static claimAllFees(owner: TransactionSigner, positions: Position[], positionsPerClaim?: number): Promise<Instruction[][]>;
36
37
  }
37
38
  export declare function findPositionAddress(seeds: {
38
39
  positionMint: Address;
@@ -1 +1 @@
1
- {"version":3,"file":"position.d.ts","sourceRoot":"","sources":["../../src/entities/position.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"position.d.ts","sourceRoot":"","sources":["../../src/entities/position.ts"],"names":[],"mappings":"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"}
@@ -5,9 +5,9 @@ import { findPositionTokenAccount, processAssociatedTokenAccountPair, } from "..
5
5
  import { getBinIndex, getBinArrayIndex, getPositionBinArrayIndices, } from "../utils/bin_location";
6
6
  import { assertRangeWithinRange, assertPositionBelongsToPool, } from "../utils/assert";
7
7
  import { isUndefined } from "../utils/type_guards";
8
- import { fetchInChunks } from "../utils/chunk";
8
+ import { chunk, fetchInChunks, } from "../utils/chunk";
9
9
  import { resolveAdminConfigAddress } from "./admin_config";
10
- import { MAX_ACCOUNTS_PER_RPC_BATCH } from "../utils/constants";
10
+ import { MAX_POSITIONS_PER_CLAIM, MAX_ACCOUNTS_PER_RPC_BATCH, } from "../utils/constants";
11
11
  import { BinArray, decodeAllBinArrays, createAllBinArrays, fetchAllBinArraysChunked, } from "./bin_array";
12
12
  export class Position {
13
13
  #pool;
@@ -141,21 +141,11 @@ export class Position {
141
141
  });
142
142
  return [...preInstructions, depositByWeightIx, ...postInstructions];
143
143
  }
144
- async claimFee(owner, range) {
144
+ async #buildClaimFeeInstruction(owner, positionTokenAccount, tokenOwnerAccountX, tokenOwnerAccountY, range) {
145
145
  const { lowerBinId, upperBinId } = range ?? this.data;
146
146
  assertRangeWithinRange({ lowerBinId, upperBinId }, this.data);
147
- const [positionTokenAccount, { ataX: tokenOwnerAccountX, ataY: tokenOwnerAccountY, preInstructions, postInstructions }] = await Promise.all([
148
- findPositionTokenAccount({ owner: owner.address, positionMint: this.data.positionMint }),
149
- processAssociatedTokenAccountPair({
150
- owner,
151
- tokenMintX: this.#pool.tokenMintX,
152
- tokenMintY: this.#pool.tokenMintY,
153
- tokenProgramX: this.#pool.tokenProgramX,
154
- tokenProgramY: this.#pool.tokenProgramY,
155
- }),
156
- ]);
157
147
  const { lowerBinArray, upperBinArray } = this.binArrayAddresses;
158
- const claimFeeIx = generated.getClaimFeeInstruction({
148
+ return generated.getClaimFeeInstruction({
159
149
  owner,
160
150
  pool: this.#pool.address,
161
151
  position: this.address,
@@ -175,6 +165,19 @@ export class Position {
175
165
  }, {
176
166
  programAddress: this.#pool.programAddress
177
167
  });
168
+ }
169
+ async claimFee(owner, range) {
170
+ const [positionTokenAccount, { ataX: tokenOwnerAccountX, ataY: tokenOwnerAccountY, preInstructions, postInstructions }] = await Promise.all([
171
+ findPositionTokenAccount({ owner: owner.address, positionMint: this.data.positionMint }),
172
+ processAssociatedTokenAccountPair({
173
+ owner,
174
+ tokenMintX: this.#pool.tokenMintX,
175
+ tokenMintY: this.#pool.tokenMintY,
176
+ tokenProgramX: this.#pool.tokenProgramX,
177
+ tokenProgramY: this.#pool.tokenProgramY,
178
+ }),
179
+ ]);
180
+ const claimFeeIx = await this.#buildClaimFeeInstruction(owner, positionTokenAccount, tokenOwnerAccountX, tokenOwnerAccountY, range);
178
181
  return [...preInstructions, claimFeeIx, ...postInstructions];
179
182
  }
180
183
  async withdraw(owner, bpsToRemove, range) {
@@ -253,6 +256,36 @@ export class Position {
253
256
  position.#binArrays.map(binArray => binArrayByAddress.get(binArray.address)),
254
257
  ])));
255
258
  }
259
+ static async claimAllFees(owner, positions, positionsPerClaim = MAX_POSITIONS_PER_CLAIM) {
260
+ if (positions.length === 0) {
261
+ return [];
262
+ }
263
+ const pool = positions[0].#pool;
264
+ for (const position of positions) {
265
+ assertPositionBelongsToPool(position.data, pool);
266
+ }
267
+ const claimablePositions = positions.filter(position => position.getBinInfos().some(({ feeX, feeY }) => feeX > 0n || feeY > 0n));
268
+ if (claimablePositions.length === 0) {
269
+ return [];
270
+ }
271
+ const [positionTokenAccounts, { ataX, ataY, preInstructions, postInstructions }] = await Promise.all([
272
+ Promise.all(claimablePositions.map(position => findPositionTokenAccount({ owner: owner.address, positionMint: position.data.positionMint }))),
273
+ processAssociatedTokenAccountPair({
274
+ owner,
275
+ tokenMintX: pool.tokenMintX,
276
+ tokenMintY: pool.tokenMintY,
277
+ tokenProgramX: pool.tokenProgramX,
278
+ tokenProgramY: pool.tokenProgramY,
279
+ }),
280
+ ]);
281
+ const claimFeeIxs = await Promise.all(claimablePositions.map((position, i) => position.#buildClaimFeeInstruction(owner, positionTokenAccounts[i], ataX, ataY)));
282
+ const chunks = chunk(claimFeeIxs, positionsPerClaim);
283
+ return chunks.map((claimFeeIxsChunk, i) => [
284
+ ...(i === 0 ? preInstructions : []),
285
+ ...claimFeeIxsChunk,
286
+ ...(i === chunks.length - 1 ? postInstructions : []),
287
+ ]);
288
+ }
256
289
  }
257
290
  export async function findPositionAddress(seeds, config) {
258
291
  const [address] = await generated.findPositionPda(seeds, config);
package/dist/index.d.ts CHANGED
@@ -4,6 +4,6 @@ export * as events from "./events";
4
4
  export * from "./entities";
5
5
  export * from "./utils/constants";
6
6
  export { NATIVE_MINT_ADDRESS } from "./utils/ata";
7
- export type { QuoteOutput, TransferFee } from "./quote";
7
+ export type { QuoteOutput, TransferFee, FeeRates } from "./quote";
8
8
  export * from "./program_addresses";
9
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACxD,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAClE,cAAc,qBAAqB,CAAC"}
@@ -1,5 +1,6 @@
1
- import { type QuoteInput, type QuoteOutput, type PoolState, type TransferFee } from "#wasm";
2
- export type { QuoteInput, QuoteOutput, PoolState, TransferFee };
1
+ import { type QuoteInput, type QuoteOutput, type PoolState, type TransferFee, type FeeRates } from "#wasm";
2
+ export type { QuoteInput, QuoteOutput, PoolState, TransferFee, FeeRates };
3
3
  export declare function quote(input: QuoteInput): Promise<QuoteOutput>;
4
4
  export declare function applyTransferFee(amount: bigint, fee?: TransferFee): Promise<bigint>;
5
+ export declare function getPoolFeeRates(poolState: PoolState, now: bigint): Promise<FeeRates>;
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/quote/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,WAAW,EACjB,MAAM,OAAO,CAAC;AAEf,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC;AAEhE,wBAAsB,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAGnE;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAGzF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/quote/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,QAAQ,EACd,MAAM,OAAO,CAAC;AAEf,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC;AAE1E,wBAAsB,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAGnE;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAGzF;AAKD,wBAAsB,eAAe,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAG1F"}
@@ -7,3 +7,10 @@ export async function applyTransferFee(amount, fee) {
7
7
  const wasm = await loadWasm();
8
8
  return wasm.applyTransferFee(amount, fee);
9
9
  }
10
+ // Decays the dynamic fee state to `now` first (the same "clock sim" the program does on-chain
11
+ // right before pricing a real swap), so the returned rates reflect what a swap would actually
12
+ // pay right now rather than the raw, potentially stale, stored volatility_accumulator.
13
+ export async function getPoolFeeRates(poolState, now) {
14
+ const wasm = await loadWasm();
15
+ return wasm.getPoolFeeRates(poolState, now);
16
+ }
@@ -27,6 +27,12 @@ export interface DynamicFeeState {
27
27
  lastUpdateTimestamp: bigint;
28
28
  }
29
29
 
30
+ export interface FeeRates {
31
+ baseFeeRate: bigint;
32
+ dynamicFeeRate: bigint;
33
+ totalFeeRate: bigint;
34
+ }
35
+
30
36
  export interface PoolState {
31
37
  binStep: number;
32
38
  feeRate: number;
@@ -67,4 +73,12 @@ export interface TransferFee {
67
73
  */
68
74
  export function applyTransferFee(amount: bigint, fee?: TransferFee | null): bigint;
69
75
 
76
+ /**
77
+ * Base/dynamic/total fee rate `pool_state` would charge for a swap happening at `now` —
78
+ * decays the dynamic fee state to `now` first (the same "clock sim" `decay_dynamic_fee` does
79
+ * on-chain right before pricing a real swap), so this reflects what a swap would actually pay
80
+ * rather than the raw, potentially stale, stored `volatility_accumulator`.
81
+ */
82
+ export function getPoolFeeRates(pool_state: PoolState, now: bigint): FeeRates;
83
+
70
84
  export function quote(input: QuoteInput): QuoteOutput;
@@ -17,6 +17,20 @@ export function applyTransferFee(amount, fee) {
17
17
  return BigInt.asUintN(64, ret[0]);
18
18
  }
19
19
 
20
+ /**
21
+ * Base/dynamic/total fee rate `pool_state` would charge for a swap happening at `now` —
22
+ * decays the dynamic fee state to `now` first (the same "clock sim" `decay_dynamic_fee` does
23
+ * on-chain right before pricing a real swap), so this reflects what a swap would actually pay
24
+ * rather than the raw, potentially stale, stored `volatility_accumulator`.
25
+ * @param {PoolState} pool_state
26
+ * @param {bigint} now
27
+ * @returns {FeeRates}
28
+ */
29
+ export function getPoolFeeRates(pool_state, now) {
30
+ const ret = wasm.getPoolFeeRates(pool_state, now);
31
+ return ret;
32
+ }
33
+
20
34
  /**
21
35
  * @param {QuoteInput} input
22
36
  * @returns {QuoteOutput}
@@ -2,6 +2,7 @@
2
2
  /* eslint-disable */
3
3
  export const memory: WebAssembly.Memory;
4
4
  export const applyTransferFee: (a: bigint, b: number) => [bigint, number, number];
5
+ export const getPoolFeeRates: (a: any, b: bigint) => any;
5
6
  export const quote: (a: any) => [number, number, number];
6
7
  export const __wbindgen_malloc: (a: number, b: number) => number;
7
8
  export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
@@ -27,6 +27,12 @@ export interface DynamicFeeState {
27
27
  lastUpdateTimestamp: bigint;
28
28
  }
29
29
 
30
+ export interface FeeRates {
31
+ baseFeeRate: bigint;
32
+ dynamicFeeRate: bigint;
33
+ totalFeeRate: bigint;
34
+ }
35
+
30
36
  export interface PoolState {
31
37
  binStep: number;
32
38
  feeRate: number;
@@ -67,6 +73,14 @@ export interface TransferFee {
67
73
  */
68
74
  export function applyTransferFee(amount: bigint, fee?: TransferFee | null): bigint;
69
75
 
76
+ /**
77
+ * Base/dynamic/total fee rate `pool_state` would charge for a swap happening at `now` —
78
+ * decays the dynamic fee state to `now` first (the same "clock sim" `decay_dynamic_fee` does
79
+ * on-chain right before pricing a real swap), so this reflects what a swap would actually pay
80
+ * rather than the raw, potentially stale, stored `volatility_accumulator`.
81
+ */
82
+ export function getPoolFeeRates(pool_state: PoolState, now: bigint): FeeRates;
83
+
70
84
  export function quote(input: QuoteInput): QuoteOutput;
71
85
 
72
86
  export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
@@ -74,6 +88,7 @@ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembl
74
88
  export interface InitOutput {
75
89
  readonly memory: WebAssembly.Memory;
76
90
  readonly applyTransferFee: (a: bigint, b: number) => [bigint, number, number];
91
+ readonly getPoolFeeRates: (a: any, b: bigint) => any;
77
92
  readonly quote: (a: any) => [number, number, number];
78
93
  readonly __wbindgen_malloc: (a: number, b: number) => number;
79
94
  readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
@@ -15,6 +15,20 @@ export function applyTransferFee(amount, fee) {
15
15
  return BigInt.asUintN(64, ret[0]);
16
16
  }
17
17
 
18
+ /**
19
+ * Base/dynamic/total fee rate `pool_state` would charge for a swap happening at `now` —
20
+ * decays the dynamic fee state to `now` first (the same "clock sim" `decay_dynamic_fee` does
21
+ * on-chain right before pricing a real swap), so this reflects what a swap would actually pay
22
+ * rather than the raw, potentially stale, stored `volatility_accumulator`.
23
+ * @param {PoolState} pool_state
24
+ * @param {bigint} now
25
+ * @returns {FeeRates}
26
+ */
27
+ export function getPoolFeeRates(pool_state, now) {
28
+ const ret = wasm.getPoolFeeRates(pool_state, now);
29
+ return ret;
30
+ }
31
+
18
32
  /**
19
33
  * @param {QuoteInput} input
20
34
  * @returns {QuoteOutput}
@@ -2,6 +2,7 @@
2
2
  /* eslint-disable */
3
3
  export const memory: WebAssembly.Memory;
4
4
  export const applyTransferFee: (a: bigint, b: number) => [bigint, number, number];
5
+ export const getPoolFeeRates: (a: any, b: bigint) => any;
5
6
  export const quote: (a: any) => [number, number, number];
6
7
  export const __wbindgen_malloc: (a: number, b: number) => number;
7
8
  export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
@@ -1,6 +1,7 @@
1
1
  import type { Address } from "@solana/kit";
2
2
  import type { BinIdRange } from "./bin_location";
3
3
  export declare function assertRangeWithinRange(inner: BinIdRange, outer: BinIdRange): void;
4
+ export declare function assertInRange(value: number, min: number, max: number, label: string): void;
4
5
  export declare function assertPositionBelongsToPool(position: {
5
6
  pool: Address;
6
7
  }, pool: {
@@ -1 +1 @@
1
- {"version":3,"file":"assert.d.ts","sourceRoot":"","sources":["../../src/utils/assert.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,UAAU,GAChB,IAAI,CAMN;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,EAC3B,IAAI,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,GACzB,IAAI,CAMN"}
1
+ {"version":3,"file":"assert.d.ts","sourceRoot":"","sources":["../../src/utils/assert.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,UAAU,GAChB,IAAI,CAMN;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAI1F;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,EAC3B,IAAI,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,GACzB,IAAI,CAMN"}
@@ -3,6 +3,11 @@ export function assertRangeWithinRange(inner, outer) {
3
3
  throw new RangeError(`Range (${inner.lowerBinId} to ${inner.upperBinId}) must be inside range (${outer.lowerBinId} to ${outer.upperBinId})`);
4
4
  }
5
5
  }
6
+ export function assertInRange(value, min, max, label) {
7
+ if (value < min || value > max) {
8
+ throw new RangeError(`${label} (${value}) must be between ${min} and ${max}`);
9
+ }
10
+ }
6
11
  export function assertPositionBelongsToPool(position, pool) {
7
12
  if (position.pool !== pool.address) {
8
13
  throw new Error(`Position's pool (${position.pool}) does not match expected pool (${pool.address})`);
@@ -9,5 +9,7 @@ export declare const MAX_PROTOCOL_SHARE: number;
9
9
  export declare const MAX_BASIS_POINTS: number;
10
10
  export declare const DYNAMIC_FEE_DIVISOR: bigint;
11
11
  export declare const MAX_POSITIONS_PER_CLAIM = 3;
12
+ export declare const MIN_BIN_ARRAYS_PER_SWAP = 2;
13
+ export declare const MIN_BIN_ARRAYS_PER_SYNC = 2;
12
14
  export declare const MAX_ACCOUNTS_PER_RPC_BATCH = 100;
13
15
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":"AA6BA,eAAO,MAAM,kBAAkB,QAA6C,CAAC;AAC7E,eAAO,MAAM,2BAA2B,QAAsD,CAAC;AAC/F,eAAO,MAAM,uBAAuB,QAAkD,CAAC;AACvF,eAAO,MAAM,uBAAuB,QAAkD,CAAC;AAEvF,eAAO,MAAM,aAAa,QAAwC,CAAC;AACnE,eAAO,MAAM,gBAAgB,QAA2C,CAAC;AACzE,eAAO,MAAM,YAAY,QAAuC,CAAC;AACjE,eAAO,MAAM,kBAAkB,QAA6C,CAAC;AAC7E,eAAO,MAAM,gBAAgB,QAA2C,CAAC;AACzE,eAAO,MAAM,mBAAmB,QAA8C,CAAC;AAE/E,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAGzC,eAAO,MAAM,0BAA0B,MAAM,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":"AA6BA,eAAO,MAAM,kBAAkB,QAA6C,CAAC;AAC7E,eAAO,MAAM,2BAA2B,QAAsD,CAAC;AAC/F,eAAO,MAAM,uBAAuB,QAAkD,CAAC;AACvF,eAAO,MAAM,uBAAuB,QAAkD,CAAC;AAEvF,eAAO,MAAM,aAAa,QAAwC,CAAC;AACnE,eAAO,MAAM,gBAAgB,QAA2C,CAAC;AACzE,eAAO,MAAM,YAAY,QAAuC,CAAC;AACjE,eAAO,MAAM,kBAAkB,QAA6C,CAAC;AAC7E,eAAO,MAAM,gBAAgB,QAA2C,CAAC;AACzE,eAAO,MAAM,mBAAmB,QAA8C,CAAC;AAE/E,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAMzC,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAGzC,eAAO,MAAM,0BAA0B,MAAM,CAAC"}
@@ -34,5 +34,11 @@ export const MAX_PROTOCOL_SHARE = getIdlNumberConstant("MAX_PROTOCOL_SHARE");
34
34
  export const MAX_BASIS_POINTS = getIdlNumberConstant("MAX_BASIS_POINTS");
35
35
  export const DYNAMIC_FEE_DIVISOR = getIdlBigIntConstant("DYNAMIC_FEE_DIVISOR");
36
36
  export const MAX_POSITIONS_PER_CLAIM = 3;
37
+ // Client-side floor, not a protocol constant: generateBinArrayIndicesForSwap/ForSync's index
38
+ // math (utils/bin_location.ts) always excludes the pool's active bin array when the count is 1
39
+ // — 2 is the smallest binArrayCount that's guaranteed to include it, which the on-chain program
40
+ // requires (see Pool.swap/quote/sync in entities/pool.ts).
41
+ export const MIN_BIN_ARRAYS_PER_SWAP = 2;
42
+ export const MIN_BIN_ARRAYS_PER_SYNC = 2;
37
43
  // Solana RPC's own hard cap on addresses per getMultipleAccounts request.
38
44
  export const MAX_ACCOUNTS_PER_RPC_BATCH = 100;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@picon-finance/dlmm-sdk",
3
- "version": "1.7.0",
3
+ "version": "1.9.0",
4
4
  "description": "Typescript SDK for interacting with the Picon DLMM protocol",
5
5
  "author": "Picon Finance",
6
6
  "license": "MIT",
@@ -78,7 +78,7 @@ export class DlmmProgram {
78
78
  public async swap(
79
79
  user: TransactionSigner,
80
80
  poolAddress: Address,
81
- params: { xToY: boolean, amountIn: bigint, minAmountOut: bigint },
81
+ params: { xToY: boolean, amountIn: bigint, minAmountOut: bigint, binArrayCount?: number },
82
82
  config?: FetchAccountConfig,
83
83
  ): Promise<Instruction[]> {
84
84
  const pool = await this.getPool(poolAddress, config);
@@ -87,7 +87,7 @@ export class DlmmProgram {
87
87
 
88
88
  public async quote(
89
89
  poolAddress: Address,
90
- params: { xToY: boolean, amountIn: bigint, slippageToleranceBps: number },
90
+ params: { xToY: boolean, amountIn: bigint, slippageToleranceBps: number, binArrayCount?: number },
91
91
  config?: FetchAccountConfig,
92
92
  ): Promise<QuoteOutput> {
93
93
  const pool = await this.getPool(poolAddress, config);
@@ -97,7 +97,7 @@ export class DlmmProgram {
97
97
  public async quoteAndSwap(
98
98
  user: TransactionSigner,
99
99
  poolAddress: Address,
100
- params: { xToY: boolean, amountIn: bigint, slippageToleranceBps: number },
100
+ params: { xToY: boolean, amountIn: bigint, slippageToleranceBps: number, binArrayCount?: number },
101
101
  config?: FetchAccountConfig,
102
102
  ): Promise<{ quoteOutput: QuoteOutput, instructions: Instruction[] }> {
103
103
  const pool = await this.getPool(poolAddress, config);
@@ -16,10 +16,13 @@ import {
16
16
  import { generated } from "..";
17
17
  import {
18
18
  quote,
19
+ getPoolFeeRates,
20
+ type FeeRates,
19
21
  type QuoteOutput,
20
22
  type TransferFee,
21
23
  } from "../quote";
22
24
  import { isAccount } from "../utils/type_guards";
25
+ import { assertInRange } from "../utils/assert";
23
26
  import { resolveAdminConfigAddress } from "./admin_config";
24
27
  import { processAssociatedTokenAccountPair } from "../utils/ata";
25
28
  import {
@@ -29,7 +32,9 @@ import {
29
32
  import { resolveTransferFee } from "../utils/transfer_fee";
30
33
  import {
31
34
  MAX_BIN_ARRAYS_PER_SWAP,
35
+ MIN_BIN_ARRAYS_PER_SWAP,
32
36
  MAX_BIN_ARRAYS_PER_SYNC,
37
+ MIN_BIN_ARRAYS_PER_SYNC,
33
38
  } from "../utils/constants";
34
39
  import {
35
40
  Position,
@@ -90,6 +95,10 @@ export class Pool {
90
95
  };
91
96
  }
92
97
 
98
+ public async getFeeRates(now: bigint = BigInt(Math.floor(Date.now() / 1000))): Promise<FeeRates> {
99
+ return await getPoolFeeRates(this.data, now);
100
+ }
101
+
93
102
  public async refresh(data: Account<generated.Pool>): Promise<void>;
94
103
  public async refresh(config?: FetchAccountConfig): Promise<void>;
95
104
  public async refresh(arg?: Account<generated.Pool> | FetchAccountConfig) {
@@ -156,13 +165,16 @@ export class Pool {
156
165
  xToY,
157
166
  amountIn,
158
167
  minAmountOut,
168
+ binArrayCount = MAX_BIN_ARRAYS_PER_SWAP,
159
169
  }: {
160
170
  xToY: boolean,
161
171
  amountIn: bigint,
162
172
  minAmountOut: bigint,
173
+ binArrayCount?: number,
163
174
  }
164
175
  ): Promise<Instruction[]> {
165
- const indices = generateBinArrayIndicesForSwap(this.activeBinId, xToY, MAX_BIN_ARRAYS_PER_SWAP);
176
+ assertInRange(binArrayCount, MIN_BIN_ARRAYS_PER_SWAP, MAX_BIN_ARRAYS_PER_SWAP, "binArrayCount");
177
+ const indices = generateBinArrayIndicesForSwap(this.activeBinId, xToY, binArrayCount);
166
178
  const [binArrayAddresses, {
167
179
  ataX: tokenUserAccountX,
168
180
  ataY: tokenUserAccountY,
@@ -211,13 +223,16 @@ export class Pool {
211
223
  xToY,
212
224
  amountIn,
213
225
  slippageToleranceBps,
226
+ binArrayCount = MAX_BIN_ARRAYS_PER_SWAP,
214
227
  }: {
215
228
  xToY: boolean,
216
229
  amountIn: bigint,
217
230
  slippageToleranceBps: number,
231
+ binArrayCount?: number,
218
232
  }
219
233
  ): Promise<QuoteOutput> {
220
- const indices = generateBinArrayIndicesForSwap(this.activeBinId, xToY, MAX_BIN_ARRAYS_PER_SWAP);
234
+ assertInRange(binArrayCount, MIN_BIN_ARRAYS_PER_SWAP, MAX_BIN_ARRAYS_PER_SWAP, "binArrayCount");
235
+ const indices = generateBinArrayIndicesForSwap(this.activeBinId, xToY, binArrayCount);
221
236
  const binArrayAddresses = await findAllBinArrayAddresses(
222
237
  { pool: this.address, indices },
223
238
  { programAddress: this.#programAddress },
@@ -247,22 +262,26 @@ export class Pool {
247
262
  xToY,
248
263
  amountIn,
249
264
  slippageToleranceBps,
265
+ binArrayCount = MAX_BIN_ARRAYS_PER_SWAP,
250
266
  }: {
251
267
  xToY: boolean,
252
268
  amountIn: bigint,
253
269
  slippageToleranceBps: number,
270
+ binArrayCount?: number,
254
271
  }
255
272
  ): Promise<{ quoteOutput: QuoteOutput, instructions: Instruction[] }> {
256
- const quoteOutput = await this.quote({ xToY, amountIn, slippageToleranceBps });
257
- const instructions = await this.swap(user, { xToY, amountIn, minAmountOut: quoteOutput.minAmountOut });
273
+ const quoteOutput = await this.quote({ xToY, amountIn, slippageToleranceBps, binArrayCount });
274
+ const instructions = await this.swap(user, { xToY, amountIn, minAmountOut: quoteOutput.minAmountOut, binArrayCount });
258
275
  return { quoteOutput, instructions };
259
276
  }
260
277
 
261
278
  public async sync(
262
279
  user: TransactionSigner,
263
280
  desiredBinId: number,
281
+ binArrayCount: number = MAX_BIN_ARRAYS_PER_SYNC,
264
282
  ): Promise<Instruction[]> {
265
- const indices = generateBinArrayIndicesForSync(this.activeBinId, desiredBinId, MAX_BIN_ARRAYS_PER_SYNC);
283
+ assertInRange(binArrayCount, MIN_BIN_ARRAYS_PER_SYNC, MAX_BIN_ARRAYS_PER_SYNC, "binArrayCount");
284
+ const indices = generateBinArrayIndicesForSync(this.activeBinId, desiredBinId, binArrayCount);
266
285
  const binArrayAddresses = await findAllBinArrayAddresses(
267
286
  { pool: this.address, indices },
268
287
  { programAddress: this.#programAddress },
@@ -28,9 +28,15 @@ import {
28
28
  assertPositionBelongsToPool,
29
29
  } from "../utils/assert";
30
30
  import { isUndefined } from "../utils/type_guards";
31
- import { fetchInChunks } from "../utils/chunk";
31
+ import {
32
+ chunk,
33
+ fetchInChunks,
34
+ } from "../utils/chunk";
32
35
  import { resolveAdminConfigAddress } from "./admin_config";
33
- import { MAX_ACCOUNTS_PER_RPC_BATCH } from "../utils/constants";
36
+ import {
37
+ MAX_POSITIONS_PER_CLAIM,
38
+ MAX_ACCOUNTS_PER_RPC_BATCH,
39
+ } from "../utils/constants";
34
40
 
35
41
  import { Pool } from "./pool";
36
42
  import {
@@ -224,31 +230,18 @@ export class Position {
224
230
  return [...preInstructions, depositByWeightIx, ...postInstructions];
225
231
  }
226
232
 
227
- public async claimFee(
233
+ async #buildClaimFeeInstruction(
228
234
  owner: TransactionSigner,
235
+ positionTokenAccount: Address,
236
+ tokenOwnerAccountX: Address,
237
+ tokenOwnerAccountY: Address,
229
238
  range?: BinIdRange,
230
- ): Promise<Instruction[]> {
239
+ ): Promise<Instruction> {
231
240
  const { lowerBinId, upperBinId } = range ?? this.data;
232
241
  assertRangeWithinRange({ lowerBinId, upperBinId }, this.data);
233
242
 
234
- const [positionTokenAccount, {
235
- ataX: tokenOwnerAccountX,
236
- ataY: tokenOwnerAccountY,
237
- preInstructions,
238
- postInstructions
239
- }] = await Promise.all([
240
- findPositionTokenAccount({ owner: owner.address, positionMint: this.data.positionMint }),
241
- processAssociatedTokenAccountPair({
242
- owner,
243
- tokenMintX: this.#pool.tokenMintX,
244
- tokenMintY: this.#pool.tokenMintY,
245
- tokenProgramX: this.#pool.tokenProgramX,
246
- tokenProgramY: this.#pool.tokenProgramY,
247
- }),
248
- ]);
249
-
250
243
  const { lowerBinArray, upperBinArray } = this.binArrayAddresses;
251
- const claimFeeIx = generated.getClaimFeeInstruction({
244
+ return generated.getClaimFeeInstruction({
252
245
  owner,
253
246
  pool: this.#pool.address,
254
247
  position: this.address,
@@ -268,6 +261,31 @@ export class Position {
268
261
  }, {
269
262
  programAddress: this.#pool.programAddress
270
263
  });
264
+ }
265
+
266
+ public async claimFee(
267
+ owner: TransactionSigner,
268
+ range?: BinIdRange,
269
+ ): Promise<Instruction[]> {
270
+ const [positionTokenAccount, {
271
+ ataX: tokenOwnerAccountX,
272
+ ataY: tokenOwnerAccountY,
273
+ preInstructions,
274
+ postInstructions
275
+ }] = await Promise.all([
276
+ findPositionTokenAccount({ owner: owner.address, positionMint: this.data.positionMint }),
277
+ processAssociatedTokenAccountPair({
278
+ owner,
279
+ tokenMintX: this.#pool.tokenMintX,
280
+ tokenMintY: this.#pool.tokenMintY,
281
+ tokenProgramX: this.#pool.tokenProgramX,
282
+ tokenProgramY: this.#pool.tokenProgramY,
283
+ }),
284
+ ]);
285
+
286
+ const claimFeeIx = await this.#buildClaimFeeInstruction(
287
+ owner, positionTokenAccount, tokenOwnerAccountX, tokenOwnerAccountY, range,
288
+ );
271
289
 
272
290
  return [...preInstructions, claimFeeIx, ...postInstructions];
273
291
  }
@@ -399,6 +417,49 @@ export class Position {
399
417
  position.#binArrays.map(binArray => binArrayByAddress.get(binArray.address)!),
400
418
  ])));
401
419
  }
420
+
421
+ public static async claimAllFees(
422
+ owner: TransactionSigner,
423
+ positions: Position[],
424
+ positionsPerClaim: number = MAX_POSITIONS_PER_CLAIM,
425
+ ): Promise<Instruction[][]> {
426
+ if (positions.length === 0) {
427
+ return [];
428
+ }
429
+
430
+ const pool = positions[0].#pool;
431
+ for (const position of positions) {
432
+ assertPositionBelongsToPool(position.data, pool);
433
+ }
434
+
435
+ const claimablePositions = positions.filter(position =>
436
+ position.getBinInfos().some(({ feeX, feeY }) => feeX > 0n || feeY > 0n));
437
+ if (claimablePositions.length === 0) {
438
+ return [];
439
+ }
440
+
441
+ const [positionTokenAccounts, { ataX, ataY, preInstructions, postInstructions }] = await Promise.all([
442
+ Promise.all(claimablePositions.map(position =>
443
+ findPositionTokenAccount({ owner: owner.address, positionMint: position.data.positionMint }))),
444
+ processAssociatedTokenAccountPair({
445
+ owner,
446
+ tokenMintX: pool.tokenMintX,
447
+ tokenMintY: pool.tokenMintY,
448
+ tokenProgramX: pool.tokenProgramX,
449
+ tokenProgramY: pool.tokenProgramY,
450
+ }),
451
+ ]);
452
+
453
+ const claimFeeIxs = await Promise.all(claimablePositions.map((position, i) =>
454
+ position.#buildClaimFeeInstruction(owner, positionTokenAccounts[i], ataX, ataY)));
455
+
456
+ const chunks = chunk(claimFeeIxs, positionsPerClaim);
457
+ return chunks.map((claimFeeIxsChunk, i) => [
458
+ ...(i === 0 ? preInstructions : []),
459
+ ...claimFeeIxsChunk,
460
+ ...(i === chunks.length - 1 ? postInstructions : []),
461
+ ]);
462
+ }
402
463
  }
403
464
 
404
465
  export async function findPositionAddress(
package/src/index.ts CHANGED
@@ -4,5 +4,5 @@ export * as events from "./events";
4
4
  export * from "./entities";
5
5
  export * from "./utils/constants";
6
6
  export { NATIVE_MINT_ADDRESS } from "./utils/ata";
7
- export type { QuoteOutput, TransferFee } from "./quote";
7
+ export type { QuoteOutput, TransferFee, FeeRates } from "./quote";
8
8
  export * from "./program_addresses";
@@ -4,9 +4,10 @@ import {
4
4
  type QuoteOutput,
5
5
  type PoolState,
6
6
  type TransferFee,
7
+ type FeeRates,
7
8
  } from "#wasm";
8
9
 
9
- export type { QuoteInput, QuoteOutput, PoolState, TransferFee };
10
+ export type { QuoteInput, QuoteOutput, PoolState, TransferFee, FeeRates };
10
11
 
11
12
  export async function quote(input: QuoteInput): Promise<QuoteOutput> {
12
13
  const wasm = await loadWasm();
@@ -17,3 +18,11 @@ export async function applyTransferFee(amount: bigint, fee?: TransferFee): Promi
17
18
  const wasm = await loadWasm();
18
19
  return wasm.applyTransferFee(amount, fee);
19
20
  }
21
+
22
+ // Decays the dynamic fee state to `now` first (the same "clock sim" the program does on-chain
23
+ // right before pricing a real swap), so the returned rates reflect what a swap would actually
24
+ // pay right now rather than the raw, potentially stale, stored volatility_accumulator.
25
+ export async function getPoolFeeRates(poolState: PoolState, now: bigint): Promise<FeeRates> {
26
+ const wasm = await loadWasm();
27
+ return wasm.getPoolFeeRates(poolState, now);
28
+ }
@@ -27,6 +27,12 @@ export interface DynamicFeeState {
27
27
  lastUpdateTimestamp: bigint;
28
28
  }
29
29
 
30
+ export interface FeeRates {
31
+ baseFeeRate: bigint;
32
+ dynamicFeeRate: bigint;
33
+ totalFeeRate: bigint;
34
+ }
35
+
30
36
  export interface PoolState {
31
37
  binStep: number;
32
38
  feeRate: number;
@@ -67,4 +73,12 @@ export interface TransferFee {
67
73
  */
68
74
  export function applyTransferFee(amount: bigint, fee?: TransferFee | null): bigint;
69
75
 
76
+ /**
77
+ * Base/dynamic/total fee rate `pool_state` would charge for a swap happening at `now` —
78
+ * decays the dynamic fee state to `now` first (the same "clock sim" `decay_dynamic_fee` does
79
+ * on-chain right before pricing a real swap), so this reflects what a swap would actually pay
80
+ * rather than the raw, potentially stale, stored `volatility_accumulator`.
81
+ */
82
+ export function getPoolFeeRates(pool_state: PoolState, now: bigint): FeeRates;
83
+
70
84
  export function quote(input: QuoteInput): QuoteOutput;
@@ -17,6 +17,20 @@ export function applyTransferFee(amount, fee) {
17
17
  return BigInt.asUintN(64, ret[0]);
18
18
  }
19
19
 
20
+ /**
21
+ * Base/dynamic/total fee rate `pool_state` would charge for a swap happening at `now` —
22
+ * decays the dynamic fee state to `now` first (the same "clock sim" `decay_dynamic_fee` does
23
+ * on-chain right before pricing a real swap), so this reflects what a swap would actually pay
24
+ * rather than the raw, potentially stale, stored `volatility_accumulator`.
25
+ * @param {PoolState} pool_state
26
+ * @param {bigint} now
27
+ * @returns {FeeRates}
28
+ */
29
+ export function getPoolFeeRates(pool_state, now) {
30
+ const ret = wasm.getPoolFeeRates(pool_state, now);
31
+ return ret;
32
+ }
33
+
20
34
  /**
21
35
  * @param {QuoteInput} input
22
36
  * @returns {QuoteOutput}
@@ -2,6 +2,7 @@
2
2
  /* eslint-disable */
3
3
  export const memory: WebAssembly.Memory;
4
4
  export const applyTransferFee: (a: bigint, b: number) => [bigint, number, number];
5
+ export const getPoolFeeRates: (a: any, b: bigint) => any;
5
6
  export const quote: (a: any) => [number, number, number];
6
7
  export const __wbindgen_malloc: (a: number, b: number) => number;
7
8
  export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
@@ -27,6 +27,12 @@ export interface DynamicFeeState {
27
27
  lastUpdateTimestamp: bigint;
28
28
  }
29
29
 
30
+ export interface FeeRates {
31
+ baseFeeRate: bigint;
32
+ dynamicFeeRate: bigint;
33
+ totalFeeRate: bigint;
34
+ }
35
+
30
36
  export interface PoolState {
31
37
  binStep: number;
32
38
  feeRate: number;
@@ -67,6 +73,14 @@ export interface TransferFee {
67
73
  */
68
74
  export function applyTransferFee(amount: bigint, fee?: TransferFee | null): bigint;
69
75
 
76
+ /**
77
+ * Base/dynamic/total fee rate `pool_state` would charge for a swap happening at `now` —
78
+ * decays the dynamic fee state to `now` first (the same "clock sim" `decay_dynamic_fee` does
79
+ * on-chain right before pricing a real swap), so this reflects what a swap would actually pay
80
+ * rather than the raw, potentially stale, stored `volatility_accumulator`.
81
+ */
82
+ export function getPoolFeeRates(pool_state: PoolState, now: bigint): FeeRates;
83
+
70
84
  export function quote(input: QuoteInput): QuoteOutput;
71
85
 
72
86
  export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
@@ -74,6 +88,7 @@ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembl
74
88
  export interface InitOutput {
75
89
  readonly memory: WebAssembly.Memory;
76
90
  readonly applyTransferFee: (a: bigint, b: number) => [bigint, number, number];
91
+ readonly getPoolFeeRates: (a: any, b: bigint) => any;
77
92
  readonly quote: (a: any) => [number, number, number];
78
93
  readonly __wbindgen_malloc: (a: number, b: number) => number;
79
94
  readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
@@ -15,6 +15,20 @@ export function applyTransferFee(amount, fee) {
15
15
  return BigInt.asUintN(64, ret[0]);
16
16
  }
17
17
 
18
+ /**
19
+ * Base/dynamic/total fee rate `pool_state` would charge for a swap happening at `now` —
20
+ * decays the dynamic fee state to `now` first (the same "clock sim" `decay_dynamic_fee` does
21
+ * on-chain right before pricing a real swap), so this reflects what a swap would actually pay
22
+ * rather than the raw, potentially stale, stored `volatility_accumulator`.
23
+ * @param {PoolState} pool_state
24
+ * @param {bigint} now
25
+ * @returns {FeeRates}
26
+ */
27
+ export function getPoolFeeRates(pool_state, now) {
28
+ const ret = wasm.getPoolFeeRates(pool_state, now);
29
+ return ret;
30
+ }
31
+
18
32
  /**
19
33
  * @param {QuoteInput} input
20
34
  * @returns {QuoteOutput}
@@ -2,6 +2,7 @@
2
2
  /* eslint-disable */
3
3
  export const memory: WebAssembly.Memory;
4
4
  export const applyTransferFee: (a: bigint, b: number) => [bigint, number, number];
5
+ export const getPoolFeeRates: (a: any, b: bigint) => any;
5
6
  export const quote: (a: any) => [number, number, number];
6
7
  export const __wbindgen_malloc: (a: number, b: number) => number;
7
8
  export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
@@ -13,6 +13,12 @@ export function assertRangeWithinRange(
13
13
  }
14
14
  }
15
15
 
16
+ export function assertInRange(value: number, min: number, max: number, label: string): void {
17
+ if (value < min || value > max) {
18
+ throw new RangeError(`${label} (${value}) must be between ${min} and ${max}`);
19
+ }
20
+ }
21
+
16
22
  export function assertPositionBelongsToPool(
17
23
  position: { pool: Address },
18
24
  pool: { address: Address },
@@ -41,5 +41,12 @@ export const DYNAMIC_FEE_DIVISOR = getIdlBigIntConstant("DYNAMIC_FEE_DIVISOR");
41
41
 
42
42
  export const MAX_POSITIONS_PER_CLAIM = 3;
43
43
 
44
+ // Client-side floor, not a protocol constant: generateBinArrayIndicesForSwap/ForSync's index
45
+ // math (utils/bin_location.ts) always excludes the pool's active bin array when the count is 1
46
+ // — 2 is the smallest binArrayCount that's guaranteed to include it, which the on-chain program
47
+ // requires (see Pool.swap/quote/sync in entities/pool.ts).
48
+ export const MIN_BIN_ARRAYS_PER_SWAP = 2;
49
+ export const MIN_BIN_ARRAYS_PER_SYNC = 2;
50
+
44
51
  // Solana RPC's own hard cap on addresses per getMultipleAccounts request.
45
52
  export const MAX_ACCOUNTS_PER_RPC_BATCH = 100;