@picon-finance/dlmm-sdk 1.16.4 → 1.17.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 +1 -1
- package/dist/entities/pool.d.ts.map +1 -1
- package/dist/entities/pool.js +10 -27
- package/dist/entities/position.d.ts +7 -2
- package/dist/entities/position.d.ts.map +1 -1
- package/dist/entities/position.js +25 -71
- package/dist/utils/ata.d.ts +0 -10
- package/dist/utils/ata.d.ts.map +1 -1
- package/dist/utils/ata.js +0 -9
- package/dist/utils/transfer_hook.d.ts +12 -0
- package/dist/utils/transfer_hook.d.ts.map +1 -1
- package/dist/utils/transfer_hook.js +25 -0
- package/package.json +4 -4
- package/src/entities/pool.ts +11 -30
- package/src/entities/position.ts +38 -84
- package/src/utils/ata.ts +0 -22
- package/src/utils/transfer_hook.ts +37 -0
package/README.md
CHANGED
|
@@ -98,7 +98,7 @@ const depositIxs = await position.depositByWeight(ownerSigner, {
|
|
|
98
98
|
|
|
99
99
|
// Later: claim fees, withdraw (partially or fully, by bps), close.
|
|
100
100
|
const claimFeeIxs = await position.claimFee(ownerSigner);
|
|
101
|
-
const withdrawIxs = await position.withdraw(ownerSigner, 5_000); // bps, out of 10_000 = 100%
|
|
101
|
+
const withdrawIxs = await position.withdraw(ownerSigner, { bpsToRemove: 5_000 }); // bps, out of 10_000 = 100%
|
|
102
102
|
const closeIx = await position.close(ownerSigner);
|
|
103
103
|
```
|
|
104
104
|
|
|
@@ -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,EAIL,KAAK,QAAQ,EACb,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EACjB,MAAM,UAAU,CAAC;AAWlB,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
|
@@ -7,7 +7,7 @@ import { resolveAdminConfigAddress } from "./admin_config";
|
|
|
7
7
|
import { processAssociatedTokenAccountPair } from "../utils/ata";
|
|
8
8
|
import { getBinArrayIndex, getBinArrayIndexSequence, generateBinArrayIndicesForSwap, generateBinArrayIndicesForSync, } from "../utils/bin_location";
|
|
9
9
|
import { resolveTransferFee } from "../utils/transfer_fee";
|
|
10
|
-
import { resolveTransferHookProgram, resolveTransferHookExtraAccounts,
|
|
10
|
+
import { appendRemainingAccounts, buildTransferHookScheme, resolveTransferHookProgram, resolveTransferHookExtraAccounts, } from "../utils/transfer_hook";
|
|
11
11
|
import { MAX_BIN_ARRAYS_PER_TRAVERSAL } from "../utils/constants";
|
|
12
12
|
import { Position, openPosition, closePosition, findPositionAddress, findAllPositionAddresses, } from "./position";
|
|
13
13
|
import { BinArray, findAllBinArrayAddresses } from "./bin_array";
|
|
@@ -147,25 +147,21 @@ export class Pool {
|
|
|
147
147
|
this.resolveTransferHookAccountsX(xTransferAccounts),
|
|
148
148
|
this.resolveTransferHookAccountsY(yTransferAccounts),
|
|
149
149
|
]);
|
|
150
|
+
const hookScheme = buildTransferHookScheme(transferHookXAccounts, transferHookYAccounts);
|
|
150
151
|
const groups = [
|
|
151
152
|
{ kind: generated.AccountKind.BinArray, count: binArrayAddresses.length },
|
|
153
|
+
...hookScheme.groups,
|
|
154
|
+
];
|
|
155
|
+
const remainingAccounts = [
|
|
156
|
+
...binArrayAddresses.map(address => ({ address, role: AccountRole.WRITABLE })),
|
|
157
|
+
...hookScheme.remainingAccounts,
|
|
152
158
|
];
|
|
153
|
-
const remainingAccounts = binArrayAddresses.map(address => ({ address, role: AccountRole.WRITABLE }));
|
|
154
|
-
if (transferHookXAccounts.length > 0) {
|
|
155
|
-
groups.push({ kind: generated.AccountKind.TransferHookX, count: transferHookXAccounts.length });
|
|
156
|
-
remainingAccounts.push(...transferHookXAccounts.map(toRemainingAccountMeta));
|
|
157
|
-
}
|
|
158
|
-
if (transferHookYAccounts.length > 0) {
|
|
159
|
-
groups.push({ kind: generated.AccountKind.TransferHookY, count: transferHookYAccounts.length });
|
|
160
|
-
remainingAccounts.push(...transferHookYAccounts.map(toRemainingAccountMeta));
|
|
161
|
-
}
|
|
162
159
|
const swapIx = buildSwapIx({
|
|
163
160
|
tokenUserAccountX,
|
|
164
161
|
tokenUserAccountY,
|
|
165
162
|
remainingAccountsScheme: { groups },
|
|
166
163
|
});
|
|
167
|
-
|
|
168
|
-
return [...preInstructions, swapIxWithBinArrays, ...postInstructions];
|
|
164
|
+
return [...preInstructions, appendRemainingAccounts(swapIx, remainingAccounts), ...postInstructions];
|
|
169
165
|
}
|
|
170
166
|
// Public so Position (which only holds a reference to this Pool, not its private mint data)
|
|
171
167
|
// can resolve hook accounts for its own deposit/withdraw/claimFee instructions without ever
|
|
@@ -283,16 +279,7 @@ export class Pool {
|
|
|
283
279
|
source: this.tokenVaultY, mint: this.tokenMintY, destination: tokenAdminAccountY, owner: this.address,
|
|
284
280
|
}),
|
|
285
281
|
]);
|
|
286
|
-
const groups =
|
|
287
|
-
const remainingAccounts = [];
|
|
288
|
-
if (transferHookXAccounts.length > 0) {
|
|
289
|
-
groups.push({ kind: generated.AccountKind.TransferHookX, count: transferHookXAccounts.length });
|
|
290
|
-
remainingAccounts.push(...transferHookXAccounts.map(toRemainingAccountMeta));
|
|
291
|
-
}
|
|
292
|
-
if (transferHookYAccounts.length > 0) {
|
|
293
|
-
groups.push({ kind: generated.AccountKind.TransferHookY, count: transferHookYAccounts.length });
|
|
294
|
-
remainingAccounts.push(...transferHookYAccounts.map(toRemainingAccountMeta));
|
|
295
|
-
}
|
|
282
|
+
const { groups, remainingAccounts } = buildTransferHookScheme(transferHookXAccounts, transferHookYAccounts);
|
|
296
283
|
const claimProtocolFeeIx = await generated.getClaimProtocolFeeInstructionAsync({
|
|
297
284
|
authority,
|
|
298
285
|
pool: this.address,
|
|
@@ -307,11 +294,7 @@ export class Pool {
|
|
|
307
294
|
tokenProgramX: this.tokenProgramX,
|
|
308
295
|
tokenProgramY: this.tokenProgramY,
|
|
309
296
|
}, { programAddress: this.#programAddress });
|
|
310
|
-
|
|
311
|
-
...claimProtocolFeeIx,
|
|
312
|
-
accounts: [...claimProtocolFeeIx.accounts, ...remainingAccounts],
|
|
313
|
-
};
|
|
314
|
-
return [...preInstructions, claimProtocolFeeIxWithHookAccounts, ...postInstructions];
|
|
297
|
+
return [...preInstructions, appendRemainingAccounts(claimProtocolFeeIx, remainingAccounts), ...postInstructions];
|
|
315
298
|
}
|
|
316
299
|
static async load(rpc, address, programAddress, config) {
|
|
317
300
|
const pool = await generated.fetchPool(rpc, address, config);
|
|
@@ -27,8 +27,13 @@ export declare class Position {
|
|
|
27
27
|
maxActiveBinSlippage: number;
|
|
28
28
|
distributionMode: generated.DistributionMode;
|
|
29
29
|
}): Promise<Instruction[]>;
|
|
30
|
-
claimFee(owner: TransactionSigner, range?:
|
|
31
|
-
|
|
30
|
+
claimFee(owner: TransactionSigner, { range }?: {
|
|
31
|
+
range?: BinIdRange;
|
|
32
|
+
}): Promise<Instruction[]>;
|
|
33
|
+
withdraw(owner: TransactionSigner, { bpsToRemove, range }: {
|
|
34
|
+
bpsToRemove: number;
|
|
35
|
+
range?: BinIdRange;
|
|
36
|
+
}): Promise<Instruction[]>;
|
|
32
37
|
close(owner: TransactionSigner): Promise<Instruction>;
|
|
33
38
|
static load(pool: Pool, address: Address, config?: FetchAccountsConfig): Promise<Position>;
|
|
34
39
|
static loadAll(pool: Pool, addresses: Address[], config?: FetchAccountsConfig): Promise<Position[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"position.d.ts","sourceRoot":"","sources":["../../src/entities/position.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,eAAe,
|
|
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;AAU/B,OAAO,EAIL,KAAK,UAAU,EAChB,MAAM,uBAAuB,CAAC;AAgB/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;IAqCrD,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,CAoDzB;IAkDY,QAAQ,CACnB,KAAK,EAAE,iBAAiB,EACxB,EAAE,KAAK,EAAE,GAAE;QAAE,KAAK,CAAC,EAAE,UAAU,CAAA;KAAO,GACrC,OAAO,CAAC,WAAW,EAAE,CAAC,CAaxB;IAEY,QAAQ,CACnB,KAAK,EAAE,iBAAiB,EACxB,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,UAAU,CAAA;KAAE,GAClE,OAAO,CAAC,WAAW,EAAE,CAAC,CAgDxB;IAEY,KAAK,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAKjE;IAED,OAAoB,IAAI,CACtB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,EAChB,MAAM,CAAC,EAAE,mBAAmB,GAC3B,OAAO,CAAC,QAAQ,CAAC,CAkBnB;IAED,OAAoB,OAAO,CACzB,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,OAAO,EAAE,EACpB,MAAM,CAAC,EAAE,mBAAmB,GAC3B,OAAO,CAAC,QAAQ,EAAE,CAAC,CAkBrB;IAED,OAAoB,UAAU,CAC5B,GAAG,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,EACvC,SAAS,EAAE,QAAQ,EAAE,EACrB,MAAM,CAAC,EAAE,mBAAmB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAiBf;IAED,OAAoB,YAAY,CAC9B,KAAK,EAAE,iBAAiB,EACxB,SAAS,EAAE,QAAQ,EAAE,EACrB,iBAAiB,GAAE,MAAoC,GACtD,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAqC1B;CACF;AAED,wBAAsB,mBAAmB,CACvC,KAAK,EAAE;IAAE,YAAY,EAAE,OAAO,CAAA;CAAE,EAChC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,OAAO,CAAC,CAGlB;AAED,wBAAsB,wBAAwB,CAC5C,EAAE,aAAa,EAAE,EAAE;IAAE,aAAa,EAAE,OAAO,EAAE,CAAA;CAAE,EAC/C,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,OAAO,EAAE,CAAC,CAIpB;AAED,wBAAsB,YAAY,CAChC,GAAG,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,EACvC,EACE,KAAK,EACL,YAAY,EACZ,IAAI,EACJ,UAAU,EACV,UAAU,GACX,EAAE;IACD,KAAK,EAAE,iBAAiB,CAAC;IACzB,YAAY,EAAE,iBAAiB,CAAC;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB,EACD,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,WAAW,EAAE,CAAC,CAyBxB;AAED,wBAAsB,aAAa,CACjC,EACE,KAAK,EACL,YAAY,EACZ,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,iBAAiB,CAAC;IACzB,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,EACD,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,WAAW,CAAC,CAWtB"}
|
|
@@ -2,7 +2,7 @@ import { decodeAccount, assertAccountExists, fetchEncodedAccounts, } from "@sola
|
|
|
2
2
|
import { generated } from "..";
|
|
3
3
|
import { getAmountAfterTransferFee } from "../quote";
|
|
4
4
|
import { findPositionTokenAccount, processAssociatedTokenAccountPair, } from "../utils/ata";
|
|
5
|
-
import {
|
|
5
|
+
import { appendRemainingAccounts, buildTransferHookScheme, } from "../utils/transfer_hook";
|
|
6
6
|
import { getBinIndex, getBinArrayIndex, getPositionBinArrayIndices, } from "../utils/bin_location";
|
|
7
7
|
import { assertRangeWithinRange, assertPositionBelongsToPool, } from "../utils/assert";
|
|
8
8
|
import { isUndefined } from "../utils/type_guards";
|
|
@@ -97,12 +97,14 @@ export class Position {
|
|
|
97
97
|
}
|
|
98
98
|
const [position, binArrays] = arg;
|
|
99
99
|
this.#account = position;
|
|
100
|
-
this.#binArrays.
|
|
100
|
+
await Promise.all(this.#binArrays.map((b, i) => b.refresh(binArrays[i])));
|
|
101
101
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
102
|
+
// Shared by depositByWeight/claimFee/withdraw — each needs the owner's position-NFT token
|
|
103
|
+
// account plus its X/Y ATAs (creating either that don't exist yet, funding wSOL if native).
|
|
104
|
+
// amounts is only relevant for a deposit (it decides how much wSOL to wrap); omitted for
|
|
105
|
+
// claim/withdraw, which only ever receive tokens.
|
|
106
|
+
async #prepareOwnerAccounts(owner, amounts) {
|
|
107
|
+
return await Promise.all([
|
|
106
108
|
findPositionTokenAccount({ owner: owner.address, positionMint: this.data.positionMint }),
|
|
107
109
|
processAssociatedTokenAccountPair({
|
|
108
110
|
owner,
|
|
@@ -110,10 +112,15 @@ export class Position {
|
|
|
110
112
|
tokenMintY: this.#pool.tokenMintY,
|
|
111
113
|
tokenProgramX: this.#pool.tokenProgramX,
|
|
112
114
|
tokenProgramY: this.#pool.tokenProgramY,
|
|
113
|
-
amountX,
|
|
114
|
-
amountY,
|
|
115
|
+
amountX: amounts?.amountX,
|
|
116
|
+
amountY: amounts?.amountY,
|
|
115
117
|
}),
|
|
116
118
|
]);
|
|
119
|
+
}
|
|
120
|
+
async depositByWeight(owner, { amountX, amountY, lowerBinId, binWeights, maxActiveBinSlippage, distributionMode, }) {
|
|
121
|
+
const upperBinId = lowerBinId + binWeights.length - 1;
|
|
122
|
+
assertRangeWithinRange({ lowerBinId, upperBinId }, this.data);
|
|
123
|
+
const [positionTokenAccount, { ataX: tokenOwnerAccountX, ataY: tokenOwnerAccountY, preInstructions, postInstructions }] = await this.#prepareOwnerAccounts(owner, { amountX, amountY });
|
|
117
124
|
// Both legs move owner -> vault (deposit), signed by owner itself.
|
|
118
125
|
const [transferHookXAccounts, transferHookYAccounts] = await Promise.all([
|
|
119
126
|
this.#pool.resolveTransferHookAccountsX({
|
|
@@ -123,16 +130,7 @@ export class Position {
|
|
|
123
130
|
source: tokenOwnerAccountY, mint: this.#pool.tokenMintY, destination: this.#pool.tokenVaultY, owner: owner.address,
|
|
124
131
|
}),
|
|
125
132
|
]);
|
|
126
|
-
const groups =
|
|
127
|
-
const remainingAccounts = [];
|
|
128
|
-
if (transferHookXAccounts.length > 0) {
|
|
129
|
-
groups.push({ kind: generated.AccountKind.TransferHookX, count: transferHookXAccounts.length });
|
|
130
|
-
remainingAccounts.push(...transferHookXAccounts.map(toRemainingAccountMeta));
|
|
131
|
-
}
|
|
132
|
-
if (transferHookYAccounts.length > 0) {
|
|
133
|
-
groups.push({ kind: generated.AccountKind.TransferHookY, count: transferHookYAccounts.length });
|
|
134
|
-
remainingAccounts.push(...transferHookYAccounts.map(toRemainingAccountMeta));
|
|
135
|
-
}
|
|
133
|
+
const { groups, remainingAccounts } = buildTransferHookScheme(transferHookXAccounts, transferHookYAccounts);
|
|
136
134
|
const { lowerBinArray, upperBinArray } = this.binArrayAddresses;
|
|
137
135
|
const depositByWeightIx = generated.getDepositByWeightInstruction({
|
|
138
136
|
owner,
|
|
@@ -160,11 +158,7 @@ export class Position {
|
|
|
160
158
|
}, {
|
|
161
159
|
programAddress: this.#pool.programAddress
|
|
162
160
|
});
|
|
163
|
-
|
|
164
|
-
...depositByWeightIx,
|
|
165
|
-
accounts: [...depositByWeightIx.accounts, ...remainingAccounts],
|
|
166
|
-
};
|
|
167
|
-
return [...preInstructions, depositByWeightIxWithHookAccounts, ...postInstructions];
|
|
161
|
+
return [...preInstructions, appendRemainingAccounts(depositByWeightIx, remainingAccounts), ...postInstructions];
|
|
168
162
|
}
|
|
169
163
|
async #buildClaimFeeInstruction(owner, positionTokenAccount, tokenOwnerAccountX, tokenOwnerAccountY, range) {
|
|
170
164
|
const { lowerBinId, upperBinId } = range ?? this.data;
|
|
@@ -178,16 +172,7 @@ export class Position {
|
|
|
178
172
|
source: this.#pool.tokenVaultY, mint: this.#pool.tokenMintY, destination: tokenOwnerAccountY, owner: this.#pool.address,
|
|
179
173
|
}),
|
|
180
174
|
]);
|
|
181
|
-
const groups =
|
|
182
|
-
const remainingAccounts = [];
|
|
183
|
-
if (transferHookXAccounts.length > 0) {
|
|
184
|
-
groups.push({ kind: generated.AccountKind.TransferHookX, count: transferHookXAccounts.length });
|
|
185
|
-
remainingAccounts.push(...transferHookXAccounts.map(toRemainingAccountMeta));
|
|
186
|
-
}
|
|
187
|
-
if (transferHookYAccounts.length > 0) {
|
|
188
|
-
groups.push({ kind: generated.AccountKind.TransferHookY, count: transferHookYAccounts.length });
|
|
189
|
-
remainingAccounts.push(...transferHookYAccounts.map(toRemainingAccountMeta));
|
|
190
|
-
}
|
|
175
|
+
const { groups, remainingAccounts } = buildTransferHookScheme(transferHookXAccounts, transferHookYAccounts);
|
|
191
176
|
const { lowerBinArray, upperBinArray } = this.binArrayAddresses;
|
|
192
177
|
const claimFeeIx = generated.getClaimFeeInstruction({
|
|
193
178
|
owner,
|
|
@@ -210,35 +195,17 @@ export class Position {
|
|
|
210
195
|
}, {
|
|
211
196
|
programAddress: this.#pool.programAddress
|
|
212
197
|
});
|
|
213
|
-
return
|
|
198
|
+
return appendRemainingAccounts(claimFeeIx, remainingAccounts);
|
|
214
199
|
}
|
|
215
|
-
async claimFee(owner, range) {
|
|
216
|
-
const [positionTokenAccount, { ataX: tokenOwnerAccountX, ataY: tokenOwnerAccountY, preInstructions, postInstructions }] = await
|
|
217
|
-
findPositionTokenAccount({ owner: owner.address, positionMint: this.data.positionMint }),
|
|
218
|
-
processAssociatedTokenAccountPair({
|
|
219
|
-
owner,
|
|
220
|
-
tokenMintX: this.#pool.tokenMintX,
|
|
221
|
-
tokenMintY: this.#pool.tokenMintY,
|
|
222
|
-
tokenProgramX: this.#pool.tokenProgramX,
|
|
223
|
-
tokenProgramY: this.#pool.tokenProgramY,
|
|
224
|
-
}),
|
|
225
|
-
]);
|
|
200
|
+
async claimFee(owner, { range } = {}) {
|
|
201
|
+
const [positionTokenAccount, { ataX: tokenOwnerAccountX, ataY: tokenOwnerAccountY, preInstructions, postInstructions }] = await this.#prepareOwnerAccounts(owner);
|
|
226
202
|
const claimFeeIx = await this.#buildClaimFeeInstruction(owner, positionTokenAccount, tokenOwnerAccountX, tokenOwnerAccountY, range);
|
|
227
203
|
return [...preInstructions, claimFeeIx, ...postInstructions];
|
|
228
204
|
}
|
|
229
|
-
async withdraw(owner, bpsToRemove, range) {
|
|
205
|
+
async withdraw(owner, { bpsToRemove, range }) {
|
|
230
206
|
const { lowerBinId, upperBinId } = range ?? this.data;
|
|
231
207
|
assertRangeWithinRange({ lowerBinId, upperBinId }, this.data);
|
|
232
|
-
const [positionTokenAccount, { ataX: tokenOwnerAccountX, ataY: tokenOwnerAccountY, preInstructions, postInstructions }] = await
|
|
233
|
-
findPositionTokenAccount({ owner: owner.address, positionMint: this.data.positionMint }),
|
|
234
|
-
processAssociatedTokenAccountPair({
|
|
235
|
-
owner,
|
|
236
|
-
tokenMintX: this.#pool.tokenMintX,
|
|
237
|
-
tokenMintY: this.#pool.tokenMintY,
|
|
238
|
-
tokenProgramX: this.#pool.tokenProgramX,
|
|
239
|
-
tokenProgramY: this.#pool.tokenProgramY,
|
|
240
|
-
}),
|
|
241
|
-
]);
|
|
208
|
+
const [positionTokenAccount, { ataX: tokenOwnerAccountX, ataY: tokenOwnerAccountY, preInstructions, postInstructions }] = await this.#prepareOwnerAccounts(owner);
|
|
242
209
|
// Both legs move vault -> owner (withdraw), signed by the pool PDA.
|
|
243
210
|
const [transferHookXAccounts, transferHookYAccounts] = await Promise.all([
|
|
244
211
|
this.#pool.resolveTransferHookAccountsX({
|
|
@@ -248,16 +215,7 @@ export class Position {
|
|
|
248
215
|
source: this.#pool.tokenVaultY, mint: this.#pool.tokenMintY, destination: tokenOwnerAccountY, owner: this.#pool.address,
|
|
249
216
|
}),
|
|
250
217
|
]);
|
|
251
|
-
const groups =
|
|
252
|
-
const remainingAccounts = [];
|
|
253
|
-
if (transferHookXAccounts.length > 0) {
|
|
254
|
-
groups.push({ kind: generated.AccountKind.TransferHookX, count: transferHookXAccounts.length });
|
|
255
|
-
remainingAccounts.push(...transferHookXAccounts.map(toRemainingAccountMeta));
|
|
256
|
-
}
|
|
257
|
-
if (transferHookYAccounts.length > 0) {
|
|
258
|
-
groups.push({ kind: generated.AccountKind.TransferHookY, count: transferHookYAccounts.length });
|
|
259
|
-
remainingAccounts.push(...transferHookYAccounts.map(toRemainingAccountMeta));
|
|
260
|
-
}
|
|
218
|
+
const { groups, remainingAccounts } = buildTransferHookScheme(transferHookXAccounts, transferHookYAccounts);
|
|
261
219
|
const { lowerBinArray, upperBinArray } = this.binArrayAddresses;
|
|
262
220
|
const withdrawIx = generated.getWithdrawInstruction({
|
|
263
221
|
owner,
|
|
@@ -281,11 +239,7 @@ export class Position {
|
|
|
281
239
|
}, {
|
|
282
240
|
programAddress: this.#pool.programAddress
|
|
283
241
|
});
|
|
284
|
-
|
|
285
|
-
...withdrawIx,
|
|
286
|
-
accounts: [...withdrawIx.accounts, ...remainingAccounts],
|
|
287
|
-
};
|
|
288
|
-
return [...preInstructions, withdrawIxWithHookAccounts, ...postInstructions];
|
|
242
|
+
return [...preInstructions, appendRemainingAccounts(withdrawIx, remainingAccounts), ...postInstructions];
|
|
289
243
|
}
|
|
290
244
|
async close(owner) {
|
|
291
245
|
return await closePosition({ owner, positionMint: this.data.positionMint, position: this.address }, { programAddress: this.#pool.programAddress });
|
package/dist/utils/ata.d.ts
CHANGED
|
@@ -9,16 +9,6 @@ export declare function findPositionTokenAccount({ owner, positionMint, }: {
|
|
|
9
9
|
owner: Address;
|
|
10
10
|
positionMint: Address;
|
|
11
11
|
}): Promise<Address>;
|
|
12
|
-
export declare function findPoolTokenVaults({ pool, tokenMintX, tokenMintY, tokenProgramX, tokenProgramY, }: {
|
|
13
|
-
pool: Address;
|
|
14
|
-
tokenMintX: Address;
|
|
15
|
-
tokenMintY: Address;
|
|
16
|
-
tokenProgramX: Address;
|
|
17
|
-
tokenProgramY: Address;
|
|
18
|
-
}): Promise<{
|
|
19
|
-
tokenVaultX: Address;
|
|
20
|
-
tokenVaultY: Address;
|
|
21
|
-
}>;
|
|
22
12
|
interface ProcessAssociatedTokenAccountParams {
|
|
23
13
|
owner: TransactionSigner;
|
|
24
14
|
mint: Address;
|
package/dist/utils/ata.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ata.d.ts","sourceRoot":"","sources":["../../src/utils/ata.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACvB,MAAM,aAAa,CAAC;AAerB,eAAO,MAAM,mBAAmB,EAAoD,OAAO,CAAC;AAE5F,wBAAsB,oCAAoC,CAAC,MAAM,EAAE;IACjE,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,OAAO,CAAC;CACvB,4BAIA;AAID,wBAAgB,wBAAwB,CAAC,EACvC,KAAK,EACL,YAAY,GACb,EAAE;IACD,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,OAAO,CAAC;CACvB,GAAG,OAAO,CAAC,OAAO,CAAC,CAEnB;
|
|
1
|
+
{"version":3,"file":"ata.d.ts","sourceRoot":"","sources":["../../src/utils/ata.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACvB,MAAM,aAAa,CAAC;AAerB,eAAO,MAAM,mBAAmB,EAAoD,OAAO,CAAC;AAE5F,wBAAsB,oCAAoC,CAAC,MAAM,EAAE;IACjE,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,OAAO,CAAC;CACvB,4BAIA;AAID,wBAAgB,wBAAwB,CAAC,EACvC,KAAK,EACL,YAAY,GACb,EAAE;IACD,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,OAAO,CAAC;CACvB,GAAG,OAAO,CAAC,OAAO,CAAC,CAEnB;AAED,UAAU,mCAAmC;IAC3C,KAAK,EAAE,iBAAiB,CAAC;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,UAAU,mCAAmC;IAC3C,GAAG,EAAE,OAAO,CAAC;IACb,eAAe,EAAE,WAAW,EAAE,CAAC;IAC/B,gBAAgB,EAAE,WAAW,EAAE,CAAC;CACjC;AAED,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,mCAAmC,GAAG,OAAO,CAAC,mCAAmC,CAAC,CAMvI;AAKD,wBAAsB,iCAAiC,CAAC,EACtD,KAAK,EACL,UAAU,EACV,UAAU,EACV,aAAa,EACb,aAAa,EACb,OAAO,EACP,OAAO,GACR,EAAE;IACD,KAAK,EAAE,iBAAiB,CAAC;IACzB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC;IACV,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,eAAe,EAAE,WAAW,EAAE,CAAC;IAC/B,gBAAgB,EAAE,WAAW,EAAE,CAAC;CACjC,CAAC,CAWD"}
|
package/dist/utils/ata.js
CHANGED
|
@@ -12,15 +12,6 @@ export async function findAssociatedTokenPdaByTokenProgram(params) {
|
|
|
12
12
|
export function findPositionTokenAccount({ owner, positionMint, }) {
|
|
13
13
|
return findAssociatedTokenPdaByTokenProgram({ owner, mint: positionMint, tokenProgram: TOKEN_2022_PROGRAM_ADDRESS });
|
|
14
14
|
}
|
|
15
|
-
// A pool's X/Y vaults — shared by every instruction that moves tokens through a pool
|
|
16
|
-
// (withdraw, claim_fee, claim_multiple_fees, claim_protocol_fee, deposit_by_weight, swap).
|
|
17
|
-
export async function findPoolTokenVaults({ pool, tokenMintX, tokenMintY, tokenProgramX, tokenProgramY, }) {
|
|
18
|
-
const [tokenVaultX, tokenVaultY] = await Promise.all([
|
|
19
|
-
findAssociatedTokenPdaByTokenProgram({ owner: pool, mint: tokenMintX, tokenProgram: tokenProgramX }),
|
|
20
|
-
findAssociatedTokenPdaByTokenProgram({ owner: pool, mint: tokenMintY, tokenProgram: tokenProgramY }),
|
|
21
|
-
]);
|
|
22
|
-
return { tokenVaultX, tokenVaultY };
|
|
23
|
-
}
|
|
24
15
|
export function processAssociatedTokenAccount(params) {
|
|
25
16
|
if (params.mint === NATIVE_MINT_ADDRESS) {
|
|
26
17
|
return processWsolAssociatedTokenAccount(params);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AccountRole, createSolanaRpc, type Address } from "@solana/kit";
|
|
2
2
|
import type { Mint } from "@solana-program/token-2022";
|
|
3
|
+
import * as generated from "../generated";
|
|
3
4
|
export declare function resolveTransferHookProgram(mint: Mint): Address | undefined;
|
|
4
5
|
export declare function getExtraAccountMetaListAddress(mint: Address, hookProgram: Address): Promise<Address>;
|
|
5
6
|
export type ExtraAccount = {
|
|
@@ -18,4 +19,15 @@ export declare function toRemainingAccountMeta({ address, isSigner, isWritable }
|
|
|
18
19
|
address: Address;
|
|
19
20
|
role: AccountRole;
|
|
20
21
|
};
|
|
22
|
+
export type RemainingAccountMeta = {
|
|
23
|
+
address: Address;
|
|
24
|
+
role: AccountRole;
|
|
25
|
+
};
|
|
26
|
+
export declare function buildTransferHookScheme(transferHookXAccounts: ExtraAccount[], transferHookYAccounts: ExtraAccount[]): {
|
|
27
|
+
groups: generated.AccountGroup[];
|
|
28
|
+
remainingAccounts: RemainingAccountMeta[];
|
|
29
|
+
};
|
|
30
|
+
export declare function appendRemainingAccounts<TIx extends {
|
|
31
|
+
accounts?: readonly unknown[];
|
|
32
|
+
}>(instruction: TIx, remainingAccounts: RemainingAccountMeta[]): TIx;
|
|
21
33
|
//# sourceMappingURL=transfer_hook.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transfer_hook.d.ts","sourceRoot":"","sources":["../../src/utils/transfer_hook.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EAIX,eAAe,EAEf,KAAK,OAAO,EACb,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,IAAI,EAAa,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"transfer_hook.d.ts","sourceRoot":"","sources":["../../src/utils/transfer_hook.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EAIX,eAAe,EAEf,KAAK,OAAO,EACb,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,IAAI,EAAa,MAAM,4BAA4B,CAAC;AAClE,OAAO,KAAK,SAAS,MAAM,cAAc,CAAC;AA8B1C,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,GAAG,SAAS,CAQ1E;AAKD,wBAAsB,8BAA8B,CAClD,IAAI,EAAE,OAAO,EACb,WAAW,EAAE,OAAO,GACnB,OAAO,CAAC,OAAO,CAAC,CAQlB;AA4ED,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AA+CF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAWF,wBAAsB,gCAAgC,CACpD,GAAG,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,EACvC,WAAW,EAAE,OAAO,EACpB,gBAAgB,EAAE,gBAAgB,EAClC,eAAe,GAAE,UAA6B,GAC7C,OAAO,CAAC,YAAY,EAAE,CAAC,CAqEzB;AAGD,wBAAgB,sBAAsB,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,YAAY;;;EAKrF;AAED,MAAM,MAAM,oBAAoB,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC;AAO3E,wBAAgB,uBAAuB,CACrC,qBAAqB,EAAE,YAAY,EAAE,EACrC,qBAAqB,EAAE,YAAY,EAAE,GACpC;IAAE,MAAM,EAAE,SAAS,CAAC,YAAY,EAAE,CAAC;IAAC,iBAAiB,EAAE,oBAAoB,EAAE,CAAA;CAAE,CAcjF;AAKD,wBAAgB,uBAAuB,CAAC,GAAG,SAAS;IAAE,QAAQ,CAAC,EAAE,SAAS,OAAO,EAAE,CAAA;CAAE,EACnF,WAAW,EAAE,GAAG,EAChB,iBAAiB,EAAE,oBAAoB,EAAE,GACxC,GAAG,CAEL"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AccountRole, getAddressEncoder, getAddressDecoder, getProgramDerivedAddress, unwrapOption, } from "@solana/kit";
|
|
2
2
|
import { SYSTEM_PROGRAM_ADDRESS } from "@solana-program/system";
|
|
3
|
+
import * as generated from "../generated";
|
|
3
4
|
const EXTRA_ACCOUNT_METAS_SEED = "extra-account-metas";
|
|
4
5
|
// spl-tlv-account-resolution's on-chain byte layout (verified against the actual Rust crate
|
|
5
6
|
// source, spl-tlv-account-resolution 0.4.0's account.rs/state.rs/seeds.rs — not guessed):
|
|
@@ -198,3 +199,27 @@ export function toRemainingAccountMeta({ address, isSigner, isWritable }) {
|
|
|
198
199
|
: (isWritable ? AccountRole.WRITABLE : AccountRole.READONLY);
|
|
199
200
|
return { address, role };
|
|
200
201
|
}
|
|
202
|
+
// Builds the TransferHookX/TransferHookY groups + their remaining-account metas from a resolved
|
|
203
|
+
// pair of hook accounts — one group per side, omitted entirely when that side has no active hook
|
|
204
|
+
// (mirrors the on-chain program's own RemainingAccountsScheme, which only expects a group to be
|
|
205
|
+
// present when the corresponding mint actually carries a hook). Callers that also need a group
|
|
206
|
+
// ahead of these (e.g. swap's BinArray group) prepend their own groups/accounts to the result.
|
|
207
|
+
export function buildTransferHookScheme(transferHookXAccounts, transferHookYAccounts) {
|
|
208
|
+
const groups = [];
|
|
209
|
+
const remainingAccounts = [];
|
|
210
|
+
if (transferHookXAccounts.length > 0) {
|
|
211
|
+
groups.push({ kind: generated.AccountKind.TransferHookX, count: transferHookXAccounts.length });
|
|
212
|
+
remainingAccounts.push(...transferHookXAccounts.map(toRemainingAccountMeta));
|
|
213
|
+
}
|
|
214
|
+
if (transferHookYAccounts.length > 0) {
|
|
215
|
+
groups.push({ kind: generated.AccountKind.TransferHookY, count: transferHookYAccounts.length });
|
|
216
|
+
remainingAccounts.push(...transferHookYAccounts.map(toRemainingAccountMeta));
|
|
217
|
+
}
|
|
218
|
+
return { groups, remainingAccounts };
|
|
219
|
+
}
|
|
220
|
+
// Appends resolved remaining-account metas (transfer hook accounts, bin arrays, ...) onto an
|
|
221
|
+
// already-built instruction — the one-line splice every instruction builder in entities/ needs
|
|
222
|
+
// after computing its own RemainingAccountsScheme.
|
|
223
|
+
export function appendRemainingAccounts(instruction, remainingAccounts) {
|
|
224
|
+
return { ...instruction, accounts: [...(instruction.accounts ?? []), ...remainingAccounts] };
|
|
225
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@picon-finance/dlmm-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.17.0",
|
|
4
4
|
"description": "Typescript SDK for interacting with the Picon DLMM protocol",
|
|
5
5
|
"author": "Picon Finance",
|
|
6
6
|
"license": "MIT",
|
|
@@ -52,8 +52,8 @@
|
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@types/bun": "latest",
|
|
55
|
-
"@codama/nodes-from-anchor": "^1.5.
|
|
56
|
-
"@codama/renderers-js": "^2.3.
|
|
57
|
-
"codama": "^1.
|
|
55
|
+
"@codama/nodes-from-anchor": "^1.5.3",
|
|
56
|
+
"@codama/renderers-js": "^2.3.1",
|
|
57
|
+
"codama": "^1.10.0"
|
|
58
58
|
}
|
|
59
59
|
}
|
package/src/entities/pool.ts
CHANGED
|
@@ -34,9 +34,10 @@ import {
|
|
|
34
34
|
} from "../utils/bin_location";
|
|
35
35
|
import { resolveTransferFee } from "../utils/transfer_fee";
|
|
36
36
|
import {
|
|
37
|
+
appendRemainingAccounts,
|
|
38
|
+
buildTransferHookScheme,
|
|
37
39
|
resolveTransferHookProgram,
|
|
38
40
|
resolveTransferHookExtraAccounts,
|
|
39
|
-
toRemainingAccountMeta,
|
|
40
41
|
type ExtraAccount,
|
|
41
42
|
type TransferAccounts as TransferHookAccounts,
|
|
42
43
|
} from "../utils/transfer_hook";
|
|
@@ -311,28 +312,23 @@ export class Pool {
|
|
|
311
312
|
this.resolveTransferHookAccountsY(yTransferAccounts),
|
|
312
313
|
]);
|
|
313
314
|
|
|
315
|
+
const hookScheme = buildTransferHookScheme(transferHookXAccounts, transferHookYAccounts);
|
|
314
316
|
const groups: generated.AccountGroup[] = [
|
|
315
317
|
{ kind: generated.AccountKind.BinArray, count: binArrayAddresses.length },
|
|
318
|
+
...hookScheme.groups,
|
|
319
|
+
];
|
|
320
|
+
const remainingAccounts = [
|
|
321
|
+
...binArrayAddresses.map(address => ({ address, role: AccountRole.WRITABLE })),
|
|
322
|
+
...hookScheme.remainingAccounts,
|
|
316
323
|
];
|
|
317
|
-
const remainingAccounts = binArrayAddresses.map(address => ({ address, role: AccountRole.WRITABLE }));
|
|
318
|
-
|
|
319
|
-
if (transferHookXAccounts.length > 0) {
|
|
320
|
-
groups.push({ kind: generated.AccountKind.TransferHookX, count: transferHookXAccounts.length });
|
|
321
|
-
remainingAccounts.push(...transferHookXAccounts.map(toRemainingAccountMeta));
|
|
322
|
-
}
|
|
323
|
-
if (transferHookYAccounts.length > 0) {
|
|
324
|
-
groups.push({ kind: generated.AccountKind.TransferHookY, count: transferHookYAccounts.length });
|
|
325
|
-
remainingAccounts.push(...transferHookYAccounts.map(toRemainingAccountMeta));
|
|
326
|
-
}
|
|
327
324
|
|
|
328
325
|
const swapIx = buildSwapIx({
|
|
329
326
|
tokenUserAccountX,
|
|
330
327
|
tokenUserAccountY,
|
|
331
328
|
remainingAccountsScheme: { groups },
|
|
332
329
|
});
|
|
333
|
-
const swapIxWithBinArrays = { ...swapIx, accounts: [...(swapIx.accounts ?? []), ...remainingAccounts] };
|
|
334
330
|
|
|
335
|
-
return [...preInstructions,
|
|
331
|
+
return [...preInstructions, appendRemainingAccounts(swapIx, remainingAccounts), ...postInstructions];
|
|
336
332
|
}
|
|
337
333
|
|
|
338
334
|
// Public so Position (which only holds a reference to this Pool, not its private mint data)
|
|
@@ -548,17 +544,7 @@ export class Pool {
|
|
|
548
544
|
}),
|
|
549
545
|
]);
|
|
550
546
|
|
|
551
|
-
const groups
|
|
552
|
-
const remainingAccounts: { address: Address, role: AccountRole }[] = [];
|
|
553
|
-
|
|
554
|
-
if (transferHookXAccounts.length > 0) {
|
|
555
|
-
groups.push({ kind: generated.AccountKind.TransferHookX, count: transferHookXAccounts.length });
|
|
556
|
-
remainingAccounts.push(...transferHookXAccounts.map(toRemainingAccountMeta));
|
|
557
|
-
}
|
|
558
|
-
if (transferHookYAccounts.length > 0) {
|
|
559
|
-
groups.push({ kind: generated.AccountKind.TransferHookY, count: transferHookYAccounts.length });
|
|
560
|
-
remainingAccounts.push(...transferHookYAccounts.map(toRemainingAccountMeta));
|
|
561
|
-
}
|
|
547
|
+
const { groups, remainingAccounts } = buildTransferHookScheme(transferHookXAccounts, transferHookYAccounts);
|
|
562
548
|
|
|
563
549
|
const claimProtocolFeeIx = await generated.getClaimProtocolFeeInstructionAsync({
|
|
564
550
|
authority,
|
|
@@ -575,12 +561,7 @@ export class Pool {
|
|
|
575
561
|
tokenProgramY: this.tokenProgramY,
|
|
576
562
|
}, { programAddress: this.#programAddress });
|
|
577
563
|
|
|
578
|
-
|
|
579
|
-
...claimProtocolFeeIx,
|
|
580
|
-
accounts: [...claimProtocolFeeIx.accounts, ...remainingAccounts],
|
|
581
|
-
};
|
|
582
|
-
|
|
583
|
-
return [...preInstructions, claimProtocolFeeIxWithHookAccounts, ...postInstructions];
|
|
564
|
+
return [...preInstructions, appendRemainingAccounts(claimProtocolFeeIx, remainingAccounts), ...postInstructions];
|
|
584
565
|
}
|
|
585
566
|
|
|
586
567
|
public static async load(
|
package/src/entities/position.ts
CHANGED
|
@@ -3,7 +3,6 @@ import {
|
|
|
3
3
|
createSolanaRpc,
|
|
4
4
|
assertAccountExists,
|
|
5
5
|
fetchEncodedAccounts,
|
|
6
|
-
type AccountRole,
|
|
7
6
|
type Address,
|
|
8
7
|
type Account,
|
|
9
8
|
type Instruction,
|
|
@@ -18,7 +17,10 @@ import {
|
|
|
18
17
|
findPositionTokenAccount,
|
|
19
18
|
processAssociatedTokenAccountPair,
|
|
20
19
|
} from "../utils/ata";
|
|
21
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
appendRemainingAccounts,
|
|
22
|
+
buildTransferHookScheme,
|
|
23
|
+
} from "../utils/transfer_hook";
|
|
22
24
|
import {
|
|
23
25
|
getBinIndex,
|
|
24
26
|
getBinArrayIndex,
|
|
@@ -163,7 +165,29 @@ export class Position {
|
|
|
163
165
|
}
|
|
164
166
|
const [position, binArrays] = arg;
|
|
165
167
|
this.#account = position;
|
|
166
|
-
this.#binArrays.
|
|
168
|
+
await Promise.all(this.#binArrays.map((b, i) => b.refresh(binArrays[i])));
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Shared by depositByWeight/claimFee/withdraw — each needs the owner's position-NFT token
|
|
172
|
+
// account plus its X/Y ATAs (creating either that don't exist yet, funding wSOL if native).
|
|
173
|
+
// amounts is only relevant for a deposit (it decides how much wSOL to wrap); omitted for
|
|
174
|
+
// claim/withdraw, which only ever receive tokens.
|
|
175
|
+
async #prepareOwnerAccounts(
|
|
176
|
+
owner: TransactionSigner,
|
|
177
|
+
amounts?: { amountX: bigint, amountY: bigint },
|
|
178
|
+
) {
|
|
179
|
+
return await Promise.all([
|
|
180
|
+
findPositionTokenAccount({ owner: owner.address, positionMint: this.data.positionMint }),
|
|
181
|
+
processAssociatedTokenAccountPair({
|
|
182
|
+
owner,
|
|
183
|
+
tokenMintX: this.#pool.tokenMintX,
|
|
184
|
+
tokenMintY: this.#pool.tokenMintY,
|
|
185
|
+
tokenProgramX: this.#pool.tokenProgramX,
|
|
186
|
+
tokenProgramY: this.#pool.tokenProgramY,
|
|
187
|
+
amountX: amounts?.amountX,
|
|
188
|
+
amountY: amounts?.amountY,
|
|
189
|
+
}),
|
|
190
|
+
]);
|
|
167
191
|
}
|
|
168
192
|
|
|
169
193
|
public async depositByWeight(owner: TransactionSigner, {
|
|
@@ -189,18 +213,7 @@ export class Position {
|
|
|
189
213
|
ataY: tokenOwnerAccountY,
|
|
190
214
|
preInstructions,
|
|
191
215
|
postInstructions
|
|
192
|
-
}] = await
|
|
193
|
-
findPositionTokenAccount({ owner: owner.address, positionMint: this.data.positionMint }),
|
|
194
|
-
processAssociatedTokenAccountPair({
|
|
195
|
-
owner,
|
|
196
|
-
tokenMintX: this.#pool.tokenMintX,
|
|
197
|
-
tokenMintY: this.#pool.tokenMintY,
|
|
198
|
-
tokenProgramX: this.#pool.tokenProgramX,
|
|
199
|
-
tokenProgramY: this.#pool.tokenProgramY,
|
|
200
|
-
amountX,
|
|
201
|
-
amountY,
|
|
202
|
-
}),
|
|
203
|
-
]);
|
|
216
|
+
}] = await this.#prepareOwnerAccounts(owner, { amountX, amountY });
|
|
204
217
|
|
|
205
218
|
// Both legs move owner -> vault (deposit), signed by owner itself.
|
|
206
219
|
const [transferHookXAccounts, transferHookYAccounts] = await Promise.all([
|
|
@@ -212,17 +225,7 @@ export class Position {
|
|
|
212
225
|
}),
|
|
213
226
|
]);
|
|
214
227
|
|
|
215
|
-
const groups
|
|
216
|
-
const remainingAccounts: { address: Address, role: AccountRole }[] = [];
|
|
217
|
-
|
|
218
|
-
if (transferHookXAccounts.length > 0) {
|
|
219
|
-
groups.push({ kind: generated.AccountKind.TransferHookX, count: transferHookXAccounts.length });
|
|
220
|
-
remainingAccounts.push(...transferHookXAccounts.map(toRemainingAccountMeta));
|
|
221
|
-
}
|
|
222
|
-
if (transferHookYAccounts.length > 0) {
|
|
223
|
-
groups.push({ kind: generated.AccountKind.TransferHookY, count: transferHookYAccounts.length });
|
|
224
|
-
remainingAccounts.push(...transferHookYAccounts.map(toRemainingAccountMeta));
|
|
225
|
-
}
|
|
228
|
+
const { groups, remainingAccounts } = buildTransferHookScheme(transferHookXAccounts, transferHookYAccounts);
|
|
226
229
|
|
|
227
230
|
const { lowerBinArray, upperBinArray } = this.binArrayAddresses;
|
|
228
231
|
const depositByWeightIx = generated.getDepositByWeightInstruction({
|
|
@@ -252,12 +255,7 @@ export class Position {
|
|
|
252
255
|
programAddress: this.#pool.programAddress
|
|
253
256
|
});
|
|
254
257
|
|
|
255
|
-
|
|
256
|
-
...depositByWeightIx,
|
|
257
|
-
accounts: [...depositByWeightIx.accounts, ...remainingAccounts],
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
return [...preInstructions, depositByWeightIxWithHookAccounts, ...postInstructions];
|
|
258
|
+
return [...preInstructions, appendRemainingAccounts(depositByWeightIx, remainingAccounts), ...postInstructions];
|
|
261
259
|
}
|
|
262
260
|
|
|
263
261
|
async #buildClaimFeeInstruction(
|
|
@@ -280,17 +278,7 @@ export class Position {
|
|
|
280
278
|
}),
|
|
281
279
|
]);
|
|
282
280
|
|
|
283
|
-
const groups
|
|
284
|
-
const remainingAccounts: { address: Address, role: AccountRole }[] = [];
|
|
285
|
-
|
|
286
|
-
if (transferHookXAccounts.length > 0) {
|
|
287
|
-
groups.push({ kind: generated.AccountKind.TransferHookX, count: transferHookXAccounts.length });
|
|
288
|
-
remainingAccounts.push(...transferHookXAccounts.map(toRemainingAccountMeta));
|
|
289
|
-
}
|
|
290
|
-
if (transferHookYAccounts.length > 0) {
|
|
291
|
-
groups.push({ kind: generated.AccountKind.TransferHookY, count: transferHookYAccounts.length });
|
|
292
|
-
remainingAccounts.push(...transferHookYAccounts.map(toRemainingAccountMeta));
|
|
293
|
-
}
|
|
281
|
+
const { groups, remainingAccounts } = buildTransferHookScheme(transferHookXAccounts, transferHookYAccounts);
|
|
294
282
|
|
|
295
283
|
const { lowerBinArray, upperBinArray } = this.binArrayAddresses;
|
|
296
284
|
const claimFeeIx = generated.getClaimFeeInstruction({
|
|
@@ -315,28 +303,19 @@ export class Position {
|
|
|
315
303
|
programAddress: this.#pool.programAddress
|
|
316
304
|
});
|
|
317
305
|
|
|
318
|
-
return
|
|
306
|
+
return appendRemainingAccounts(claimFeeIx, remainingAccounts);
|
|
319
307
|
}
|
|
320
308
|
|
|
321
309
|
public async claimFee(
|
|
322
310
|
owner: TransactionSigner,
|
|
323
|
-
range?: BinIdRange,
|
|
311
|
+
{ range }: { range?: BinIdRange } = {},
|
|
324
312
|
): Promise<Instruction[]> {
|
|
325
313
|
const [positionTokenAccount, {
|
|
326
314
|
ataX: tokenOwnerAccountX,
|
|
327
315
|
ataY: tokenOwnerAccountY,
|
|
328
316
|
preInstructions,
|
|
329
317
|
postInstructions
|
|
330
|
-
}] = await
|
|
331
|
-
findPositionTokenAccount({ owner: owner.address, positionMint: this.data.positionMint }),
|
|
332
|
-
processAssociatedTokenAccountPair({
|
|
333
|
-
owner,
|
|
334
|
-
tokenMintX: this.#pool.tokenMintX,
|
|
335
|
-
tokenMintY: this.#pool.tokenMintY,
|
|
336
|
-
tokenProgramX: this.#pool.tokenProgramX,
|
|
337
|
-
tokenProgramY: this.#pool.tokenProgramY,
|
|
338
|
-
}),
|
|
339
|
-
]);
|
|
318
|
+
}] = await this.#prepareOwnerAccounts(owner);
|
|
340
319
|
|
|
341
320
|
const claimFeeIx = await this.#buildClaimFeeInstruction(
|
|
342
321
|
owner, positionTokenAccount, tokenOwnerAccountX, tokenOwnerAccountY, range,
|
|
@@ -347,8 +326,7 @@ export class Position {
|
|
|
347
326
|
|
|
348
327
|
public async withdraw(
|
|
349
328
|
owner: TransactionSigner,
|
|
350
|
-
bpsToRemove: number,
|
|
351
|
-
range?: BinIdRange,
|
|
329
|
+
{ bpsToRemove, range }: { bpsToRemove: number, range?: BinIdRange },
|
|
352
330
|
): Promise<Instruction[]> {
|
|
353
331
|
const { lowerBinId, upperBinId } = range ?? this.data;
|
|
354
332
|
assertRangeWithinRange({ lowerBinId, upperBinId }, this.data);
|
|
@@ -358,16 +336,7 @@ export class Position {
|
|
|
358
336
|
ataY: tokenOwnerAccountY,
|
|
359
337
|
preInstructions,
|
|
360
338
|
postInstructions
|
|
361
|
-
}] = await
|
|
362
|
-
findPositionTokenAccount({ owner: owner.address, positionMint: this.data.positionMint }),
|
|
363
|
-
processAssociatedTokenAccountPair({
|
|
364
|
-
owner,
|
|
365
|
-
tokenMintX: this.#pool.tokenMintX,
|
|
366
|
-
tokenMintY: this.#pool.tokenMintY,
|
|
367
|
-
tokenProgramX: this.#pool.tokenProgramX,
|
|
368
|
-
tokenProgramY: this.#pool.tokenProgramY,
|
|
369
|
-
}),
|
|
370
|
-
]);
|
|
339
|
+
}] = await this.#prepareOwnerAccounts(owner);
|
|
371
340
|
|
|
372
341
|
// Both legs move vault -> owner (withdraw), signed by the pool PDA.
|
|
373
342
|
const [transferHookXAccounts, transferHookYAccounts] = await Promise.all([
|
|
@@ -379,17 +348,7 @@ export class Position {
|
|
|
379
348
|
}),
|
|
380
349
|
]);
|
|
381
350
|
|
|
382
|
-
const groups
|
|
383
|
-
const remainingAccounts: { address: Address, role: AccountRole }[] = [];
|
|
384
|
-
|
|
385
|
-
if (transferHookXAccounts.length > 0) {
|
|
386
|
-
groups.push({ kind: generated.AccountKind.TransferHookX, count: transferHookXAccounts.length });
|
|
387
|
-
remainingAccounts.push(...transferHookXAccounts.map(toRemainingAccountMeta));
|
|
388
|
-
}
|
|
389
|
-
if (transferHookYAccounts.length > 0) {
|
|
390
|
-
groups.push({ kind: generated.AccountKind.TransferHookY, count: transferHookYAccounts.length });
|
|
391
|
-
remainingAccounts.push(...transferHookYAccounts.map(toRemainingAccountMeta));
|
|
392
|
-
}
|
|
351
|
+
const { groups, remainingAccounts } = buildTransferHookScheme(transferHookXAccounts, transferHookYAccounts);
|
|
393
352
|
|
|
394
353
|
const { lowerBinArray, upperBinArray } = this.binArrayAddresses;
|
|
395
354
|
const withdrawIx = generated.getWithdrawInstruction({
|
|
@@ -415,12 +374,7 @@ export class Position {
|
|
|
415
374
|
programAddress: this.#pool.programAddress
|
|
416
375
|
});
|
|
417
376
|
|
|
418
|
-
|
|
419
|
-
...withdrawIx,
|
|
420
|
-
accounts: [...withdrawIx.accounts, ...remainingAccounts],
|
|
421
|
-
};
|
|
422
|
-
|
|
423
|
-
return [...preInstructions, withdrawIxWithHookAccounts, ...postInstructions];
|
|
377
|
+
return [...preInstructions, appendRemainingAccounts(withdrawIx, remainingAccounts), ...postInstructions];
|
|
424
378
|
}
|
|
425
379
|
|
|
426
380
|
public async close(owner: TransactionSigner): Promise<Instruction> {
|
package/src/utils/ata.ts
CHANGED
|
@@ -41,28 +41,6 @@ export function findPositionTokenAccount({
|
|
|
41
41
|
return findAssociatedTokenPdaByTokenProgram({ owner, mint: positionMint, tokenProgram: TOKEN_2022_PROGRAM_ADDRESS });
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
// A pool's X/Y vaults — shared by every instruction that moves tokens through a pool
|
|
45
|
-
// (withdraw, claim_fee, claim_multiple_fees, claim_protocol_fee, deposit_by_weight, swap).
|
|
46
|
-
export async function findPoolTokenVaults({
|
|
47
|
-
pool,
|
|
48
|
-
tokenMintX,
|
|
49
|
-
tokenMintY,
|
|
50
|
-
tokenProgramX,
|
|
51
|
-
tokenProgramY,
|
|
52
|
-
}: {
|
|
53
|
-
pool: Address,
|
|
54
|
-
tokenMintX: Address,
|
|
55
|
-
tokenMintY: Address,
|
|
56
|
-
tokenProgramX: Address,
|
|
57
|
-
tokenProgramY: Address,
|
|
58
|
-
}): Promise<{ tokenVaultX: Address; tokenVaultY: Address }> {
|
|
59
|
-
const [tokenVaultX, tokenVaultY] = await Promise.all([
|
|
60
|
-
findAssociatedTokenPdaByTokenProgram({ owner: pool, mint: tokenMintX, tokenProgram: tokenProgramX }),
|
|
61
|
-
findAssociatedTokenPdaByTokenProgram({ owner: pool, mint: tokenMintY, tokenProgram: tokenProgramY }),
|
|
62
|
-
]);
|
|
63
|
-
return { tokenVaultX, tokenVaultY };
|
|
64
|
-
}
|
|
65
|
-
|
|
66
44
|
interface ProcessAssociatedTokenAccountParams {
|
|
67
45
|
owner: TransactionSigner,
|
|
68
46
|
mint: Address,
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
} from "@solana/kit";
|
|
10
10
|
import { SYSTEM_PROGRAM_ADDRESS } from "@solana-program/system";
|
|
11
11
|
import type { Mint, Extension } from "@solana-program/token-2022";
|
|
12
|
+
import * as generated from "../generated";
|
|
12
13
|
|
|
13
14
|
const EXTRA_ACCOUNT_METAS_SEED = "extra-account-metas";
|
|
14
15
|
|
|
@@ -288,3 +289,39 @@ export function toRemainingAccountMeta({ address, isSigner, isWritable }: ExtraA
|
|
|
288
289
|
: (isWritable ? AccountRole.WRITABLE : AccountRole.READONLY);
|
|
289
290
|
return { address, role };
|
|
290
291
|
}
|
|
292
|
+
|
|
293
|
+
export type RemainingAccountMeta = { address: Address, role: AccountRole };
|
|
294
|
+
|
|
295
|
+
// Builds the TransferHookX/TransferHookY groups + their remaining-account metas from a resolved
|
|
296
|
+
// pair of hook accounts — one group per side, omitted entirely when that side has no active hook
|
|
297
|
+
// (mirrors the on-chain program's own RemainingAccountsScheme, which only expects a group to be
|
|
298
|
+
// present when the corresponding mint actually carries a hook). Callers that also need a group
|
|
299
|
+
// ahead of these (e.g. swap's BinArray group) prepend their own groups/accounts to the result.
|
|
300
|
+
export function buildTransferHookScheme(
|
|
301
|
+
transferHookXAccounts: ExtraAccount[],
|
|
302
|
+
transferHookYAccounts: ExtraAccount[],
|
|
303
|
+
): { groups: generated.AccountGroup[], remainingAccounts: RemainingAccountMeta[] } {
|
|
304
|
+
const groups: generated.AccountGroup[] = [];
|
|
305
|
+
const remainingAccounts: RemainingAccountMeta[] = [];
|
|
306
|
+
|
|
307
|
+
if (transferHookXAccounts.length > 0) {
|
|
308
|
+
groups.push({ kind: generated.AccountKind.TransferHookX, count: transferHookXAccounts.length });
|
|
309
|
+
remainingAccounts.push(...transferHookXAccounts.map(toRemainingAccountMeta));
|
|
310
|
+
}
|
|
311
|
+
if (transferHookYAccounts.length > 0) {
|
|
312
|
+
groups.push({ kind: generated.AccountKind.TransferHookY, count: transferHookYAccounts.length });
|
|
313
|
+
remainingAccounts.push(...transferHookYAccounts.map(toRemainingAccountMeta));
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return { groups, remainingAccounts };
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Appends resolved remaining-account metas (transfer hook accounts, bin arrays, ...) onto an
|
|
320
|
+
// already-built instruction — the one-line splice every instruction builder in entities/ needs
|
|
321
|
+
// after computing its own RemainingAccountsScheme.
|
|
322
|
+
export function appendRemainingAccounts<TIx extends { accounts?: readonly unknown[] }>(
|
|
323
|
+
instruction: TIx,
|
|
324
|
+
remainingAccounts: RemainingAccountMeta[],
|
|
325
|
+
): TIx {
|
|
326
|
+
return { ...instruction, accounts: [...(instruction.accounts ?? []), ...remainingAccounts] };
|
|
327
|
+
}
|