@picon-finance/dlmm-sdk 1.5.0 → 1.7.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 (36) hide show
  1. package/README.md +22 -6
  2. package/dist/entities/pool.d.ts +5 -1
  3. package/dist/entities/pool.d.ts.map +1 -1
  4. package/dist/entities/pool.js +10 -5
  5. package/dist/entities/position.d.ts +5 -5
  6. package/dist/entities/position.d.ts.map +1 -1
  7. package/dist/entities/position.js +59 -14
  8. package/dist/entities/types.d.ts +26 -0
  9. package/dist/entities/types.d.ts.map +1 -1
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/quote/index.d.ts +1 -0
  13. package/dist/quote/index.d.ts.map +1 -1
  14. package/dist/quote/index.js +4 -0
  15. package/dist/quote/wasm-node/picon_dlmm_quote.d.ts +6 -0
  16. package/dist/quote/wasm-node/picon_dlmm_quote.js +15 -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 +7 -0
  20. package/dist/quote/wasm-web/picon_dlmm_quote.js +15 -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/package.json +1 -1
  24. package/src/entities/pool.ts +15 -6
  25. package/src/entities/position.ts +69 -17
  26. package/src/entities/types.ts +37 -1
  27. package/src/index.ts +1 -1
  28. package/src/quote/index.ts +5 -0
  29. package/src/quote/wasm-node/picon_dlmm_quote.d.ts +6 -0
  30. package/src/quote/wasm-node/picon_dlmm_quote.js +15 -0
  31. package/src/quote/wasm-node/picon_dlmm_quote_bg.wasm +0 -0
  32. package/src/quote/wasm-node/picon_dlmm_quote_bg.wasm.d.ts +1 -0
  33. package/src/quote/wasm-web/picon_dlmm_quote.d.ts +7 -0
  34. package/src/quote/wasm-web/picon_dlmm_quote.js +15 -0
  35. package/src/quote/wasm-web/picon_dlmm_quote_bg.wasm +0 -0
  36. 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 the pool was
71
- // fetched a while ago (or opened before other activity could've moved the price), refresh it
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.data.feeStates[i].feeOwedX`/`feeOwedY` is the fee already swept into the position (materialized by the last deposit/withdraw/claim_fee call), not the full claimable amount fees earned since then aren't reflected until the next such call. `position.getPendingFee()` computes that remaining delta from the same cached position + bin array data (no RPC):
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 { amountX: pendingFeeX, amountY: pendingFeeY } = position.getPendingFee();
100
- const owedFeeX = position.data.feeStates.reduce((sum, feeState) => sum + feeState.feeOwedX, 0n);
101
- // owedFeeX + pendingFeeX is the total a claimFee call would sweep right now.
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):
@@ -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":"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"}
1
+ {"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../../src/entities/pool.ts"],"names":[],"mappings":"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"}
@@ -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, { epoch }] = await Promise.all([
105
+ const [maybeBinArrays, { transferFeeX, transferFeeY }] = await Promise.all([
99
106
  generated.fetchAllMaybeBinArray(this.#rpc, binArrayAddresses),
100
- this.#rpc.getEpochInfo().send(),
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,
@@ -2,21 +2,21 @@ import { createSolanaRpc, type Address, type Account, type Instruction, type Tra
2
2
  import { generated } from "..";
3
3
  import { type BinIdRange } from "../utils/bin_location";
4
4
  import { Pool } from "./pool";
5
- import { type ProgramConfig } from "./types";
5
+ import { BinArray } from "./bin_array";
6
+ import { type PositionInfo, type ProgramConfig, type PositionBinInfo } from "./types";
6
7
  export declare class Position {
7
8
  #private;
8
9
  private constructor();
9
10
  get address(): Address<string>;
10
11
  get data(): generated.Position;
11
12
  get positionMint(): Address;
13
+ get binArrays(): readonly BinArray[];
12
14
  get binArrayAddresses(): {
13
15
  lowerBinArray: Address;
14
16
  upperBinArray?: Address | undefined;
15
17
  };
16
- getPendingFee(): {
17
- amountX: bigint;
18
- amountY: bigint;
19
- };
18
+ getBinInfos(): PositionBinInfo[];
19
+ getInfo(): Promise<PositionInfo>;
20
20
  refresh(data: [Account<generated.Position>, Account<generated.BinArray>[]]): Promise<void>;
21
21
  refresh(config?: FetchAccountsConfig): Promise<void>;
22
22
  depositByWeight(owner: TransactionSigner, { amountX, amountY, lowerBinId, binWeights, maxActiveBinSlippage, distributionMode, }: {
@@ -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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"}
@@ -1,5 +1,6 @@
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";
@@ -20,30 +21,74 @@ export class Position {
20
21
  get address() { return this.#account.address; }
21
22
  get data() { return this.#account.data; }
22
23
  get positionMint() { return this.data.positionMint; }
24
+ get binArrays() { return this.#binArrays; }
23
25
  get binArrayAddresses() {
24
26
  const lowerBinArray = this.#binArrays[0].address;
25
27
  const upperBinArray = this.#binArrays.length > 1 ? this.#binArrays[1].address : undefined;
26
28
  return { lowerBinArray, upperBinArray };
27
29
  }
28
- getPendingFee() {
30
+ getBinInfos() {
29
31
  const { lowerBinId, upperBinId, feeStates } = this.data;
30
32
  const lowerBinArrayIndex = getBinArrayIndex(lowerBinId);
31
- return Array.from({ length: upperBinId - lowerBinId + 1 }, (_, i) => i)
32
- .flatMap(i => {
33
- const feeState = feeStates[i];
34
- if (feeState.shares === 0n)
35
- return [];
33
+ const binCount = upperBinId - lowerBinId + 1;
34
+ return feeStates
35
+ .slice(0, binCount)
36
+ .map((feeState, i) => {
36
37
  const binId = lowerBinId + i;
37
38
  const binIndex = getBinIndex(binId);
38
- const binArrayIndex = getBinArrayIndex(binId) - lowerBinArrayIndex;
39
- const binArray = this.#binArrays[binArrayIndex];
39
+ const localBinArrayIndex = getBinArrayIndex(binId) - lowerBinArrayIndex;
40
+ const binArray = this.#binArrays[localBinArrayIndex];
40
41
  const bin = binArray.bins[binIndex];
41
- return bin.totalShares > 0n ? [{ feeState, bin }] : [];
42
- })
43
- .reduce((total, { feeState, bin }) => ({
44
- amountX: total.amountX + earnedAmount(bin.feePerShareX, feeState.feePerShareCheckpointX, feeState.shares),
45
- amountY: total.amountY + earnedAmount(bin.feePerShareY, feeState.feePerShareCheckpointY, feeState.shares),
46
- }), { amountX: 0n, amountY: 0n });
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
+ };
47
92
  }
48
93
  async refresh(arg) {
49
94
  if (!Array.isArray(arg)) {
@@ -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 { QuoteInput, QuoteOutput, PoolState, TransferFee } from "./quote";
7
+ export type { QuoteOutput, TransferFee } 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,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC/E,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,MAAM,SAAS,CAAC;AACxD,cAAc,qBAAqB,CAAC"}
@@ -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"}
@@ -3,3 +3,7 @@ export async function quote(input) {
3
3
  const wasm = await loadWasm();
4
4
  return wasm.quote(input);
5
5
  }
6
+ export async function applyTransferFee(amount, fee) {
7
+ const wasm = await loadWasm();
8
+ return wasm.applyTransferFee(amount, fee);
9
+ }
@@ -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}
@@ -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}
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@picon-finance/dlmm-sdk",
3
- "version": "1.5.0",
3
+ "version": "1.7.0",
4
4
  "description": "Typescript SDK for interacting with the Picon DLMM protocol",
5
5
  "author": "Picon Finance",
6
6
  "license": "MIT",
@@ -14,7 +14,11 @@ import {
14
14
  } from "@solana-program/token-2022";
15
15
 
16
16
  import { generated } from "..";
17
- import { quote, type QuoteOutput } from "../quote";
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, { epoch }] = await Promise.all([
226
+ const [maybeBinArrays, { transferFeeX, transferFeeY }] = await Promise.all([
215
227
  generated.fetchAllMaybeBinArray(this.#rpc, binArrayAddresses),
216
- this.#rpc.getEpochInfo().send(),
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,
@@ -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,
@@ -38,7 +39,11 @@ import {
38
39
  createAllBinArrays,
39
40
  fetchAllBinArraysChunked,
40
41
  } from "./bin_array";
41
- import { type ProgramConfig } from "./types";
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;
@@ -58,6 +63,7 @@ export class Position {
58
63
  public get address() { return this.#account.address; }
59
64
  public get data() { return this.#account.data; }
60
65
  public get positionMint() { return this.data.positionMint; }
66
+ public get binArrays(): readonly BinArray[] { return this.#binArrays; }
61
67
 
62
68
  public get binArrayAddresses(): { lowerBinArray: Address, upperBinArray?: Address | undefined } {
63
69
  const lowerBinArray = this.#binArrays[0].address;
@@ -65,29 +71,75 @@ export class Position {
65
71
  return { lowerBinArray, upperBinArray };
66
72
  }
67
73
 
68
- public getPendingFee(): { amountX: bigint, amountY: bigint } {
74
+ public getBinInfos(): PositionBinInfo[] {
69
75
  const { lowerBinId, upperBinId, feeStates } = this.data;
70
76
  const lowerBinArrayIndex = getBinArrayIndex(lowerBinId);
77
+ const binCount = upperBinId - lowerBinId + 1;
71
78
 
72
- return Array.from({ length: upperBinId - lowerBinId + 1 }, (_, i) => i)
73
- .flatMap(i => {
74
- const feeState = feeStates[i]!;
75
- if (feeState.shares === 0n) return [];
76
-
79
+ return feeStates
80
+ .slice(0, binCount)
81
+ .map((feeState, i) => {
77
82
  const binId = lowerBinId + i;
78
-
79
83
  const binIndex = getBinIndex(binId);
80
- const binArrayIndex = getBinArrayIndex(binId) - lowerBinArrayIndex;
81
-
82
- const binArray = this.#binArrays[binArrayIndex];
84
+ const localBinArrayIndex = getBinArrayIndex(binId) - lowerBinArrayIndex;
85
+ const binArray = this.#binArrays[localBinArrayIndex];
83
86
  const bin = binArray.bins[binIndex];
84
87
 
85
- return bin.totalShares > 0n ? [{ feeState, bin }] : [];
86
- })
87
- .reduce((total, { feeState, bin }) => ({
88
- amountX: total.amountX + earnedAmount(bin.feePerShareX, feeState.feePerShareCheckpointX, feeState.shares),
89
- amountY: total.amountY + earnedAmount(bin.feePerShareY, feeState.feePerShareCheckpointY, feeState.shares),
90
- }), { amountX: 0n, amountY: 0n });
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
+ };
91
143
  }
92
144
 
93
145
  public async refresh(data: [Account<generated.Position>, Account<generated.BinArray>[]]): Promise<void>;
@@ -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 { QuoteInput, QuoteOutput, PoolState, TransferFee } from "./quote";
7
+ export type { QuoteOutput, TransferFee } from "./quote";
8
8
  export * from "./program_addresses";
@@ -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}
@@ -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}
@@ -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;