@picon-finance/dlmm-sdk 1.2.0 → 1.3.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 +107 -16
- package/dist/entities/admin_config.d.ts +23 -0
- package/dist/entities/admin_config.d.ts.map +1 -0
- package/dist/entities/admin_config.js +54 -0
- package/dist/entities/bin_array.d.ts +36 -0
- package/dist/entities/bin_array.d.ts.map +1 -0
- package/dist/entities/bin_array.js +62 -0
- package/dist/entities/dlmm_program.d.ts +50 -0
- package/dist/entities/dlmm_program.d.ts.map +1 -0
- package/dist/entities/dlmm_program.js +73 -0
- package/dist/entities/index.d.ts +7 -0
- package/dist/entities/index.d.ts.map +1 -0
- package/dist/entities/index.js +6 -0
- package/dist/entities/pool.d.ts +71 -0
- package/dist/entities/pool.d.ts.map +1 -0
- package/dist/entities/pool.js +189 -0
- package/dist/entities/position.d.ts +51 -0
- package/dist/entities/position.d.ts.map +1 -0
- package/dist/entities/position.js +248 -0
- package/dist/entities/position_pool.d.ts +7 -0
- package/dist/entities/position_pool.d.ts.map +1 -0
- package/dist/entities/position_pool.js +30 -0
- package/dist/entities/types.d.ts +5 -0
- package/dist/entities/types.d.ts.map +1 -0
- package/dist/entities/types.js +0 -0
- package/dist/events.d.ts +9 -1
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +48 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/program_addresses.d.ts.map +1 -1
- package/dist/program_addresses.js +0 -5
- package/dist/utils/assert.d.ts +9 -0
- package/dist/utils/assert.d.ts.map +1 -0
- package/dist/utils/assert.js +10 -0
- package/dist/utils/bin_location.d.ts +4 -0
- package/dist/utils/bin_location.d.ts.map +1 -1
- package/dist/utils/bin_location.js +0 -12
- package/dist/utils/chunk.d.ts +1 -0
- package/dist/utils/chunk.d.ts.map +1 -1
- package/dist/utils/chunk.js +4 -0
- package/dist/utils/type_guards.d.ts +2 -0
- package/dist/utils/type_guards.d.ts.map +1 -1
- package/dist/utils/type_guards.js +7 -0
- package/package.json +1 -2
- package/src/entities/admin_config.ts +122 -0
- package/src/entities/bin_array.ts +156 -0
- package/src/entities/dlmm_program.ts +210 -0
- package/src/entities/index.ts +6 -0
- package/src/entities/pool.ts +392 -0
- package/src/entities/position.ts +444 -0
- package/src/entities/position_pool.ts +68 -0
- package/src/entities/types.ts +3 -0
- package/src/events.ts +77 -0
- package/src/index.ts +2 -1
- package/src/program_addresses.ts +0 -6
- package/src/utils/assert.ts +25 -0
- package/src/utils/bin_location.ts +5 -12
- package/src/utils/chunk.ts +9 -0
- package/src/utils/type_guards.ts +12 -0
- package/dist/actions/accept_admin_authority.d.ts +0 -13
- package/dist/actions/accept_admin_authority.d.ts.map +0 -1
- package/dist/actions/accept_admin_authority.js +0 -7
- package/dist/actions/claim_fee.d.ts +0 -21
- package/dist/actions/claim_fee.d.ts.map +0 -1
- package/dist/actions/claim_fee.js +0 -40
- package/dist/actions/claim_multiple_fees.d.ts +0 -19
- package/dist/actions/claim_multiple_fees.d.ts.map +0 -1
- package/dist/actions/claim_multiple_fees.js +0 -81
- package/dist/actions/claim_protocol_fee.d.ts +0 -18
- package/dist/actions/claim_protocol_fee.d.ts.map +0 -1
- package/dist/actions/claim_protocol_fee.js +0 -33
- package/dist/actions/close_position.d.ts +0 -14
- package/dist/actions/close_position.d.ts.map +0 -1
- package/dist/actions/close_position.js +0 -14
- package/dist/actions/create_admin_config.d.ts +0 -15
- package/dist/actions/create_admin_config.d.ts.map +0 -1
- package/dist/actions/create_admin_config.js +0 -30
- package/dist/actions/create_bin_array.d.ts +0 -16
- package/dist/actions/create_bin_array.d.ts.map +0 -1
- package/dist/actions/create_bin_array.js +0 -10
- package/dist/actions/create_pool.d.ts +0 -21
- package/dist/actions/create_pool.d.ts.map +0 -1
- package/dist/actions/create_pool.js +0 -22
- package/dist/actions/delete_bin_array.d.ts +0 -16
- package/dist/actions/delete_bin_array.d.ts.map +0 -1
- package/dist/actions/delete_bin_array.js +0 -13
- package/dist/actions/deposit_by_weight.d.ts +0 -27
- package/dist/actions/deposit_by_weight.d.ts.map +0 -1
- package/dist/actions/deposit_by_weight.js +0 -52
- package/dist/actions/get_admin_config.d.ts +0 -4
- package/dist/actions/get_admin_config.d.ts.map +0 -1
- package/dist/actions/get_admin_config.js +0 -7
- package/dist/actions/get_bin_arrays_by_indices.d.ts +0 -5
- package/dist/actions/get_bin_arrays_by_indices.d.ts.map +0 -1
- package/dist/actions/get_bin_arrays_by_indices.js +0 -6
- package/dist/actions/get_pool.d.ts +0 -4
- package/dist/actions/get_pool.d.ts.map +0 -1
- package/dist/actions/get_pool.js +0 -5
- package/dist/actions/get_position.d.ts +0 -4
- package/dist/actions/get_position.d.ts.map +0 -1
- package/dist/actions/get_position.js +0 -5
- package/dist/actions/get_position_by_position_mint.d.ts +0 -4
- package/dist/actions/get_position_by_position_mint.d.ts.map +0 -1
- package/dist/actions/get_position_by_position_mint.js +0 -6
- package/dist/actions/get_positions_by_owner.d.ts +0 -5
- package/dist/actions/get_positions_by_owner.d.ts.map +0 -1
- package/dist/actions/get_positions_by_owner.js +0 -33
- package/dist/actions/get_positions_by_position_mints.d.ts +0 -5
- package/dist/actions/get_positions_by_position_mints.d.ts.map +0 -1
- package/dist/actions/get_positions_by_position_mints.js +0 -9
- package/dist/actions/helpers/build_swap_transaction_message.d.ts +0 -22
- package/dist/actions/helpers/build_swap_transaction_message.d.ts.map +0 -1
- package/dist/actions/helpers/build_swap_transaction_message.js +0 -50
- package/dist/actions/helpers/build_transaction_message.d.ts +0 -20
- package/dist/actions/helpers/build_transaction_message.d.ts.map +0 -1
- package/dist/actions/helpers/build_transaction_message.js +0 -5
- package/dist/actions/helpers/index.d.ts +0 -8
- package/dist/actions/helpers/index.d.ts.map +0 -1
- package/dist/actions/helpers/index.js +0 -7
- package/dist/actions/helpers/resolve_active_bin_and_mints.d.ts +0 -12
- package/dist/actions/helpers/resolve_active_bin_and_mints.d.ts.map +0 -1
- package/dist/actions/helpers/resolve_active_bin_and_mints.js +0 -13
- package/dist/actions/helpers/resolve_admin_config_address.d.ts +0 -3
- package/dist/actions/helpers/resolve_admin_config_address.d.ts.map +0 -1
- package/dist/actions/helpers/resolve_admin_config_address.js +0 -9
- package/dist/actions/helpers/resolve_mint_info.d.ts +0 -10
- package/dist/actions/helpers/resolve_mint_info.d.ts.map +0 -1
- package/dist/actions/helpers/resolve_mint_info.js +0 -20
- package/dist/actions/helpers/resolve_position_range.d.ts +0 -12
- package/dist/actions/helpers/resolve_position_range.d.ts.map +0 -1
- package/dist/actions/helpers/resolve_position_range.js +0 -12
- package/dist/actions/helpers/resolve_token_mints_and_programs.d.ts +0 -15
- package/dist/actions/helpers/resolve_token_mints_and_programs.d.ts.map +0 -1
- package/dist/actions/helpers/resolve_token_mints_and_programs.js +0 -29
- package/dist/actions/index.d.ts +0 -31
- package/dist/actions/index.d.ts.map +0 -1
- package/dist/actions/index.js +0 -28
- package/dist/actions/is_admin_config_active.d.ts +0 -4
- package/dist/actions/is_admin_config_active.d.ts.map +0 -1
- package/dist/actions/is_admin_config_active.js +0 -7
- package/dist/actions/on_event.d.ts +0 -11
- package/dist/actions/on_event.d.ts.map +0 -1
- package/dist/actions/on_event.js +0 -50
- package/dist/actions/open_position.d.ts +0 -17
- package/dist/actions/open_position.d.ts.map +0 -1
- package/dist/actions/open_position.js +0 -31
- package/dist/actions/quote.d.ts +0 -13
- package/dist/actions/quote.d.ts.map +0 -1
- package/dist/actions/quote.js +0 -43
- package/dist/actions/set_metadata_update_authority.d.ts +0 -14
- package/dist/actions/set_metadata_update_authority.d.ts.map +0 -1
- package/dist/actions/set_metadata_update_authority.js +0 -7
- package/dist/actions/set_pool_dynamic_fee_config.d.ts +0 -16
- package/dist/actions/set_pool_dynamic_fee_config.d.ts.map +0 -1
- package/dist/actions/set_pool_dynamic_fee_config.js +0 -7
- package/dist/actions/set_pool_protocol_share.d.ts +0 -15
- package/dist/actions/set_pool_protocol_share.d.ts.map +0 -1
- package/dist/actions/set_pool_protocol_share.js +0 -7
- package/dist/actions/swap.d.ts +0 -22
- package/dist/actions/swap.d.ts.map +0 -1
- package/dist/actions/swap.js +0 -19
- package/dist/actions/sync_pool.d.ts +0 -15
- package/dist/actions/sync_pool.d.ts.map +0 -1
- package/dist/actions/sync_pool.js +0 -26
- package/dist/actions/transfer_admin_authority.d.ts +0 -14
- package/dist/actions/transfer_admin_authority.d.ts.map +0 -1
- package/dist/actions/transfer_admin_authority.js +0 -7
- package/dist/actions/withdraw.d.ts +0 -22
- package/dist/actions/withdraw.d.ts.map +0 -1
- package/dist/actions/withdraw.js +0 -41
- package/dist/utils/admin_config.d.ts +0 -3
- package/dist/utils/admin_config.d.ts.map +0 -1
- package/dist/utils/admin_config.js +0 -4
- package/dist/utils/bin_array.d.ts +0 -8
- package/dist/utils/bin_array.d.ts.map +0 -1
- package/dist/utils/bin_array.js +0 -29
- package/dist/utils/compute_budget.d.ts +0 -11
- package/dist/utils/compute_budget.d.ts.map +0 -1
- package/dist/utils/compute_budget.js +0 -22
- package/src/actions/accept_admin_authority.ts +0 -17
- package/src/actions/claim_fee.ts +0 -84
- package/src/actions/claim_multiple_fees.ts +0 -123
- package/src/actions/claim_protocol_fee.ts +0 -68
- package/src/actions/close_position.ts +0 -21
- package/src/actions/create_admin_config.ts +0 -51
- package/src/actions/create_bin_array.ts +0 -30
- package/src/actions/create_pool.ts +0 -49
- package/src/actions/delete_bin_array.ts +0 -33
- package/src/actions/deposit_by_weight.ts +0 -107
- package/src/actions/get_admin_config.ts +0 -13
- package/src/actions/get_bin_arrays_by_indices.ts +0 -15
- package/src/actions/get_pool.ts +0 -8
- package/src/actions/get_position.ts +0 -8
- package/src/actions/get_position_by_position_mint.ts +0 -14
- package/src/actions/get_positions_by_owner.ts +0 -48
- package/src/actions/get_positions_by_position_mints.ts +0 -21
- package/src/actions/helpers/build_swap_transaction_message.ts +0 -86
- package/src/actions/helpers/build_transaction_message.ts +0 -45
- package/src/actions/helpers/index.ts +0 -7
- package/src/actions/helpers/resolve_active_bin_and_mints.ts +0 -21
- package/src/actions/helpers/resolve_admin_config_address.ts +0 -11
- package/src/actions/helpers/resolve_mint_info.ts +0 -36
- package/src/actions/helpers/resolve_position_range.ts +0 -21
- package/src/actions/helpers/resolve_token_mints_and_programs.ts +0 -56
- package/src/actions/index.ts +0 -34
- package/src/actions/is_admin_config_active.ts +0 -14
- package/src/actions/on_event.ts +0 -78
- package/src/actions/open_position.ts +0 -66
- package/src/actions/quote.ts +0 -70
- package/src/actions/set_metadata_update_authority.ts +0 -17
- package/src/actions/set_pool_dynamic_fee_config.ts +0 -17
- package/src/actions/set_pool_protocol_share.ts +0 -17
- package/src/actions/swap.ts +0 -56
- package/src/actions/sync_pool.ts +0 -35
- package/src/actions/transfer_admin_authority.ts +0 -17
- package/src/actions/withdraw.ts +0 -87
- package/src/utils/admin_config.ts +0 -6
- package/src/utils/bin_array.ts +0 -45
- package/src/utils/compute_budget.ts +0 -58
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
import {
|
|
2
|
+
decodeAccount,
|
|
3
|
+
createSolanaRpc,
|
|
4
|
+
assertAccountExists,
|
|
5
|
+
fetchEncodedAccounts,
|
|
6
|
+
type Address,
|
|
7
|
+
type Account,
|
|
8
|
+
type Instruction,
|
|
9
|
+
type TransactionSigner,
|
|
10
|
+
type FetchAccountsConfig,
|
|
11
|
+
type MaybeEncodedAccount,
|
|
12
|
+
} from "@solana/kit";
|
|
13
|
+
|
|
14
|
+
import { generated } from "..";
|
|
15
|
+
import {
|
|
16
|
+
findPositionTokenAccount,
|
|
17
|
+
processAssociatedTokenAccountPair,
|
|
18
|
+
} from "../utils/ata";
|
|
19
|
+
import {
|
|
20
|
+
getBinArrayIndex,
|
|
21
|
+
getPositionBinArrayIndices,
|
|
22
|
+
type BinIdRange,
|
|
23
|
+
} from "../utils/bin_location";
|
|
24
|
+
import {
|
|
25
|
+
assertRangeWithinRange,
|
|
26
|
+
assertPositionBelongsToPool,
|
|
27
|
+
} from "../utils/assert";
|
|
28
|
+
import { isUndefined } from "../utils/type_guards";
|
|
29
|
+
import { fetchInChunks } from "../utils/chunk";
|
|
30
|
+
import { resolveAdminConfigAddress } from "./admin_config";
|
|
31
|
+
import { MAX_ACCOUNTS_PER_RPC_BATCH } from "../utils/constants";
|
|
32
|
+
|
|
33
|
+
import { Pool } from "./pool";
|
|
34
|
+
import {
|
|
35
|
+
BinArray,
|
|
36
|
+
decodeAllBinArrays,
|
|
37
|
+
createAllBinArrays,
|
|
38
|
+
fetchAllBinArraysChunked,
|
|
39
|
+
} from "./bin_array";
|
|
40
|
+
import { type ProgramConfig } from "./types";
|
|
41
|
+
|
|
42
|
+
export class Position {
|
|
43
|
+
#pool: Pool;
|
|
44
|
+
#account: Account<generated.Position>;
|
|
45
|
+
#binArrays: BinArray[];
|
|
46
|
+
|
|
47
|
+
private constructor(
|
|
48
|
+
pool: Pool,
|
|
49
|
+
account: Account<generated.Position>,
|
|
50
|
+
binArrays: BinArray[],
|
|
51
|
+
) {
|
|
52
|
+
this.#pool = pool;
|
|
53
|
+
this.#account = account;
|
|
54
|
+
this.#binArrays = binArrays;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public get address() { return this.#account.address; }
|
|
58
|
+
public get data() { return this.#account.data; }
|
|
59
|
+
public get positionMint() { return this.data.positionMint; }
|
|
60
|
+
|
|
61
|
+
public get binArrayAddresses(): { lowerBinArray: Address, upperBinArray?: Address | undefined } {
|
|
62
|
+
const lowerBinArray = this.#binArrays[0].address;
|
|
63
|
+
const upperBinArray = this.#binArrays.length > 1 ? this.#binArrays[1].address : undefined;
|
|
64
|
+
return { lowerBinArray, upperBinArray };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
public async refresh(data: [Account<generated.Position>, Account<generated.BinArray>[]]): Promise<void>;
|
|
68
|
+
public async refresh(config?: FetchAccountsConfig): Promise<void>;
|
|
69
|
+
public async refresh(arg?: [Account<generated.Position>, Account<generated.BinArray>[]] | FetchAccountsConfig) {
|
|
70
|
+
if (!Array.isArray(arg)) {
|
|
71
|
+
arg = await fetchPositionWithBinArrays(
|
|
72
|
+
this.#pool.rpc,
|
|
73
|
+
this.address,
|
|
74
|
+
this.#binArrays.map(b => b.address),
|
|
75
|
+
arg,
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
const [position, binArrays] = arg;
|
|
79
|
+
this.#account = position;
|
|
80
|
+
this.#binArrays.forEach((b, i) => b.refresh(binArrays[i]));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public async depositByWeight(owner: TransactionSigner, {
|
|
84
|
+
amountX,
|
|
85
|
+
amountY,
|
|
86
|
+
lowerBinId,
|
|
87
|
+
binWeights,
|
|
88
|
+
maxActiveBinSlippage,
|
|
89
|
+
distributionMode,
|
|
90
|
+
}: {
|
|
91
|
+
amountX: bigint,
|
|
92
|
+
amountY: bigint,
|
|
93
|
+
lowerBinId: number,
|
|
94
|
+
binWeights: number[],
|
|
95
|
+
maxActiveBinSlippage: number,
|
|
96
|
+
distributionMode: generated.DistributionMode,
|
|
97
|
+
}): Promise<Instruction[]> {
|
|
98
|
+
const upperBinId = lowerBinId + binWeights.length - 1;
|
|
99
|
+
assertRangeWithinRange({ lowerBinId, upperBinId }, this.data);
|
|
100
|
+
|
|
101
|
+
const [positionTokenAccount, {
|
|
102
|
+
ataX: tokenOwnerAccountX,
|
|
103
|
+
ataY: tokenOwnerAccountY,
|
|
104
|
+
preInstructions,
|
|
105
|
+
postInstructions
|
|
106
|
+
}] = await Promise.all([
|
|
107
|
+
findPositionTokenAccount({ owner: owner.address, positionMint: this.data.positionMint }),
|
|
108
|
+
processAssociatedTokenAccountPair({
|
|
109
|
+
owner,
|
|
110
|
+
tokenMintX: this.#pool.tokenMintX,
|
|
111
|
+
tokenMintY: this.#pool.tokenMintY,
|
|
112
|
+
tokenProgramX: this.#pool.tokenProgramX,
|
|
113
|
+
tokenProgramY: this.#pool.tokenProgramY,
|
|
114
|
+
amountX,
|
|
115
|
+
amountY,
|
|
116
|
+
}),
|
|
117
|
+
]);
|
|
118
|
+
|
|
119
|
+
const { lowerBinArray, upperBinArray } = this.binArrayAddresses;
|
|
120
|
+
const depositByWeightIx = generated.getDepositByWeightInstruction({
|
|
121
|
+
owner,
|
|
122
|
+
pool: this.#pool.address,
|
|
123
|
+
position: this.address,
|
|
124
|
+
positionTokenAccount,
|
|
125
|
+
tokenMintX: this.#pool.tokenMintX,
|
|
126
|
+
tokenMintY: this.#pool.tokenMintY,
|
|
127
|
+
tokenOwnerAccountX,
|
|
128
|
+
tokenOwnerAccountY,
|
|
129
|
+
tokenVaultX: this.#pool.tokenVaultX,
|
|
130
|
+
tokenVaultY: this.#pool.tokenVaultY,
|
|
131
|
+
tokenProgramX: this.#pool.tokenProgramX,
|
|
132
|
+
tokenProgramY: this.#pool.tokenProgramY,
|
|
133
|
+
lowerBinArray,
|
|
134
|
+
upperBinArray,
|
|
135
|
+
amountX,
|
|
136
|
+
amountY,
|
|
137
|
+
activeBinId: this.#pool.activeBinId,
|
|
138
|
+
maxActiveBinSlippage,
|
|
139
|
+
distributionMode,
|
|
140
|
+
lowerBinId,
|
|
141
|
+
binWeights,
|
|
142
|
+
}, {
|
|
143
|
+
programAddress: this.#pool.programAddress
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
return [...preInstructions, depositByWeightIx, ...postInstructions];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
public async claimFee(
|
|
150
|
+
owner: TransactionSigner,
|
|
151
|
+
range?: BinIdRange,
|
|
152
|
+
): Promise<Instruction[]> {
|
|
153
|
+
const { lowerBinId, upperBinId } = range ?? this.data;
|
|
154
|
+
assertRangeWithinRange({ lowerBinId, upperBinId }, this.data);
|
|
155
|
+
|
|
156
|
+
const [positionTokenAccount, {
|
|
157
|
+
ataX: tokenOwnerAccountX,
|
|
158
|
+
ataY: tokenOwnerAccountY,
|
|
159
|
+
preInstructions,
|
|
160
|
+
postInstructions
|
|
161
|
+
}] = await Promise.all([
|
|
162
|
+
findPositionTokenAccount({ owner: owner.address, positionMint: this.data.positionMint }),
|
|
163
|
+
processAssociatedTokenAccountPair({
|
|
164
|
+
owner,
|
|
165
|
+
tokenMintX: this.#pool.tokenMintX,
|
|
166
|
+
tokenMintY: this.#pool.tokenMintY,
|
|
167
|
+
tokenProgramX: this.#pool.tokenProgramX,
|
|
168
|
+
tokenProgramY: this.#pool.tokenProgramY,
|
|
169
|
+
}),
|
|
170
|
+
]);
|
|
171
|
+
|
|
172
|
+
const { lowerBinArray, upperBinArray } = this.binArrayAddresses;
|
|
173
|
+
const claimFeeIx = generated.getClaimFeeInstruction({
|
|
174
|
+
owner,
|
|
175
|
+
pool: this.#pool.address,
|
|
176
|
+
position: this.address,
|
|
177
|
+
positionTokenAccount,
|
|
178
|
+
tokenMintX: this.#pool.tokenMintX,
|
|
179
|
+
tokenMintY: this.#pool.tokenMintY,
|
|
180
|
+
tokenOwnerAccountX,
|
|
181
|
+
tokenOwnerAccountY,
|
|
182
|
+
tokenVaultX: this.#pool.tokenVaultX,
|
|
183
|
+
tokenVaultY: this.#pool.tokenVaultY,
|
|
184
|
+
tokenProgramX: this.#pool.tokenProgramX,
|
|
185
|
+
tokenProgramY: this.#pool.tokenProgramY,
|
|
186
|
+
lowerBinArray,
|
|
187
|
+
upperBinArray,
|
|
188
|
+
lowerBinId,
|
|
189
|
+
upperBinId,
|
|
190
|
+
}, {
|
|
191
|
+
programAddress: this.#pool.programAddress
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
return [...preInstructions, claimFeeIx, ...postInstructions];
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
public async withdraw(
|
|
198
|
+
owner: TransactionSigner,
|
|
199
|
+
bpsToRemove: number,
|
|
200
|
+
range?: BinIdRange,
|
|
201
|
+
): Promise<Instruction[]> {
|
|
202
|
+
const { lowerBinId, upperBinId } = range ?? this.data;
|
|
203
|
+
assertRangeWithinRange({ lowerBinId, upperBinId }, this.data);
|
|
204
|
+
|
|
205
|
+
const [positionTokenAccount, {
|
|
206
|
+
ataX: tokenOwnerAccountX,
|
|
207
|
+
ataY: tokenOwnerAccountY,
|
|
208
|
+
preInstructions,
|
|
209
|
+
postInstructions
|
|
210
|
+
}] = await Promise.all([
|
|
211
|
+
findPositionTokenAccount({ owner: owner.address, positionMint: this.data.positionMint }),
|
|
212
|
+
processAssociatedTokenAccountPair({
|
|
213
|
+
owner,
|
|
214
|
+
tokenMintX: this.#pool.tokenMintX,
|
|
215
|
+
tokenMintY: this.#pool.tokenMintY,
|
|
216
|
+
tokenProgramX: this.#pool.tokenProgramX,
|
|
217
|
+
tokenProgramY: this.#pool.tokenProgramY,
|
|
218
|
+
}),
|
|
219
|
+
]);
|
|
220
|
+
|
|
221
|
+
const { lowerBinArray, upperBinArray } = this.binArrayAddresses;
|
|
222
|
+
const withdrawIx = generated.getWithdrawInstruction({
|
|
223
|
+
owner,
|
|
224
|
+
pool: this.#pool.address,
|
|
225
|
+
position: this.address,
|
|
226
|
+
positionTokenAccount,
|
|
227
|
+
tokenMintX: this.#pool.tokenMintX,
|
|
228
|
+
tokenMintY: this.#pool.tokenMintY,
|
|
229
|
+
tokenOwnerAccountX,
|
|
230
|
+
tokenOwnerAccountY,
|
|
231
|
+
tokenVaultX: this.#pool.tokenVaultX,
|
|
232
|
+
tokenVaultY: this.#pool.tokenVaultY,
|
|
233
|
+
tokenProgramX: this.#pool.tokenProgramX,
|
|
234
|
+
tokenProgramY: this.#pool.tokenProgramY,
|
|
235
|
+
lowerBinArray,
|
|
236
|
+
upperBinArray,
|
|
237
|
+
lowerBinId,
|
|
238
|
+
upperBinId,
|
|
239
|
+
bpsToRemove,
|
|
240
|
+
}, {
|
|
241
|
+
programAddress: this.#pool.programAddress
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
return [...preInstructions, withdrawIx, ...postInstructions];
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
public async close(owner: TransactionSigner): Promise<Instruction> {
|
|
248
|
+
return await closePosition(
|
|
249
|
+
{ owner, positionMint: this.data.positionMint, position: this.address },
|
|
250
|
+
{ programAddress: this.#pool.programAddress },
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
public static async load(
|
|
255
|
+
pool: Pool,
|
|
256
|
+
address: Address,
|
|
257
|
+
config?: FetchAccountsConfig,
|
|
258
|
+
): Promise<Position> {
|
|
259
|
+
const position = await generated.fetchPosition(pool.rpc, address, config);
|
|
260
|
+
assertPositionBelongsToPool(position.data, pool);
|
|
261
|
+
|
|
262
|
+
const { lowerBinId, upperBinId } = position.data;
|
|
263
|
+
const indices = [...new Set([
|
|
264
|
+
getBinArrayIndex(lowerBinId),
|
|
265
|
+
getBinArrayIndex(upperBinId),
|
|
266
|
+
])];
|
|
267
|
+
const binArrays = await BinArray.loadAll(
|
|
268
|
+
pool.rpc,
|
|
269
|
+
pool.address,
|
|
270
|
+
indices,
|
|
271
|
+
pool.programAddress,
|
|
272
|
+
config,
|
|
273
|
+
);
|
|
274
|
+
|
|
275
|
+
return new Position(pool, position, binArrays);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
public static async loadAll(
|
|
279
|
+
pool: Pool,
|
|
280
|
+
addresses: Address[],
|
|
281
|
+
config?: FetchAccountsConfig,
|
|
282
|
+
): Promise<Position[]> {
|
|
283
|
+
const positions = await fetchAllPositionsChunked(pool.rpc, addresses, config);
|
|
284
|
+
|
|
285
|
+
const indicesByPosition = positions.map(position =>
|
|
286
|
+
[...new Set([getBinArrayIndex(position.data.lowerBinId), getBinArrayIndex(position.data.upperBinId)])]);
|
|
287
|
+
const binArrays = await BinArray.loadAll(
|
|
288
|
+
pool.rpc,
|
|
289
|
+
pool.address,
|
|
290
|
+
[...new Set(indicesByPosition.flat())],
|
|
291
|
+
pool.programAddress, config,
|
|
292
|
+
);
|
|
293
|
+
const binArrayByIndex = new Map(binArrays.map(binArray => [binArray.data.index, binArray]));
|
|
294
|
+
|
|
295
|
+
return positions.map((position, i) => {
|
|
296
|
+
assertPositionBelongsToPool(position.data, pool);
|
|
297
|
+
const positionBinArrays = indicesByPosition[i].map(index => binArrayByIndex.get(index)!);
|
|
298
|
+
return new Position(pool, position, positionBinArrays);
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
public static async refreshAll(
|
|
303
|
+
rpc: ReturnType<typeof createSolanaRpc>,
|
|
304
|
+
positions: Position[],
|
|
305
|
+
config?: FetchAccountsConfig,
|
|
306
|
+
): Promise<void> {
|
|
307
|
+
if (positions.length === 0) {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const addresses = positions.map(position => position.address);
|
|
312
|
+
const positionAccounts = await fetchAllPositionsChunked(rpc, addresses, config);
|
|
313
|
+
|
|
314
|
+
const binArrayAddresses = [...new Set(positions.flatMap(position =>
|
|
315
|
+
position.#binArrays.map(binArray => binArray.address)))];
|
|
316
|
+
const binArrayAccounts = await fetchAllBinArraysChunked(rpc, binArrayAddresses, config);
|
|
317
|
+
const binArrayByAddress = new Map(binArrayAccounts.map(account => [account.address, account]));
|
|
318
|
+
|
|
319
|
+
await Promise.all(positions.map((position, i) => position.refresh([
|
|
320
|
+
positionAccounts[i],
|
|
321
|
+
position.#binArrays.map(binArray => binArrayByAddress.get(binArray.address)!),
|
|
322
|
+
])));
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export async function findPositionAddress(
|
|
327
|
+
seeds: { positionMint: Address },
|
|
328
|
+
config: ProgramConfig,
|
|
329
|
+
): Promise<Address> {
|
|
330
|
+
const [address] = await generated.findPositionPda(seeds, config);
|
|
331
|
+
return address;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export async function findAllPositionAddresses(
|
|
335
|
+
{ positionMints }: { positionMints: Address[] },
|
|
336
|
+
config: ProgramConfig,
|
|
337
|
+
): Promise<Address[]> {
|
|
338
|
+
return await Promise.all(
|
|
339
|
+
positionMints.map(positionMint => findPositionAddress({ positionMint }, config))
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export async function openPosition(
|
|
344
|
+
rpc: ReturnType<typeof createSolanaRpc>,
|
|
345
|
+
{
|
|
346
|
+
owner,
|
|
347
|
+
positionMint,
|
|
348
|
+
pool,
|
|
349
|
+
lowerBinId,
|
|
350
|
+
upperBinId,
|
|
351
|
+
}: {
|
|
352
|
+
owner: TransactionSigner,
|
|
353
|
+
positionMint: TransactionSigner,
|
|
354
|
+
pool: Address,
|
|
355
|
+
lowerBinId: number,
|
|
356
|
+
upperBinId: number,
|
|
357
|
+
},
|
|
358
|
+
config: ProgramConfig,
|
|
359
|
+
): Promise<Instruction[]> {
|
|
360
|
+
const [adminConfig, position] = await Promise.all([
|
|
361
|
+
resolveAdminConfigAddress(config.programAddress),
|
|
362
|
+
findPositionAddress({ positionMint: positionMint.address }, config),
|
|
363
|
+
]);
|
|
364
|
+
const { metadataUpdateAuthority } = (await generated.fetchAdminConfig(rpc, adminConfig)).data;
|
|
365
|
+
const { lowerBinArrayIndex, upperBinArrayIndex } = getPositionBinArrayIndices(lowerBinId, upperBinId);
|
|
366
|
+
const indices = isUndefined(upperBinArrayIndex) ? [lowerBinArrayIndex] : [lowerBinArrayIndex, upperBinArrayIndex];
|
|
367
|
+
const createBinArraysIxs = await createAllBinArrays(
|
|
368
|
+
{ payer: owner, pool, indices, idempotent: true },
|
|
369
|
+
config,
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
const openPositionIx = await generated.getOpenPositionInstructionAsync({
|
|
373
|
+
pool,
|
|
374
|
+
lowerBinId,
|
|
375
|
+
upperBinId,
|
|
376
|
+
owner,
|
|
377
|
+
positionMint,
|
|
378
|
+
position,
|
|
379
|
+
adminConfig,
|
|
380
|
+
metadataUpdateAuthority,
|
|
381
|
+
}, config);
|
|
382
|
+
|
|
383
|
+
return [...createBinArraysIxs, openPositionIx];
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
export async function closePosition(
|
|
387
|
+
{
|
|
388
|
+
owner,
|
|
389
|
+
positionMint,
|
|
390
|
+
position,
|
|
391
|
+
}: {
|
|
392
|
+
owner: TransactionSigner,
|
|
393
|
+
positionMint: Address,
|
|
394
|
+
position?: Address,
|
|
395
|
+
},
|
|
396
|
+
config: ProgramConfig,
|
|
397
|
+
): Promise<Instruction> {
|
|
398
|
+
const [resolvedPosition, positionTokenAccount] = await Promise.all([
|
|
399
|
+
position ?? findPositionAddress({ positionMint }, config),
|
|
400
|
+
findPositionTokenAccount({ owner: owner.address, positionMint }),
|
|
401
|
+
]);
|
|
402
|
+
return await generated.getClosePositionInstructionAsync({
|
|
403
|
+
owner,
|
|
404
|
+
position: resolvedPosition,
|
|
405
|
+
positionMint,
|
|
406
|
+
positionTokenAccount,
|
|
407
|
+
}, config);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
async function fetchPositionWithBinArrays(
|
|
411
|
+
rpc: ReturnType<typeof createSolanaRpc>,
|
|
412
|
+
positionAddress: Address,
|
|
413
|
+
binArrayAddresses: Address[],
|
|
414
|
+
config?: FetchAccountsConfig,
|
|
415
|
+
): Promise<[Account<generated.Position>, Account<generated.BinArray>[]]> {
|
|
416
|
+
const [positionAccount, ...binArrayAccounts] = await fetchEncodedAccounts(rpc, [
|
|
417
|
+
positionAddress, ...binArrayAddresses,
|
|
418
|
+
], config);
|
|
419
|
+
return [
|
|
420
|
+
decodePosition(positionAccount),
|
|
421
|
+
decodeAllBinArrays(binArrayAccounts)
|
|
422
|
+
];
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
async function fetchAllPositionsChunked(
|
|
426
|
+
rpc: ReturnType<typeof createSolanaRpc>,
|
|
427
|
+
addresses: Address[],
|
|
428
|
+
config?: FetchAccountsConfig,
|
|
429
|
+
) {
|
|
430
|
+
return await fetchInChunks(
|
|
431
|
+
addresses,
|
|
432
|
+
MAX_ACCOUNTS_PER_RPC_BATCH,
|
|
433
|
+
chunkAddresses => generated.fetchAllPosition(rpc, chunkAddresses, config),
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
const positionDecoder = generated.getPositionDecoder();
|
|
438
|
+
|
|
439
|
+
function decodePosition(
|
|
440
|
+
maybeAccount: MaybeEncodedAccount<string>,
|
|
441
|
+
): Account<generated.Position> {
|
|
442
|
+
assertAccountExists(maybeAccount);
|
|
443
|
+
return decodeAccount(maybeAccount, positionDecoder);
|
|
444
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createSolanaRpc,
|
|
3
|
+
getAddressDecoder,
|
|
4
|
+
parseBase64RpcAccount,
|
|
5
|
+
type Address,
|
|
6
|
+
type AccountInfoBase,
|
|
7
|
+
type FetchAccountsConfig,
|
|
8
|
+
type AccountInfoWithBase64EncodedData,
|
|
9
|
+
} from "@solana/kit";
|
|
10
|
+
import { fetchInChunks } from "../utils/chunk";
|
|
11
|
+
import { MAX_ACCOUNTS_PER_RPC_BATCH } from "../utils/constants";
|
|
12
|
+
|
|
13
|
+
export type PositionPoolEntry = {
|
|
14
|
+
address: Address,
|
|
15
|
+
pool: Address,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export async function fetchAllMaybePositionPoolsChunked(
|
|
19
|
+
rpc: ReturnType<typeof createSolanaRpc>,
|
|
20
|
+
addresses: Address[],
|
|
21
|
+
config?: FetchAccountsConfig,
|
|
22
|
+
): Promise<(PositionPoolEntry | undefined)[]> {
|
|
23
|
+
return await fetchInChunks(
|
|
24
|
+
addresses,
|
|
25
|
+
MAX_ACCOUNTS_PER_RPC_BATCH,
|
|
26
|
+
chunkAddresses => fetchAllMaybePositionPools(rpc, chunkAddresses, config),
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const POSITION_POOL_SLICE = Object.freeze({ offset: 8, length: 32 });
|
|
31
|
+
|
|
32
|
+
async function fetchAllMaybePositionPools(
|
|
33
|
+
rpc: ReturnType<typeof createSolanaRpc>,
|
|
34
|
+
addresses: Address[],
|
|
35
|
+
config?: FetchAccountsConfig,
|
|
36
|
+
): Promise<(PositionPoolEntry | undefined)[]> {
|
|
37
|
+
const { abortSignal, ...rpcConfig } = config ?? {};
|
|
38
|
+
const { value: accounts } = await rpc.getMultipleAccounts(addresses, {
|
|
39
|
+
...rpcConfig,
|
|
40
|
+
dataSlice: POSITION_POOL_SLICE,
|
|
41
|
+
encoding: "base64",
|
|
42
|
+
}).send({ abortSignal });
|
|
43
|
+
|
|
44
|
+
return decodeAllMaybePositionPools(addresses, accounts);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const addressDecoder = getAddressDecoder();
|
|
48
|
+
|
|
49
|
+
function decodeMaybePositionPool(
|
|
50
|
+
address: Address,
|
|
51
|
+
account: (AccountInfoBase & AccountInfoWithBase64EncodedData | null),
|
|
52
|
+
): PositionPoolEntry | undefined {
|
|
53
|
+
if (!account) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const pool = addressDecoder.decode(parseBase64RpcAccount(address, account).data);
|
|
57
|
+
return { address, pool };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function decodeAllMaybePositionPools(
|
|
61
|
+
addresses: Address[],
|
|
62
|
+
accounts: (AccountInfoBase & AccountInfoWithBase64EncodedData | null)[],
|
|
63
|
+
): (PositionPoolEntry | undefined)[] {
|
|
64
|
+
return accounts.map((account, i) => {
|
|
65
|
+
const address = addresses[i];
|
|
66
|
+
return decodeMaybePositionPool(address, account);
|
|
67
|
+
});
|
|
68
|
+
}
|
package/src/events.ts
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
// `generated/types/*.ts` exactly for that reason.
|
|
7
7
|
import {
|
|
8
8
|
type Address,
|
|
9
|
+
type Commitment,
|
|
10
|
+
type createSolanaRpcSubscriptions,
|
|
9
11
|
getAddressDecoder,
|
|
10
12
|
getBase64Encoder,
|
|
11
13
|
getBooleanDecoder,
|
|
@@ -277,3 +279,78 @@ export function decodeEventsFromLogs(logs: readonly string[], programAddress: Ad
|
|
|
277
279
|
}
|
|
278
280
|
return events;
|
|
279
281
|
}
|
|
282
|
+
|
|
283
|
+
type RpcSubscriptions = ReturnType<typeof createSolanaRpcSubscriptions>;
|
|
284
|
+
|
|
285
|
+
// `address` defaults to `programAddress` (every pool the program touches); pass a pool
|
|
286
|
+
// address to scope it. `programAddress` also scopes CPI-log filtering (see decodeEventsFromLogs
|
|
287
|
+
// above), so it should match whatever cluster's program this subscription is watching —
|
|
288
|
+
// defaults to mainnet. Resolves once the subscription is active, with an unsubscribe function.
|
|
289
|
+
// Errors — from the stream itself (e.g. a dropped websocket) or thrown by `handler` — are
|
|
290
|
+
// reported to `onError` instead of rejecting an unheld promise; a `handler` throw only drops
|
|
291
|
+
// that one event, the subscription keeps running.
|
|
292
|
+
export async function onEvent(
|
|
293
|
+
rpcSubscriptions: RpcSubscriptions,
|
|
294
|
+
handler: (event: DlmmEvent) => void,
|
|
295
|
+
{
|
|
296
|
+
address,
|
|
297
|
+
programAddress = PICON_DLMM_PROGRAM_ADDRESS,
|
|
298
|
+
commitment,
|
|
299
|
+
onError,
|
|
300
|
+
}: { address?: Address, programAddress?: Address, commitment?: Commitment, onError?: (error: unknown) => void } = {},
|
|
301
|
+
): Promise<() => void> {
|
|
302
|
+
const abortController = new AbortController();
|
|
303
|
+
const eventStream = await subscribeToEvents(rpcSubscriptions, {
|
|
304
|
+
address: address ?? programAddress,
|
|
305
|
+
programAddress,
|
|
306
|
+
commitment,
|
|
307
|
+
abortSignal: abortController.signal,
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
(async () => {
|
|
311
|
+
try {
|
|
312
|
+
for await (const event of eventStream) {
|
|
313
|
+
try {
|
|
314
|
+
handler(event);
|
|
315
|
+
} catch (error) {
|
|
316
|
+
onError?.(error);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
} catch (error) {
|
|
320
|
+
if (!abortController.signal.aborted) {
|
|
321
|
+
onError?.(error);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
})();
|
|
325
|
+
|
|
326
|
+
return () => abortController.abort();
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Resolves once the subscription is active, so callers know they won't miss anything.
|
|
330
|
+
async function subscribeToEvents(
|
|
331
|
+
rpcSubscriptions: RpcSubscriptions,
|
|
332
|
+
{
|
|
333
|
+
address,
|
|
334
|
+
programAddress,
|
|
335
|
+
commitment = "confirmed",
|
|
336
|
+
abortSignal,
|
|
337
|
+
}: {
|
|
338
|
+
address: Address,
|
|
339
|
+
programAddress: Address,
|
|
340
|
+
commitment?: Commitment,
|
|
341
|
+
abortSignal: AbortSignal,
|
|
342
|
+
},
|
|
343
|
+
): Promise<AsyncIterable<DlmmEvent>> {
|
|
344
|
+
const notifications = await rpcSubscriptions
|
|
345
|
+
.logsNotifications({ mentions: [address] }, { commitment })
|
|
346
|
+
.subscribe({ abortSignal });
|
|
347
|
+
|
|
348
|
+
return (async function* () {
|
|
349
|
+
for await (const notification of notifications) {
|
|
350
|
+
if (notification.value.err != null) {
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
yield* decodeEventsFromLogs(notification.value.logs, programAddress);
|
|
354
|
+
}
|
|
355
|
+
})();
|
|
356
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export * as generated from "./generated";
|
|
2
2
|
export { DistributionMode } from "./generated/types/distributionMode";
|
|
3
3
|
export * as events from "./events";
|
|
4
|
+
export * from "./entities";
|
|
4
5
|
export * from "./utils/constants";
|
|
5
6
|
export { NATIVE_MINT_ADDRESS } from "./utils/ata";
|
|
6
|
-
export
|
|
7
|
+
export type { QuoteInput, QuoteOutput, PoolState, TransferFee } from "./quote";
|
|
7
8
|
export * from "./program_addresses";
|
package/src/program_addresses.ts
CHANGED
|
@@ -1,10 +1,4 @@
|
|
|
1
1
|
import { type Address } from "@solana/kit";
|
|
2
2
|
|
|
3
|
-
// SDK codegen always targets the mainnet IDL (see package.json's `copy-idl`), so this is the
|
|
4
|
-
// same value as `generated.PICON_DLMM_PROGRAM_ADDRESS` — exported under a clearer name here
|
|
5
|
-
// since it's meant to be read standalone, not discovered via the generated namespace.
|
|
6
3
|
export { PICON_DLMM_PROGRAM_ADDRESS as MAINNET_PROGRAM_ADDRESS } from "./generated";
|
|
7
|
-
|
|
8
|
-
// Not baked into codegen (the IDL's structure is identical across clusters — only the address
|
|
9
|
-
// differs) — pass this as the `programAddress` argument on any SDK action to target devnet.
|
|
10
4
|
export const DEVNET_PROGRAM_ADDRESS = "tDLMMKoxBt7UkZapYHsEgLGydmFvSQXh5mGzrRovoeM" as Address;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Address } from "@solana/kit";
|
|
2
|
+
|
|
3
|
+
import type { BinIdRange } from "./bin_location";
|
|
4
|
+
|
|
5
|
+
export function assertRangeWithinRange(
|
|
6
|
+
inner: BinIdRange,
|
|
7
|
+
outer: BinIdRange,
|
|
8
|
+
): void {
|
|
9
|
+
if (inner.lowerBinId < outer.lowerBinId || inner.upperBinId > outer.upperBinId) {
|
|
10
|
+
throw new RangeError(
|
|
11
|
+
`Range (${inner.lowerBinId} to ${inner.upperBinId}) must be inside range (${outer.lowerBinId} to ${outer.upperBinId})`,
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function assertPositionBelongsToPool(
|
|
17
|
+
position: { pool: Address },
|
|
18
|
+
pool: { address: Address },
|
|
19
|
+
): void {
|
|
20
|
+
if (position.pool !== pool.address) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
`Position's pool (${position.pool}) does not match expected pool (${pool.address})`,
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { BINS_PER_BIN_ARRAY } from "./constants";
|
|
2
2
|
|
|
3
|
+
export type BinIdRange = {
|
|
4
|
+
lowerBinId: number,
|
|
5
|
+
upperBinId: number,
|
|
6
|
+
};
|
|
7
|
+
|
|
3
8
|
export function getBinArrayIndex(binId: number): number {
|
|
4
9
|
return Math.floor(binId / BINS_PER_BIN_ARRAY);
|
|
5
10
|
}
|
|
@@ -22,10 +27,6 @@ export function getBinArrayIndexSequence(
|
|
|
22
27
|
);
|
|
23
28
|
}
|
|
24
29
|
|
|
25
|
-
// A position spans at most MAX_BIN_ARRAYS_PER_POSITION (2) bin arrays — the lower and
|
|
26
|
-
// (only if distinct) upper one covering its range. Shared by every position-scoped
|
|
27
|
-
// instruction that needs to enumerate exactly those arrays (open_position's bin-array
|
|
28
|
-
// bootstrap, withdraw/claim_fee's account derivation).
|
|
29
30
|
export function getPositionBinArrayIndices(
|
|
30
31
|
lowerBinId: number,
|
|
31
32
|
upperBinId: number,
|
|
@@ -37,9 +38,6 @@ export function getPositionBinArrayIndices(
|
|
|
37
38
|
: { lowerBinArrayIndex, upperBinArrayIndex };
|
|
38
39
|
}
|
|
39
40
|
|
|
40
|
-
// One bin array of margin is kept on the opposite side of travel: if the live active bin
|
|
41
|
-
// drifts one array against the expected direction between quote time and execution (e.g. a
|
|
42
|
-
// competing swap lands first), it's still covered by this range instead of reverting.
|
|
43
41
|
export function generateBinArrayIndicesForSwap(
|
|
44
42
|
activeBinId: number,
|
|
45
43
|
xToY: boolean,
|
|
@@ -52,11 +50,6 @@ export function generateBinArrayIndicesForSwap(
|
|
|
52
50
|
return getBinArrayIndexSequence(lowerBinArrayIndex, upperBinArrayIndex);
|
|
53
51
|
}
|
|
54
52
|
|
|
55
|
-
// Spans from the live `activeBinId` to the caller's exact `desiredBinId` target, plus one
|
|
56
|
-
// bin array of margin beyond the active end (the side subject to drift — `desiredBinId` is
|
|
57
|
-
// a fixed target, but the live active bin could move further away from it before this tx
|
|
58
|
-
// lands). Capped at `maxBinArrays`, trimming from the `desiredBinId` end so the active+margin
|
|
59
|
-
// anchor stays intact — a sync toward a distant target simply converges partially in that case.
|
|
60
53
|
export function generateBinArrayIndicesForSync(
|
|
61
54
|
activeBinId: number,
|
|
62
55
|
desiredBinId: number,
|