@picon-finance/dlmm-sdk 1.6.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 +33 -6
- package/dist/entities/pool.d.ts +5 -1
- package/dist/entities/pool.d.ts.map +1 -1
- package/dist/entities/pool.js +10 -5
- package/dist/entities/position.d.ts +4 -5
- package/dist/entities/position.d.ts.map +1 -1
- package/dist/entities/position.js +105 -28
- package/dist/entities/types.d.ts +26 -0
- package/dist/entities/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/quote/index.d.ts +1 -0
- package/dist/quote/index.d.ts.map +1 -1
- package/dist/quote/index.js +4 -0
- package/dist/quote/wasm-node/picon_dlmm_quote.d.ts +6 -0
- package/dist/quote/wasm-node/picon_dlmm_quote.js +15 -0
- package/dist/quote/wasm-node/picon_dlmm_quote_bg.wasm +0 -0
- package/dist/quote/wasm-node/picon_dlmm_quote_bg.wasm.d.ts +1 -0
- package/dist/quote/wasm-web/picon_dlmm_quote.d.ts +7 -0
- package/dist/quote/wasm-web/picon_dlmm_quote.js +15 -0
- package/dist/quote/wasm-web/picon_dlmm_quote_bg.wasm +0 -0
- package/dist/quote/wasm-web/picon_dlmm_quote_bg.wasm.d.ts +1 -0
- package/package.json +1 -1
- package/src/entities/pool.ts +15 -6
- package/src/entities/position.ts +144 -38
- package/src/entities/types.ts +37 -1
- package/src/index.ts +1 -1
- package/src/quote/index.ts +5 -0
- package/src/quote/wasm-node/picon_dlmm_quote.d.ts +6 -0
- package/src/quote/wasm-node/picon_dlmm_quote.js +15 -0
- package/src/quote/wasm-node/picon_dlmm_quote_bg.wasm +0 -0
- package/src/quote/wasm-node/picon_dlmm_quote_bg.wasm.d.ts +1 -0
- package/src/quote/wasm-web/picon_dlmm_quote.d.ts +7 -0
- package/src/quote/wasm-web/picon_dlmm_quote.js +15 -0
- package/src/quote/wasm-web/picon_dlmm_quote_bg.wasm +0 -0
- package/src/quote/wasm-web/picon_dlmm_quote_bg.wasm.d.ts +1 -0
package/README.md
CHANGED
|
@@ -67,8 +67,8 @@ const openPositionIxs = await pool.openPosition(ownerSigner, positionMintSigner,
|
|
|
67
67
|
|
|
68
68
|
const position = await pool.getPositionByPositionMint(positionMintSigner.address);
|
|
69
69
|
|
|
70
|
-
// depositByWeight checks the deposit against the pool's cached activeBinId — if
|
|
71
|
-
//
|
|
70
|
+
// depositByWeight checks the deposit against the pool's cached activeBinId — if time has
|
|
71
|
+
// passed since pool was fetched (other activity could've moved the price since), refresh it
|
|
72
72
|
// first so the deposit isn't built/checked against a stale active bin.
|
|
73
73
|
await pool.refresh();
|
|
74
74
|
|
|
@@ -93,12 +93,28 @@ const closeIx = await position.close(ownerSigner);
|
|
|
93
93
|
console.log(position.data.lowerBinId, position.data.upperBinId);
|
|
94
94
|
```
|
|
95
95
|
|
|
96
|
-
`position.
|
|
96
|
+
`position.getInfo()` returns a full summary: deposited amounts and the total fee a `claimFee` call would sweep right now, each in both `gross*` (before any Token-2022 transfer fee) and `net*` (what you'd actually receive) forms, plus the per-bin data they're summed from:
|
|
97
97
|
|
|
98
98
|
```ts
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
const info = await position.getInfo();
|
|
100
|
+
console.log(`Deposited: ${info.netAmountX} X / ${info.netAmountY} Y`);
|
|
101
|
+
console.log(`Claimable fee: ${info.netFeeX} X / ${info.netFeeY} Y`);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`info.bins` (same as calling `position.getBinInfos()` directly) is the per-bin breakdown `getInfo()` sums to produce those totals — always raw, since `gross*`/`net*` only apply once, to the aggregate:
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
for (const { bin, amountX, amountY, feeX, feeY } of position.getBinInfos()) {
|
|
108
|
+
console.log(`bin ${bin.id}: deposited ${amountX} X / ${amountY} Y, fee ${feeX} X / ${feeY} Y`);
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Both are computed entirely from cached position + bin array data — `getBinInfos()` makes no RPC calls at all; `getInfo()` makes one round trip (via `Pool.getTransferFees()`) to resolve each mint's live transfer-fee rate.
|
|
113
|
+
|
|
114
|
+
`Pool.getTransferFees()` resolves each mint's active [Token-2022 transfer-fee](https://spl.solana.com/token-2022/extensions#transfer-fees) config from cached mint data — `undefined` per side means that mint has no `TransferFeeConfig` extension, not that the fee is zero:
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
const { transferFeeX, transferFeeY } = await pool.getTransferFees();
|
|
102
118
|
```
|
|
103
119
|
|
|
104
120
|
Refresh a position's cached state after it changes on-chain (e.g. after a deposit lands):
|
|
@@ -126,6 +142,17 @@ Or fetch a single position directly if you already know its address:
|
|
|
126
142
|
const positionByAddress = await pool.getPosition(positionAddress);
|
|
127
143
|
```
|
|
128
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
|
+
|
|
129
156
|
### Events
|
|
130
157
|
|
|
131
158
|
Event decoding and subscriptions are a separate, opt-in feature under the `events` namespace — independent of `DlmmProgram`/`Pool`/`Position`/`BinArray`:
|
package/dist/entities/pool.d.ts
CHANGED
|
@@ -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 } from "../quote";
|
|
3
|
+
import { 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 {
|
|
@@ -19,6 +19,10 @@ export declare class Pool {
|
|
|
19
19
|
get tokenVaultY(): Address;
|
|
20
20
|
get tokenProgramX(): Address;
|
|
21
21
|
get tokenProgramY(): Address;
|
|
22
|
+
getTransferFees(): Promise<{
|
|
23
|
+
transferFeeX?: TransferFee;
|
|
24
|
+
transferFeeY?: TransferFee;
|
|
25
|
+
}>;
|
|
22
26
|
refresh(data: Account<generated.Pool>): Promise<void>;
|
|
23
27
|
refresh(config?: FetchAccountConfig): Promise<void>;
|
|
24
28
|
getPosition(address: Address, config?: FetchAccountsConfig): Promise<Position>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../../src/entities/pool.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EAEf,KAAK,OAAO,EACZ,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACzB,MAAM,aAAa,CAAC;AAMrB,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC/B,OAAO,
|
|
1
|
+
{"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../../src/entities/pool.ts"],"names":[],"mappings":"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"}
|
package/dist/entities/pool.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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, } from "../quote";
|
|
5
5
|
import { isAccount } from "../utils/type_guards";
|
|
6
6
|
import { resolveAdminConfigAddress } from "./admin_config";
|
|
7
7
|
import { processAssociatedTokenAccountPair } from "../utils/ata";
|
|
@@ -36,6 +36,13 @@ export class Pool {
|
|
|
36
36
|
get tokenVaultY() { return this.data.tokenVaultY; }
|
|
37
37
|
get tokenProgramX() { return this.#mintX.programAddress; }
|
|
38
38
|
get tokenProgramY() { return this.#mintY.programAddress; }
|
|
39
|
+
async getTransferFees() {
|
|
40
|
+
const { epoch } = await this.#rpc.getEpochInfo().send();
|
|
41
|
+
return {
|
|
42
|
+
transferFeeX: resolveTransferFee(this.#mintX.data, epoch),
|
|
43
|
+
transferFeeY: resolveTransferFee(this.#mintY.data, epoch),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
39
46
|
async refresh(arg) {
|
|
40
47
|
if (!isAccount(arg)) {
|
|
41
48
|
arg = await generated.fetchPool(this.#rpc, this.address, arg);
|
|
@@ -95,13 +102,11 @@ export class Pool {
|
|
|
95
102
|
async quote({ xToY, amountIn, slippageToleranceBps, }) {
|
|
96
103
|
const indices = generateBinArrayIndicesForSwap(this.activeBinId, xToY, MAX_BIN_ARRAYS_PER_SWAP);
|
|
97
104
|
const binArrayAddresses = await findAllBinArrayAddresses({ pool: this.address, indices }, { programAddress: this.#programAddress });
|
|
98
|
-
const [maybeBinArrays, {
|
|
105
|
+
const [maybeBinArrays, { transferFeeX, transferFeeY }] = await Promise.all([
|
|
99
106
|
generated.fetchAllMaybeBinArray(this.#rpc, binArrayAddresses),
|
|
100
|
-
this
|
|
107
|
+
this.getTransferFees(),
|
|
101
108
|
]);
|
|
102
109
|
const binArrays = maybeBinArrays.map(maybeBinArray => maybeBinArray.exists ? maybeBinArray.data : undefined);
|
|
103
|
-
const transferFeeX = resolveTransferFee(this.#mintX.data, epoch);
|
|
104
|
-
const transferFeeY = resolveTransferFee(this.#mintY.data, epoch);
|
|
105
110
|
return await quote({
|
|
106
111
|
amountIn,
|
|
107
112
|
xToY,
|
|
@@ -3,7 +3,7 @@ import { generated } from "..";
|
|
|
3
3
|
import { type BinIdRange } from "../utils/bin_location";
|
|
4
4
|
import { Pool } from "./pool";
|
|
5
5
|
import { BinArray } from "./bin_array";
|
|
6
|
-
import { type ProgramConfig } from "./types";
|
|
6
|
+
import { type PositionInfo, type ProgramConfig, type PositionBinInfo } from "./types";
|
|
7
7
|
export declare class Position {
|
|
8
8
|
#private;
|
|
9
9
|
private constructor();
|
|
@@ -15,10 +15,8 @@ export declare class Position {
|
|
|
15
15
|
lowerBinArray: Address;
|
|
16
16
|
upperBinArray?: Address | undefined;
|
|
17
17
|
};
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
amountY: bigint;
|
|
21
|
-
};
|
|
18
|
+
getBinInfos(): PositionBinInfo[];
|
|
19
|
+
getInfo(): Promise<PositionInfo>;
|
|
22
20
|
refresh(data: [Account<generated.Position>, Account<generated.BinArray>[]]): Promise<void>;
|
|
23
21
|
refresh(config?: FetchAccountsConfig): Promise<void>;
|
|
24
22
|
depositByWeight(owner: TransactionSigner, { amountX, amountY, lowerBinId, binWeights, maxActiveBinSlippage, distributionMode, }: {
|
|
@@ -35,6 +33,7 @@ export declare class Position {
|
|
|
35
33
|
static load(pool: Pool, address: Address, config?: FetchAccountsConfig): Promise<Position>;
|
|
36
34
|
static loadAll(pool: Pool, addresses: Address[], config?: FetchAccountsConfig): Promise<Position[]>;
|
|
37
35
|
static refreshAll(rpc: ReturnType<typeof createSolanaRpc>, positions: Position[], config?: FetchAccountsConfig): Promise<void>;
|
|
36
|
+
static claimAllFees(owner: TransactionSigner, positions: Position[], positionsPerClaim?: number): Promise<Instruction[][]>;
|
|
38
37
|
}
|
|
39
38
|
export declare function findPositionAddress(seeds: {
|
|
40
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;
|
|
1
|
+
{"version":3,"file":"position.d.ts","sourceRoot":"","sources":["../../src/entities/position.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { decodeAccount, assertAccountExists, fetchEncodedAccounts, } from "@solana/kit";
|
|
2
2
|
import { generated } from "..";
|
|
3
|
+
import { applyTransferFee } from "../quote";
|
|
3
4
|
import { findPositionTokenAccount, processAssociatedTokenAccountPair, } from "../utils/ata";
|
|
4
5
|
import { getBinIndex, getBinArrayIndex, getPositionBinArrayIndices, } from "../utils/bin_location";
|
|
5
6
|
import { assertRangeWithinRange, assertPositionBelongsToPool, } from "../utils/assert";
|
|
6
7
|
import { isUndefined } from "../utils/type_guards";
|
|
7
|
-
import { fetchInChunks } from "../utils/chunk";
|
|
8
|
+
import { chunk, fetchInChunks } from "../utils/chunk";
|
|
8
9
|
import { resolveAdminConfigAddress } from "./admin_config";
|
|
9
|
-
import { MAX_ACCOUNTS_PER_RPC_BATCH } from "../utils/constants";
|
|
10
|
+
import { MAX_ACCOUNTS_PER_RPC_BATCH, MAX_POSITIONS_PER_CLAIM } from "../utils/constants";
|
|
10
11
|
import { BinArray, decodeAllBinArrays, createAllBinArrays, fetchAllBinArraysChunked, } from "./bin_array";
|
|
11
12
|
export class Position {
|
|
12
13
|
#pool;
|
|
@@ -26,25 +27,68 @@ export class Position {
|
|
|
26
27
|
const upperBinArray = this.#binArrays.length > 1 ? this.#binArrays[1].address : undefined;
|
|
27
28
|
return { lowerBinArray, upperBinArray };
|
|
28
29
|
}
|
|
29
|
-
|
|
30
|
+
getBinInfos() {
|
|
30
31
|
const { lowerBinId, upperBinId, feeStates } = this.data;
|
|
31
32
|
const lowerBinArrayIndex = getBinArrayIndex(lowerBinId);
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return [];
|
|
33
|
+
const binCount = upperBinId - lowerBinId + 1;
|
|
34
|
+
return feeStates
|
|
35
|
+
.slice(0, binCount)
|
|
36
|
+
.map((feeState, i) => {
|
|
37
37
|
const binId = lowerBinId + i;
|
|
38
38
|
const binIndex = getBinIndex(binId);
|
|
39
|
-
const
|
|
40
|
-
const binArray = this.#binArrays[
|
|
39
|
+
const localBinArrayIndex = getBinArrayIndex(binId) - lowerBinArrayIndex;
|
|
40
|
+
const binArray = this.#binArrays[localBinArrayIndex];
|
|
41
41
|
const bin = binArray.bins[binIndex];
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
const amountX = bin.totalShares > 0n ? (feeState.shares * bin.amountX) / bin.totalShares : 0n;
|
|
43
|
+
const amountY = bin.totalShares > 0n ? (feeState.shares * bin.amountY) / bin.totalShares : 0n;
|
|
44
|
+
let feeX = feeState.feeOwedX;
|
|
45
|
+
let feeY = feeState.feeOwedY;
|
|
46
|
+
if (feeState.shares > 0n && bin.totalShares > 0n) {
|
|
47
|
+
feeX += earnedAmount(bin.feePerShareX, feeState.feePerShareCheckpointX, feeState.shares);
|
|
48
|
+
feeY += earnedAmount(bin.feePerShareY, feeState.feePerShareCheckpointY, feeState.shares);
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
bin: {
|
|
52
|
+
id: binId,
|
|
53
|
+
price: bin.price,
|
|
54
|
+
amountX: bin.amountX,
|
|
55
|
+
amountY: bin.amountY,
|
|
56
|
+
shares: bin.totalShares
|
|
57
|
+
},
|
|
58
|
+
amountX,
|
|
59
|
+
amountY,
|
|
60
|
+
shares: feeState.shares,
|
|
61
|
+
feeX,
|
|
62
|
+
feeY,
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
async getInfo() {
|
|
67
|
+
const bins = this.getBinInfos();
|
|
68
|
+
const gross = bins.reduce((acc, { amountX, amountY, feeX, feeY }) => ({
|
|
69
|
+
amountX: acc.amountX + amountX,
|
|
70
|
+
amountY: acc.amountY + amountY,
|
|
71
|
+
feeX: acc.feeX + feeX,
|
|
72
|
+
feeY: acc.feeY + feeY,
|
|
73
|
+
}), { amountX: 0n, amountY: 0n, feeX: 0n, feeY: 0n });
|
|
74
|
+
const { transferFeeX, transferFeeY } = await this.#pool.getTransferFees();
|
|
75
|
+
const [netAmountX, netAmountY, netFeeX, netFeeY] = await Promise.all([
|
|
76
|
+
applyTransferFee(gross.amountX, transferFeeX),
|
|
77
|
+
applyTransferFee(gross.amountY, transferFeeY),
|
|
78
|
+
applyTransferFee(gross.feeX, transferFeeX),
|
|
79
|
+
applyTransferFee(gross.feeY, transferFeeY),
|
|
80
|
+
]);
|
|
81
|
+
return {
|
|
82
|
+
bins,
|
|
83
|
+
grossAmountX: gross.amountX,
|
|
84
|
+
grossAmountY: gross.amountY,
|
|
85
|
+
netAmountX,
|
|
86
|
+
netAmountY,
|
|
87
|
+
grossFeeX: gross.feeX,
|
|
88
|
+
grossFeeY: gross.feeY,
|
|
89
|
+
netFeeX,
|
|
90
|
+
netFeeY,
|
|
91
|
+
};
|
|
48
92
|
}
|
|
49
93
|
async refresh(arg) {
|
|
50
94
|
if (!Array.isArray(arg)) {
|
|
@@ -97,21 +141,11 @@ export class Position {
|
|
|
97
141
|
});
|
|
98
142
|
return [...preInstructions, depositByWeightIx, ...postInstructions];
|
|
99
143
|
}
|
|
100
|
-
async
|
|
144
|
+
async #buildClaimFeeInstruction(owner, positionTokenAccount, tokenOwnerAccountX, tokenOwnerAccountY, range) {
|
|
101
145
|
const { lowerBinId, upperBinId } = range ?? this.data;
|
|
102
146
|
assertRangeWithinRange({ lowerBinId, upperBinId }, this.data);
|
|
103
|
-
const [positionTokenAccount, { ataX: tokenOwnerAccountX, ataY: tokenOwnerAccountY, preInstructions, postInstructions }] = await Promise.all([
|
|
104
|
-
findPositionTokenAccount({ owner: owner.address, positionMint: this.data.positionMint }),
|
|
105
|
-
processAssociatedTokenAccountPair({
|
|
106
|
-
owner,
|
|
107
|
-
tokenMintX: this.#pool.tokenMintX,
|
|
108
|
-
tokenMintY: this.#pool.tokenMintY,
|
|
109
|
-
tokenProgramX: this.#pool.tokenProgramX,
|
|
110
|
-
tokenProgramY: this.#pool.tokenProgramY,
|
|
111
|
-
}),
|
|
112
|
-
]);
|
|
113
147
|
const { lowerBinArray, upperBinArray } = this.binArrayAddresses;
|
|
114
|
-
|
|
148
|
+
return generated.getClaimFeeInstruction({
|
|
115
149
|
owner,
|
|
116
150
|
pool: this.#pool.address,
|
|
117
151
|
position: this.address,
|
|
@@ -131,6 +165,19 @@ export class Position {
|
|
|
131
165
|
}, {
|
|
132
166
|
programAddress: this.#pool.programAddress
|
|
133
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);
|
|
134
181
|
return [...preInstructions, claimFeeIx, ...postInstructions];
|
|
135
182
|
}
|
|
136
183
|
async withdraw(owner, bpsToRemove, range) {
|
|
@@ -209,6 +256,36 @@ export class Position {
|
|
|
209
256
|
position.#binArrays.map(binArray => binArrayByAddress.get(binArray.address)),
|
|
210
257
|
])));
|
|
211
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
|
+
}
|
|
212
289
|
}
|
|
213
290
|
export async function findPositionAddress(seeds, config) {
|
|
214
291
|
const [address] = await generated.findPositionPda(seeds, config);
|
package/dist/entities/types.d.ts
CHANGED
|
@@ -2,4 +2,30 @@ import { type Address } from "@solana/kit";
|
|
|
2
2
|
export type ProgramConfig = {
|
|
3
3
|
programAddress: Address;
|
|
4
4
|
};
|
|
5
|
+
export type BinInfo = {
|
|
6
|
+
id: number;
|
|
7
|
+
price: bigint;
|
|
8
|
+
amountX: bigint;
|
|
9
|
+
amountY: bigint;
|
|
10
|
+
shares: bigint;
|
|
11
|
+
};
|
|
12
|
+
export type PositionBinInfo = {
|
|
13
|
+
bin: BinInfo;
|
|
14
|
+
amountX: bigint;
|
|
15
|
+
amountY: bigint;
|
|
16
|
+
shares: bigint;
|
|
17
|
+
feeX: bigint;
|
|
18
|
+
feeY: bigint;
|
|
19
|
+
};
|
|
20
|
+
export type PositionInfo = {
|
|
21
|
+
bins: PositionBinInfo[];
|
|
22
|
+
grossAmountX: bigint;
|
|
23
|
+
grossAmountY: bigint;
|
|
24
|
+
netAmountX: bigint;
|
|
25
|
+
netAmountY: bigint;
|
|
26
|
+
grossFeeX: bigint;
|
|
27
|
+
grossFeeY: bigint;
|
|
28
|
+
netFeeX: bigint;
|
|
29
|
+
netFeeY: bigint;
|
|
30
|
+
};
|
|
5
31
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/entities/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,MAAM,aAAa,GAAG;IAAE,cAAc,EAAE,OAAO,CAAA;CAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/entities/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,MAAM,aAAa,GAAG;IAAE,cAAc,EAAE,OAAO,CAAA;CAAE,CAAC;AAExD,MAAM,MAAM,OAAO,GAAG;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IAEd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,EAAE,OAAO,CAAC;IAEb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IAEf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,eAAe,EAAE,CAAC;IAExB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IAErB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IAEnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAElB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC"}
|
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 {
|
|
7
|
+
export type { QuoteOutput, TransferFee } from "./quote";
|
|
8
8
|
export * from "./program_addresses";
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/dist/quote/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type QuoteInput, type QuoteOutput, type PoolState, type TransferFee } from "#wasm";
|
|
2
2
|
export type { QuoteInput, QuoteOutput, PoolState, TransferFee };
|
|
3
3
|
export declare function quote(input: QuoteInput): Promise<QuoteOutput>;
|
|
4
|
+
export declare function applyTransferFee(amount: bigint, fee?: TransferFee): Promise<bigint>;
|
|
4
5
|
//# 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"}
|
|
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"}
|
package/dist/quote/index.js
CHANGED
|
@@ -61,4 +61,10 @@ export interface TransferFee {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Applies `fee` to a gross `amount`, returning the net amount — or `amount` unchanged when
|
|
66
|
+
* `fee` is `None` (the mint has no `TransferFeeConfig` extension).
|
|
67
|
+
*/
|
|
68
|
+
export function applyTransferFee(amount: bigint, fee?: TransferFee | null): bigint;
|
|
69
|
+
|
|
64
70
|
export function quote(input: QuoteInput): QuoteOutput;
|
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
import { readFileSync } from 'node:fs';
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Applies `fee` to a gross `amount`, returning the net amount — or `amount` unchanged when
|
|
7
|
+
* `fee` is `None` (the mint has no `TransferFeeConfig` extension).
|
|
8
|
+
* @param {bigint} amount
|
|
9
|
+
* @param {TransferFee | null} [fee]
|
|
10
|
+
* @returns {bigint}
|
|
11
|
+
*/
|
|
12
|
+
export function applyTransferFee(amount, fee) {
|
|
13
|
+
const ret = wasm.applyTransferFee(amount, isLikeNone(fee) ? 0 : addToExternrefTable0(fee));
|
|
14
|
+
if (ret[2]) {
|
|
15
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
16
|
+
}
|
|
17
|
+
return BigInt.asUintN(64, ret[0]);
|
|
18
|
+
}
|
|
19
|
+
|
|
5
20
|
/**
|
|
6
21
|
* @param {QuoteInput} input
|
|
7
22
|
* @returns {QuoteOutput}
|
|
Binary file
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* tslint:disable */
|
|
2
2
|
/* eslint-disable */
|
|
3
3
|
export const memory: WebAssembly.Memory;
|
|
4
|
+
export const applyTransferFee: (a: bigint, b: number) => [bigint, number, number];
|
|
4
5
|
export const quote: (a: any) => [number, number, number];
|
|
5
6
|
export const __wbindgen_malloc: (a: number, b: number) => number;
|
|
6
7
|
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
|
@@ -61,12 +61,19 @@ export interface TransferFee {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Applies `fee` to a gross `amount`, returning the net amount — or `amount` unchanged when
|
|
66
|
+
* `fee` is `None` (the mint has no `TransferFeeConfig` extension).
|
|
67
|
+
*/
|
|
68
|
+
export function applyTransferFee(amount: bigint, fee?: TransferFee | null): bigint;
|
|
69
|
+
|
|
64
70
|
export function quote(input: QuoteInput): QuoteOutput;
|
|
65
71
|
|
|
66
72
|
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
|
67
73
|
|
|
68
74
|
export interface InitOutput {
|
|
69
75
|
readonly memory: WebAssembly.Memory;
|
|
76
|
+
readonly applyTransferFee: (a: bigint, b: number) => [bigint, number, number];
|
|
70
77
|
readonly quote: (a: any) => [number, number, number];
|
|
71
78
|
readonly __wbindgen_malloc: (a: number, b: number) => number;
|
|
72
79
|
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
/* @ts-self-types="./picon_dlmm_quote.d.ts" */
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Applies `fee` to a gross `amount`, returning the net amount — or `amount` unchanged when
|
|
5
|
+
* `fee` is `None` (the mint has no `TransferFeeConfig` extension).
|
|
6
|
+
* @param {bigint} amount
|
|
7
|
+
* @param {TransferFee | null} [fee]
|
|
8
|
+
* @returns {bigint}
|
|
9
|
+
*/
|
|
10
|
+
export function applyTransferFee(amount, fee) {
|
|
11
|
+
const ret = wasm.applyTransferFee(amount, isLikeNone(fee) ? 0 : addToExternrefTable0(fee));
|
|
12
|
+
if (ret[2]) {
|
|
13
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
14
|
+
}
|
|
15
|
+
return BigInt.asUintN(64, ret[0]);
|
|
16
|
+
}
|
|
17
|
+
|
|
3
18
|
/**
|
|
4
19
|
* @param {QuoteInput} input
|
|
5
20
|
* @returns {QuoteOutput}
|
|
Binary file
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* tslint:disable */
|
|
2
2
|
/* eslint-disable */
|
|
3
3
|
export const memory: WebAssembly.Memory;
|
|
4
|
+
export const applyTransferFee: (a: bigint, b: number) => [bigint, number, number];
|
|
4
5
|
export const quote: (a: any) => [number, number, number];
|
|
5
6
|
export const __wbindgen_malloc: (a: number, b: number) => number;
|
|
6
7
|
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
package/package.json
CHANGED
package/src/entities/pool.ts
CHANGED
|
@@ -14,7 +14,11 @@ import {
|
|
|
14
14
|
} from "@solana-program/token-2022";
|
|
15
15
|
|
|
16
16
|
import { generated } from "..";
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
quote,
|
|
19
|
+
type QuoteOutput,
|
|
20
|
+
type TransferFee,
|
|
21
|
+
} from "../quote";
|
|
18
22
|
import { isAccount } from "../utils/type_guards";
|
|
19
23
|
import { resolveAdminConfigAddress } from "./admin_config";
|
|
20
24
|
import { processAssociatedTokenAccountPair } from "../utils/ata";
|
|
@@ -78,6 +82,14 @@ export class Pool {
|
|
|
78
82
|
public get tokenProgramX() { return this.#mintX.programAddress; }
|
|
79
83
|
public get tokenProgramY() { return this.#mintY.programAddress; }
|
|
80
84
|
|
|
85
|
+
public async getTransferFees(): Promise<{ transferFeeX?: TransferFee, transferFeeY?: TransferFee }> {
|
|
86
|
+
const { epoch } = await this.#rpc.getEpochInfo().send();
|
|
87
|
+
return {
|
|
88
|
+
transferFeeX: resolveTransferFee(this.#mintX.data, epoch),
|
|
89
|
+
transferFeeY: resolveTransferFee(this.#mintY.data, epoch),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
81
93
|
public async refresh(data: Account<generated.Pool>): Promise<void>;
|
|
82
94
|
public async refresh(config?: FetchAccountConfig): Promise<void>;
|
|
83
95
|
public async refresh(arg?: Account<generated.Pool> | FetchAccountConfig) {
|
|
@@ -211,15 +223,12 @@ export class Pool {
|
|
|
211
223
|
{ programAddress: this.#programAddress },
|
|
212
224
|
);
|
|
213
225
|
|
|
214
|
-
const [maybeBinArrays, {
|
|
226
|
+
const [maybeBinArrays, { transferFeeX, transferFeeY }] = await Promise.all([
|
|
215
227
|
generated.fetchAllMaybeBinArray(this.#rpc, binArrayAddresses),
|
|
216
|
-
this
|
|
228
|
+
this.getTransferFees(),
|
|
217
229
|
]);
|
|
218
230
|
const binArrays = maybeBinArrays.map(maybeBinArray => maybeBinArray.exists ? maybeBinArray.data : undefined);
|
|
219
231
|
|
|
220
|
-
const transferFeeX = resolveTransferFee(this.#mintX.data, epoch);
|
|
221
|
-
const transferFeeY = resolveTransferFee(this.#mintY.data, epoch);
|
|
222
|
-
|
|
223
232
|
return await quote({
|
|
224
233
|
amountIn,
|
|
225
234
|
xToY,
|
package/src/entities/position.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
} from "@solana/kit";
|
|
13
13
|
|
|
14
14
|
import { generated } from "..";
|
|
15
|
+
import { applyTransferFee } from "../quote";
|
|
15
16
|
import {
|
|
16
17
|
findPositionTokenAccount,
|
|
17
18
|
processAssociatedTokenAccountPair,
|
|
@@ -27,9 +28,9 @@ import {
|
|
|
27
28
|
assertPositionBelongsToPool,
|
|
28
29
|
} from "../utils/assert";
|
|
29
30
|
import { isUndefined } from "../utils/type_guards";
|
|
30
|
-
import { fetchInChunks } from "../utils/chunk";
|
|
31
|
+
import { chunk, fetchInChunks } from "../utils/chunk";
|
|
31
32
|
import { resolveAdminConfigAddress } from "./admin_config";
|
|
32
|
-
import { MAX_ACCOUNTS_PER_RPC_BATCH } from "../utils/constants";
|
|
33
|
+
import { MAX_ACCOUNTS_PER_RPC_BATCH, MAX_POSITIONS_PER_CLAIM } from "../utils/constants";
|
|
33
34
|
|
|
34
35
|
import { Pool } from "./pool";
|
|
35
36
|
import {
|
|
@@ -38,7 +39,11 @@ import {
|
|
|
38
39
|
createAllBinArrays,
|
|
39
40
|
fetchAllBinArraysChunked,
|
|
40
41
|
} from "./bin_array";
|
|
41
|
-
import {
|
|
42
|
+
import {
|
|
43
|
+
type PositionInfo,
|
|
44
|
+
type ProgramConfig,
|
|
45
|
+
type PositionBinInfo,
|
|
46
|
+
} from "./types";
|
|
42
47
|
|
|
43
48
|
export class Position {
|
|
44
49
|
#pool: Pool;
|
|
@@ -66,29 +71,75 @@ export class Position {
|
|
|
66
71
|
return { lowerBinArray, upperBinArray };
|
|
67
72
|
}
|
|
68
73
|
|
|
69
|
-
public
|
|
74
|
+
public getBinInfos(): PositionBinInfo[] {
|
|
70
75
|
const { lowerBinId, upperBinId, feeStates } = this.data;
|
|
71
76
|
const lowerBinArrayIndex = getBinArrayIndex(lowerBinId);
|
|
77
|
+
const binCount = upperBinId - lowerBinId + 1;
|
|
72
78
|
|
|
73
|
-
return
|
|
74
|
-
.
|
|
75
|
-
|
|
76
|
-
if (feeState.shares === 0n) return [];
|
|
77
|
-
|
|
79
|
+
return feeStates
|
|
80
|
+
.slice(0, binCount)
|
|
81
|
+
.map((feeState, i) => {
|
|
78
82
|
const binId = lowerBinId + i;
|
|
79
|
-
|
|
80
83
|
const binIndex = getBinIndex(binId);
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
const binArray = this.#binArrays[binArrayIndex];
|
|
84
|
+
const localBinArrayIndex = getBinArrayIndex(binId) - lowerBinArrayIndex;
|
|
85
|
+
const binArray = this.#binArrays[localBinArrayIndex];
|
|
84
86
|
const bin = binArray.bins[binIndex];
|
|
85
87
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
const amountX = bin.totalShares > 0n ? (feeState.shares * bin.amountX) / bin.totalShares : 0n;
|
|
89
|
+
const amountY = bin.totalShares > 0n ? (feeState.shares * bin.amountY) / bin.totalShares : 0n;
|
|
90
|
+
|
|
91
|
+
let feeX = feeState.feeOwedX;
|
|
92
|
+
let feeY = feeState.feeOwedY;
|
|
93
|
+
if (feeState.shares > 0n && bin.totalShares > 0n) {
|
|
94
|
+
feeX += earnedAmount(bin.feePerShareX, feeState.feePerShareCheckpointX, feeState.shares);
|
|
95
|
+
feeY += earnedAmount(bin.feePerShareY, feeState.feePerShareCheckpointY, feeState.shares);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
bin: {
|
|
100
|
+
id: binId,
|
|
101
|
+
price: bin.price,
|
|
102
|
+
amountX: bin.amountX,
|
|
103
|
+
amountY: bin.amountY,
|
|
104
|
+
shares: bin.totalShares
|
|
105
|
+
},
|
|
106
|
+
amountX,
|
|
107
|
+
amountY,
|
|
108
|
+
shares: feeState.shares,
|
|
109
|
+
feeX,
|
|
110
|
+
feeY,
|
|
111
|
+
};
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
public async getInfo(): Promise<PositionInfo> {
|
|
116
|
+
const bins = this.getBinInfos();
|
|
117
|
+
const gross = bins.reduce((acc, { amountX, amountY, feeX, feeY }) => ({
|
|
118
|
+
amountX: acc.amountX + amountX,
|
|
119
|
+
amountY: acc.amountY + amountY,
|
|
120
|
+
feeX: acc.feeX + feeX,
|
|
121
|
+
feeY: acc.feeY + feeY,
|
|
122
|
+
}), { amountX: 0n, amountY: 0n, feeX: 0n, feeY: 0n });
|
|
123
|
+
|
|
124
|
+
const { transferFeeX, transferFeeY } = await this.#pool.getTransferFees();
|
|
125
|
+
const [netAmountX, netAmountY, netFeeX, netFeeY] = await Promise.all([
|
|
126
|
+
applyTransferFee(gross.amountX, transferFeeX),
|
|
127
|
+
applyTransferFee(gross.amountY, transferFeeY),
|
|
128
|
+
applyTransferFee(gross.feeX, transferFeeX),
|
|
129
|
+
applyTransferFee(gross.feeY, transferFeeY),
|
|
130
|
+
]);
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
bins,
|
|
134
|
+
grossAmountX: gross.amountX,
|
|
135
|
+
grossAmountY: gross.amountY,
|
|
136
|
+
netAmountX,
|
|
137
|
+
netAmountY,
|
|
138
|
+
grossFeeX: gross.feeX,
|
|
139
|
+
grossFeeY: gross.feeY,
|
|
140
|
+
netFeeX,
|
|
141
|
+
netFeeY,
|
|
142
|
+
};
|
|
92
143
|
}
|
|
93
144
|
|
|
94
145
|
public async refresh(data: [Account<generated.Position>, Account<generated.BinArray>[]]): Promise<void>;
|
|
@@ -173,31 +224,18 @@ export class Position {
|
|
|
173
224
|
return [...preInstructions, depositByWeightIx, ...postInstructions];
|
|
174
225
|
}
|
|
175
226
|
|
|
176
|
-
|
|
227
|
+
async #buildClaimFeeInstruction(
|
|
177
228
|
owner: TransactionSigner,
|
|
229
|
+
positionTokenAccount: Address,
|
|
230
|
+
tokenOwnerAccountX: Address,
|
|
231
|
+
tokenOwnerAccountY: Address,
|
|
178
232
|
range?: BinIdRange,
|
|
179
|
-
): Promise<Instruction
|
|
233
|
+
): Promise<Instruction> {
|
|
180
234
|
const { lowerBinId, upperBinId } = range ?? this.data;
|
|
181
235
|
assertRangeWithinRange({ lowerBinId, upperBinId }, this.data);
|
|
182
236
|
|
|
183
|
-
const [positionTokenAccount, {
|
|
184
|
-
ataX: tokenOwnerAccountX,
|
|
185
|
-
ataY: tokenOwnerAccountY,
|
|
186
|
-
preInstructions,
|
|
187
|
-
postInstructions
|
|
188
|
-
}] = await Promise.all([
|
|
189
|
-
findPositionTokenAccount({ owner: owner.address, positionMint: this.data.positionMint }),
|
|
190
|
-
processAssociatedTokenAccountPair({
|
|
191
|
-
owner,
|
|
192
|
-
tokenMintX: this.#pool.tokenMintX,
|
|
193
|
-
tokenMintY: this.#pool.tokenMintY,
|
|
194
|
-
tokenProgramX: this.#pool.tokenProgramX,
|
|
195
|
-
tokenProgramY: this.#pool.tokenProgramY,
|
|
196
|
-
}),
|
|
197
|
-
]);
|
|
198
|
-
|
|
199
237
|
const { lowerBinArray, upperBinArray } = this.binArrayAddresses;
|
|
200
|
-
|
|
238
|
+
return generated.getClaimFeeInstruction({
|
|
201
239
|
owner,
|
|
202
240
|
pool: this.#pool.address,
|
|
203
241
|
position: this.address,
|
|
@@ -217,6 +255,31 @@ export class Position {
|
|
|
217
255
|
}, {
|
|
218
256
|
programAddress: this.#pool.programAddress
|
|
219
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
|
+
);
|
|
220
283
|
|
|
221
284
|
return [...preInstructions, claimFeeIx, ...postInstructions];
|
|
222
285
|
}
|
|
@@ -348,6 +411,49 @@ export class Position {
|
|
|
348
411
|
position.#binArrays.map(binArray => binArrayByAddress.get(binArray.address)!),
|
|
349
412
|
])));
|
|
350
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
|
+
}
|
|
351
457
|
}
|
|
352
458
|
|
|
353
459
|
export async function findPositionAddress(
|
package/src/entities/types.ts
CHANGED
|
@@ -1,3 +1,39 @@
|
|
|
1
1
|
import { type Address } from "@solana/kit";
|
|
2
2
|
|
|
3
|
-
export type ProgramConfig = { programAddress: Address };
|
|
3
|
+
export type ProgramConfig = { programAddress: Address };
|
|
4
|
+
|
|
5
|
+
export type BinInfo = {
|
|
6
|
+
id: number;
|
|
7
|
+
price: bigint;
|
|
8
|
+
|
|
9
|
+
amountX: bigint;
|
|
10
|
+
amountY: bigint;
|
|
11
|
+
shares: bigint;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type PositionBinInfo = {
|
|
15
|
+
bin: BinInfo;
|
|
16
|
+
|
|
17
|
+
amountX: bigint;
|
|
18
|
+
amountY: bigint;
|
|
19
|
+
shares: bigint;
|
|
20
|
+
|
|
21
|
+
feeX: bigint;
|
|
22
|
+
feeY: bigint;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type PositionInfo = {
|
|
26
|
+
bins: PositionBinInfo[];
|
|
27
|
+
|
|
28
|
+
grossAmountX: bigint;
|
|
29
|
+
grossAmountY: bigint;
|
|
30
|
+
|
|
31
|
+
netAmountX: bigint;
|
|
32
|
+
netAmountY: bigint;
|
|
33
|
+
|
|
34
|
+
grossFeeX: bigint;
|
|
35
|
+
grossFeeY: bigint;
|
|
36
|
+
|
|
37
|
+
netFeeX: bigint;
|
|
38
|
+
netFeeY: bigint;
|
|
39
|
+
};
|
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 {
|
|
7
|
+
export type { QuoteOutput, TransferFee } from "./quote";
|
|
8
8
|
export * from "./program_addresses";
|
package/src/quote/index.ts
CHANGED
|
@@ -12,3 +12,8 @@ export async function quote(input: QuoteInput): Promise<QuoteOutput> {
|
|
|
12
12
|
const wasm = await loadWasm();
|
|
13
13
|
return wasm.quote(input);
|
|
14
14
|
}
|
|
15
|
+
|
|
16
|
+
export async function applyTransferFee(amount: bigint, fee?: TransferFee): Promise<bigint> {
|
|
17
|
+
const wasm = await loadWasm();
|
|
18
|
+
return wasm.applyTransferFee(amount, fee);
|
|
19
|
+
}
|
|
@@ -61,4 +61,10 @@ export interface TransferFee {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Applies `fee` to a gross `amount`, returning the net amount — or `amount` unchanged when
|
|
66
|
+
* `fee` is `None` (the mint has no `TransferFeeConfig` extension).
|
|
67
|
+
*/
|
|
68
|
+
export function applyTransferFee(amount: bigint, fee?: TransferFee | null): bigint;
|
|
69
|
+
|
|
64
70
|
export function quote(input: QuoteInput): QuoteOutput;
|
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
import { readFileSync } from 'node:fs';
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Applies `fee` to a gross `amount`, returning the net amount — or `amount` unchanged when
|
|
7
|
+
* `fee` is `None` (the mint has no `TransferFeeConfig` extension).
|
|
8
|
+
* @param {bigint} amount
|
|
9
|
+
* @param {TransferFee | null} [fee]
|
|
10
|
+
* @returns {bigint}
|
|
11
|
+
*/
|
|
12
|
+
export function applyTransferFee(amount, fee) {
|
|
13
|
+
const ret = wasm.applyTransferFee(amount, isLikeNone(fee) ? 0 : addToExternrefTable0(fee));
|
|
14
|
+
if (ret[2]) {
|
|
15
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
16
|
+
}
|
|
17
|
+
return BigInt.asUintN(64, ret[0]);
|
|
18
|
+
}
|
|
19
|
+
|
|
5
20
|
/**
|
|
6
21
|
* @param {QuoteInput} input
|
|
7
22
|
* @returns {QuoteOutput}
|
|
Binary file
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* tslint:disable */
|
|
2
2
|
/* eslint-disable */
|
|
3
3
|
export const memory: WebAssembly.Memory;
|
|
4
|
+
export const applyTransferFee: (a: bigint, b: number) => [bigint, number, number];
|
|
4
5
|
export const quote: (a: any) => [number, number, number];
|
|
5
6
|
export const __wbindgen_malloc: (a: number, b: number) => number;
|
|
6
7
|
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
|
@@ -61,12 +61,19 @@ export interface TransferFee {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Applies `fee` to a gross `amount`, returning the net amount — or `amount` unchanged when
|
|
66
|
+
* `fee` is `None` (the mint has no `TransferFeeConfig` extension).
|
|
67
|
+
*/
|
|
68
|
+
export function applyTransferFee(amount: bigint, fee?: TransferFee | null): bigint;
|
|
69
|
+
|
|
64
70
|
export function quote(input: QuoteInput): QuoteOutput;
|
|
65
71
|
|
|
66
72
|
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
|
67
73
|
|
|
68
74
|
export interface InitOutput {
|
|
69
75
|
readonly memory: WebAssembly.Memory;
|
|
76
|
+
readonly applyTransferFee: (a: bigint, b: number) => [bigint, number, number];
|
|
70
77
|
readonly quote: (a: any) => [number, number, number];
|
|
71
78
|
readonly __wbindgen_malloc: (a: number, b: number) => number;
|
|
72
79
|
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
/* @ts-self-types="./picon_dlmm_quote.d.ts" */
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Applies `fee` to a gross `amount`, returning the net amount — or `amount` unchanged when
|
|
5
|
+
* `fee` is `None` (the mint has no `TransferFeeConfig` extension).
|
|
6
|
+
* @param {bigint} amount
|
|
7
|
+
* @param {TransferFee | null} [fee]
|
|
8
|
+
* @returns {bigint}
|
|
9
|
+
*/
|
|
10
|
+
export function applyTransferFee(amount, fee) {
|
|
11
|
+
const ret = wasm.applyTransferFee(amount, isLikeNone(fee) ? 0 : addToExternrefTable0(fee));
|
|
12
|
+
if (ret[2]) {
|
|
13
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
14
|
+
}
|
|
15
|
+
return BigInt.asUintN(64, ret[0]);
|
|
16
|
+
}
|
|
17
|
+
|
|
3
18
|
/**
|
|
4
19
|
* @param {QuoteInput} input
|
|
5
20
|
* @returns {QuoteOutput}
|
|
Binary file
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* tslint:disable */
|
|
2
2
|
/* eslint-disable */
|
|
3
3
|
export const memory: WebAssembly.Memory;
|
|
4
|
+
export const applyTransferFee: (a: bigint, b: number) => [bigint, number, number];
|
|
4
5
|
export const quote: (a: any) => [number, number, number];
|
|
5
6
|
export const __wbindgen_malloc: (a: number, b: number) => number;
|
|
6
7
|
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|