@picon-finance/dlmm-sdk 1.7.0 → 1.8.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.
- package/README.md +11 -0
- package/dist/entities/position.d.ts +1 -0
- package/dist/entities/position.d.ts.map +1 -1
- package/dist/entities/position.js +47 -14
- package/package.json +1 -1
- package/src/entities/position.ts +76 -21
package/README.md
CHANGED
|
@@ -142,6 +142,17 @@ Or fetch a single position directly if you already know its address:
|
|
|
142
142
|
const positionByAddress = await pool.getPosition(positionAddress);
|
|
143
143
|
```
|
|
144
144
|
|
|
145
|
+
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:
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
const positions = await pool.getAllPositionsByPositionMints(positionMints);
|
|
149
|
+
const claimTxs = await Position.claimAllFees(ownerSigner, positions);
|
|
150
|
+
|
|
151
|
+
for (const claimIxs of claimTxs) {
|
|
152
|
+
// build + send one transaction per entry
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
145
156
|
### Events
|
|
146
157
|
|
|
147
158
|
Event decoding and subscriptions are a separate, opt-in feature under the `events` namespace — independent of `DlmmProgram`/`Pool`/`Position`/`BinArray`:
|
|
@@ -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":"AAAA,OAAO,EAEL,eAAe,EAGf,KAAK,OAAO,EACZ,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EAEzB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAM/B,OAAO,EAIL,KAAK,UAAU,EAChB,MAAM,uBAAuB,CAAC;AAU/B,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EACL,QAAQ,EAIT,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,eAAe,EACrB,MAAM,SAAS,CAAC;AAEjB,qBAAa,QAAQ;;IAKnB,OAAO,eAQN;IAED,IAAW,OAAO,oBAAoC;IACtD,IAAW,IAAI,uBAAiC;IAChD,IAAW,YAAY,YAAqC;IAC5D,IAAW,SAAS,IAAI,SAAS,QAAQ,EAAE,CAA4B;IAEvE,IAAW,iBAAiB,IAAI;QAAE,aAAa,EAAE,OAAO,CAAC;QAAC,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;KAAE,CAI9F;IAEM,WAAW,IAAI,eAAe,EAAE,CAuCtC;IAEY,OAAO,IAAI,OAAO,CAAC,YAAY,CAAC,CA4B5C;IAEY,OAAO,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3F,OAAO,CAAC,MAAM,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAerD,eAAe,CAAC,KAAK,EAAE,iBAAiB,EAAE,EACrD,OAAO,EACP,OAAO,EACP,UAAU,EACV,UAAU,EACV,oBAAoB,EACpB,gBAAgB,GACjB,EAAE;QACD,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,EAAE,CAAC;QACrB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,gBAAgB,EAAE,SAAS,CAAC,gBAAgB,CAAC;KAC9C,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAkDzB;
|
|
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_ACCOUNTS_PER_RPC_BATCH, MAX_POSITIONS_PER_CLAIM } 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
|
|
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
|
-
|
|
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/package.json
CHANGED
package/src/entities/position.ts
CHANGED
|
@@ -28,9 +28,9 @@ 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 { chunk, fetchInChunks } from "../utils/chunk";
|
|
32
32
|
import { resolveAdminConfigAddress } from "./admin_config";
|
|
33
|
-
import { MAX_ACCOUNTS_PER_RPC_BATCH } from "../utils/constants";
|
|
33
|
+
import { MAX_ACCOUNTS_PER_RPC_BATCH, MAX_POSITIONS_PER_CLAIM } from "../utils/constants";
|
|
34
34
|
|
|
35
35
|
import { Pool } from "./pool";
|
|
36
36
|
import {
|
|
@@ -224,31 +224,18 @@ export class Position {
|
|
|
224
224
|
return [...preInstructions, depositByWeightIx, ...postInstructions];
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
-
|
|
227
|
+
async #buildClaimFeeInstruction(
|
|
228
228
|
owner: TransactionSigner,
|
|
229
|
+
positionTokenAccount: Address,
|
|
230
|
+
tokenOwnerAccountX: Address,
|
|
231
|
+
tokenOwnerAccountY: Address,
|
|
229
232
|
range?: BinIdRange,
|
|
230
|
-
): Promise<Instruction
|
|
233
|
+
): Promise<Instruction> {
|
|
231
234
|
const { lowerBinId, upperBinId } = range ?? this.data;
|
|
232
235
|
assertRangeWithinRange({ lowerBinId, upperBinId }, this.data);
|
|
233
236
|
|
|
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
237
|
const { lowerBinArray, upperBinArray } = this.binArrayAddresses;
|
|
251
|
-
|
|
238
|
+
return generated.getClaimFeeInstruction({
|
|
252
239
|
owner,
|
|
253
240
|
pool: this.#pool.address,
|
|
254
241
|
position: this.address,
|
|
@@ -268,6 +255,31 @@ export class Position {
|
|
|
268
255
|
}, {
|
|
269
256
|
programAddress: this.#pool.programAddress
|
|
270
257
|
});
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
public async claimFee(
|
|
261
|
+
owner: TransactionSigner,
|
|
262
|
+
range?: BinIdRange,
|
|
263
|
+
): Promise<Instruction[]> {
|
|
264
|
+
const [positionTokenAccount, {
|
|
265
|
+
ataX: tokenOwnerAccountX,
|
|
266
|
+
ataY: tokenOwnerAccountY,
|
|
267
|
+
preInstructions,
|
|
268
|
+
postInstructions
|
|
269
|
+
}] = await Promise.all([
|
|
270
|
+
findPositionTokenAccount({ owner: owner.address, positionMint: this.data.positionMint }),
|
|
271
|
+
processAssociatedTokenAccountPair({
|
|
272
|
+
owner,
|
|
273
|
+
tokenMintX: this.#pool.tokenMintX,
|
|
274
|
+
tokenMintY: this.#pool.tokenMintY,
|
|
275
|
+
tokenProgramX: this.#pool.tokenProgramX,
|
|
276
|
+
tokenProgramY: this.#pool.tokenProgramY,
|
|
277
|
+
}),
|
|
278
|
+
]);
|
|
279
|
+
|
|
280
|
+
const claimFeeIx = await this.#buildClaimFeeInstruction(
|
|
281
|
+
owner, positionTokenAccount, tokenOwnerAccountX, tokenOwnerAccountY, range,
|
|
282
|
+
);
|
|
271
283
|
|
|
272
284
|
return [...preInstructions, claimFeeIx, ...postInstructions];
|
|
273
285
|
}
|
|
@@ -399,6 +411,49 @@ export class Position {
|
|
|
399
411
|
position.#binArrays.map(binArray => binArrayByAddress.get(binArray.address)!),
|
|
400
412
|
])));
|
|
401
413
|
}
|
|
414
|
+
|
|
415
|
+
public static async claimAllFees(
|
|
416
|
+
owner: TransactionSigner,
|
|
417
|
+
positions: Position[],
|
|
418
|
+
positionsPerClaim: number = MAX_POSITIONS_PER_CLAIM,
|
|
419
|
+
): Promise<Instruction[][]> {
|
|
420
|
+
if (positions.length === 0) {
|
|
421
|
+
return [];
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
const pool = positions[0].#pool;
|
|
425
|
+
for (const position of positions) {
|
|
426
|
+
assertPositionBelongsToPool(position.data, pool);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
const claimablePositions = positions.filter(position =>
|
|
430
|
+
position.getBinInfos().some(({ feeX, feeY }) => feeX > 0n || feeY > 0n));
|
|
431
|
+
if (claimablePositions.length === 0) {
|
|
432
|
+
return [];
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
const [positionTokenAccounts, { ataX, ataY, preInstructions, postInstructions }] = await Promise.all([
|
|
436
|
+
Promise.all(claimablePositions.map(position =>
|
|
437
|
+
findPositionTokenAccount({ owner: owner.address, positionMint: position.data.positionMint }))),
|
|
438
|
+
processAssociatedTokenAccountPair({
|
|
439
|
+
owner,
|
|
440
|
+
tokenMintX: pool.tokenMintX,
|
|
441
|
+
tokenMintY: pool.tokenMintY,
|
|
442
|
+
tokenProgramX: pool.tokenProgramX,
|
|
443
|
+
tokenProgramY: pool.tokenProgramY,
|
|
444
|
+
}),
|
|
445
|
+
]);
|
|
446
|
+
|
|
447
|
+
const claimFeeIxs = await Promise.all(claimablePositions.map((position, i) =>
|
|
448
|
+
position.#buildClaimFeeInstruction(owner, positionTokenAccounts[i], ataX, ataY)));
|
|
449
|
+
|
|
450
|
+
const chunks = chunk(claimFeeIxs, positionsPerClaim);
|
|
451
|
+
return chunks.map((claimFeeIxsChunk, i) => [
|
|
452
|
+
...(i === 0 ? preInstructions : []),
|
|
453
|
+
...claimFeeIxsChunk,
|
|
454
|
+
...(i === chunks.length - 1 ? postInstructions : []),
|
|
455
|
+
]);
|
|
456
|
+
}
|
|
402
457
|
}
|
|
403
458
|
|
|
404
459
|
export async function findPositionAddress(
|