@exponent-labs/exponent-sdk 0.1.7 → 0.1.8

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 (92) hide show
  1. package/build/EventDecoderV2.d.ts +31 -0
  2. package/build/EventDecoderV2.js +76 -0
  3. package/build/EventDecoderV2.js.map +1 -0
  4. package/build/addressLookupTableUtil.d.ts +17 -1
  5. package/build/addressLookupTableUtil.js +35 -1
  6. package/build/addressLookupTableUtil.js.map +1 -1
  7. package/build/clmm/events.d.ts +10 -0
  8. package/build/clmm/events.js +10 -0
  9. package/build/clmm/events.js.map +1 -0
  10. package/build/clmm/index.d.ts +1 -0
  11. package/build/clmm/index.js +18 -0
  12. package/build/clmm/index.js.map +1 -0
  13. package/build/events.d.ts +200 -9
  14. package/build/events.js +73 -24
  15. package/build/events.js.map +1 -1
  16. package/build/eventsV2.d.ts +7 -0
  17. package/build/eventsV2.js +10 -0
  18. package/build/eventsV2.js.map +1 -0
  19. package/build/flavors.d.ts +2 -0
  20. package/build/flavors.js +81 -27
  21. package/build/flavors.js.map +1 -1
  22. package/build/index.d.ts +6 -0
  23. package/build/index.js +14 -4
  24. package/build/index.js.map +1 -1
  25. package/build/lpPosition.js +4 -1
  26. package/build/lpPosition.js.map +1 -1
  27. package/build/market.d.ts +14 -2
  28. package/build/market.js +70 -29
  29. package/build/market.js.map +1 -1
  30. package/build/marketThree.d.ts +664 -0
  31. package/build/marketThree.js +1415 -0
  32. package/build/marketThree.js.map +1 -0
  33. package/build/marketThree.test.d.ts +1 -0
  34. package/build/marketThree.test.js +166 -0
  35. package/build/marketThree.test.js.map +1 -0
  36. package/build/orderbook/events.d.ts +7 -0
  37. package/build/orderbook/events.js +10 -0
  38. package/build/orderbook/events.js.map +1 -0
  39. package/build/orderbook/index.d.ts +4 -0
  40. package/build/orderbook/index.js +41 -0
  41. package/build/orderbook/index.js.map +1 -0
  42. package/build/orderbook/math.d.ts +26 -0
  43. package/build/orderbook/math.js +111 -0
  44. package/build/orderbook/math.js.map +1 -0
  45. package/build/orderbook/orderbook.d.ts +175 -0
  46. package/build/orderbook/orderbook.js +756 -0
  47. package/build/orderbook/orderbook.js.map +1 -0
  48. package/build/orderbook/types.d.ts +49 -0
  49. package/build/orderbook/types.js +27 -0
  50. package/build/orderbook/types.js.map +1 -0
  51. package/build/orderbook/utils.d.ts +18 -0
  52. package/build/orderbook/utils.js +74 -0
  53. package/build/orderbook/utils.js.map +1 -0
  54. package/build/router.d.ts +92 -0
  55. package/build/router.js +214 -0
  56. package/build/router.js.map +1 -0
  57. package/build/syPosition.js +6 -0
  58. package/build/syPosition.js.map +1 -1
  59. package/build/utils/index.d.ts +3 -2
  60. package/build/utils/index.js +22 -1
  61. package/build/utils/index.js.map +1 -1
  62. package/build/vault.d.ts +3 -1
  63. package/build/vault.js +98 -62
  64. package/build/vault.js.map +1 -1
  65. package/build/ytPosition.d.ts +2 -0
  66. package/build/ytPosition.js +18 -5
  67. package/build/ytPosition.js.map +1 -1
  68. package/package.json +28 -23
  69. package/src/EventDecoderV2.ts +96 -0
  70. package/src/addressLookupTableUtil.ts +42 -1
  71. package/src/clmm/events.ts +17 -0
  72. package/src/clmm/index.ts +1 -0
  73. package/src/events.ts +280 -27
  74. package/src/eventsV2.ts +13 -0
  75. package/src/flavors.ts +97 -27
  76. package/src/index.ts +6 -0
  77. package/src/lpPosition.ts +5 -2
  78. package/src/market.ts +100 -31
  79. package/src/marketThree.test.ts +208 -0
  80. package/src/marketThree.ts +2430 -0
  81. package/src/orderbook/events.ts +13 -0
  82. package/src/orderbook/index.ts +12 -0
  83. package/src/orderbook/math.ts +122 -0
  84. package/src/orderbook/orderbook.ts +1153 -0
  85. package/src/orderbook/types.ts +45 -0
  86. package/src/orderbook/utils.ts +74 -0
  87. package/src/router.ts +360 -0
  88. package/src/syPosition.ts +4 -0
  89. package/src/utils/index.ts +27 -2
  90. package/src/vault.ts +100 -62
  91. package/src/ytPosition.ts +28 -7
  92. package/tsconfig.json +4 -1
@@ -0,0 +1,1415 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MarketThree = void 0;
7
+ const anchor_1 = require("@coral-xyz/anchor");
8
+ const spl_token_1 = require("@solana/spl-token");
9
+ const decimal_js_1 = __importDefault(require("decimal.js"));
10
+ const exponent_clmm_idl_1 = require("@exponent-labs/exponent-clmm-idl");
11
+ const exponent_clmm_pda_1 = require("@exponent-labs/exponent-clmm-pda");
12
+ const exponent_fetcher_1 = require("@exponent-labs/exponent-fetcher");
13
+ const exponent_idl_1 = require("@exponent-labs/exponent-idl");
14
+ const exponent_pda_1 = require("@exponent-labs/exponent-pda");
15
+ const market_three_math_1 = require("@exponent-labs/market-three-math");
16
+ const addressLookupTableUtil_1 = require("./addressLookupTableUtil");
17
+ const flavors_1 = require("./flavors");
18
+ const market_1 = require("./market");
19
+ const syPosition_1 = require("./syPosition");
20
+ const utils_1 = require("./utils");
21
+ const vault_1 = require("./vault");
22
+ const SECONDS_PER_YEAR = 365 * 24 * 60 * 60;
23
+ class MarketThree {
24
+ state;
25
+ selfAddress;
26
+ env;
27
+ connection;
28
+ clmmProgram;
29
+ coreProgram;
30
+ xponPda;
31
+ pda;
32
+ constructor(state, selfAddress, env, connection) {
33
+ this.state = state;
34
+ this.selfAddress = selfAddress;
35
+ this.env = env;
36
+ this.connection = connection;
37
+ this.xponPda = new exponent_pda_1.ExponentPDA(env.coreProgramId);
38
+ this.pda = new exponent_clmm_pda_1.ExponentCLMMPDA();
39
+ const mockWallet = new market_1.MyWallet(anchor_1.web3.Keypair.generate());
40
+ this.clmmProgram = new anchor_1.Program(exponent_clmm_idl_1.IDL, new anchor_1.AnchorProvider(connection, mockWallet));
41
+ this.coreProgram = new anchor_1.Program(exponent_idl_1.IDL, new anchor_1.AnchorProvider(connection, new market_1.MyWallet(anchor_1.web3.Keypair.generate())));
42
+ }
43
+ static async load(env, connection, address, vault, ticks, options = {}) {
44
+ const fetcher = new exponent_fetcher_1.ExponentFetcher({ connection });
45
+ const fetchedMarket = await fetcher.fetchMarketThree(address);
46
+ const [alt, loadedVault, loadedTicks] = await Promise.all([
47
+ (0, addressLookupTableUtil_1.fetchAddressLookupTable)(connection, fetchedMarket.addressLookupTable),
48
+ vault || vault_1.Vault.load(env, connection, fetchedMarket.vault, options),
49
+ ticks || fetcher.fetchMarketThreeTicks(fetchedMarket.ticks),
50
+ ]);
51
+ const cpiSyAccounts = (0, addressLookupTableUtil_1.makeCpiAccountMetaLists)(alt, fetchedMarket.cpiSyAccounts);
52
+ const cpiCoreAccounts = (0, addressLookupTableUtil_1.makeMarketCoreCpiAccountMetaLists)(alt, fetchedMarket.cpiCoreAccounts);
53
+ const flavor = (() => {
54
+ switch (loadedVault.flavor.flavor) {
55
+ case "marginfi":
56
+ return (0, flavors_1.makeFlavorMarginfiSync)(loadedVault.flavor);
57
+ case "kamino":
58
+ return (0, flavors_1.makeFlavorKaminoSync)(loadedVault.flavor);
59
+ case "jitoRestaking":
60
+ return (0, flavors_1.makeFlavorJitoRestakingSync)(loadedVault.flavor);
61
+ case "perena":
62
+ return (0, flavors_1.makeFlavorPerenaSync)(loadedVault.flavor);
63
+ case "generic":
64
+ return (0, flavors_1.makeFlavorGenericSync)(loadedVault.flavor, options.syConfig);
65
+ default:
66
+ throw new Error(`Unknown flavor: ${loadedVault.flavor}`);
67
+ }
68
+ })();
69
+ const syPosition = await (0, syPosition_1.makeSyPosition)(fetcher, flavor, fetchedMarket.syProgram, address);
70
+ //? Assuming that the owner is the same for both accounts feeAccounts
71
+ const treasuryFeeOwner = await MarketThree.fetchTreasuryFeeOwner(fetchedMarket.tokenFeeTreasuryPt, connection);
72
+ const state = {
73
+ ...fetchedMarket,
74
+ vault: loadedVault,
75
+ flavor,
76
+ ticks: loadedTicks,
77
+ syPosition,
78
+ cpiSyAccounts,
79
+ cpiCoreAccounts,
80
+ ticksAccount: fetchedMarket.ticks,
81
+ treasuryFeeOwner,
82
+ };
83
+ return new MarketThree(state, address, env, connection);
84
+ }
85
+ async reload(connection = this.connection) {
86
+ const market = await MarketThree.load(this.env, connection, this.selfAddress);
87
+ this.state = market.state;
88
+ return market;
89
+ }
90
+ get vault() {
91
+ return this.state.vault;
92
+ }
93
+ get flavor() {
94
+ return this.state.flavor;
95
+ }
96
+ get lpBalance() {
97
+ return this.state.financials.liquidityBalance;
98
+ }
99
+ get syBalance() {
100
+ return this.state.financials.syBalance;
101
+ }
102
+ get ptBalance() {
103
+ return this.state.financials.ptBalance;
104
+ }
105
+ get mintSy() {
106
+ return this.state.mintSy;
107
+ }
108
+ get mintPt() {
109
+ return this.state.mintPt;
110
+ }
111
+ get statusFlags() {
112
+ return this.state.statusFlags;
113
+ }
114
+ get mintYt() {
115
+ return this.state.mintYt;
116
+ }
117
+ get addressLookupTable() {
118
+ return this.state.addressLookupTable;
119
+ }
120
+ get syProgram() {
121
+ return this.state.syProgram;
122
+ }
123
+ get cpiSyAccounts() {
124
+ return this.state.cpiSyAccounts;
125
+ }
126
+ get cpiCoreAccounts() {
127
+ return this.state.cpiCoreAccounts;
128
+ }
129
+ get marketEmissions() {
130
+ return this.state.emissions;
131
+ }
132
+ get ticksKey() {
133
+ return this.state.ticksAccount;
134
+ }
135
+ get corePda() {
136
+ return new exponent_pda_1.ExponentPDA();
137
+ }
138
+ get coreEventAuthority() {
139
+ return (0, utils_1.emitEventAuthority)(this.state.exponentCoreProgram);
140
+ }
141
+ get emissions() {
142
+ if (this.flavor.flavor === "marginfi") {
143
+ return this.flavor.mfiSyState.account.emissions.map((e) => ({
144
+ escrowAccountAddress: e.escrowAccount,
145
+ mint: e.mint,
146
+ tokenProgramAddress: e.tokenProgram,
147
+ totalClaimed: BigInt(e.totalClaimedEmissions.toString()),
148
+ lastSeenTotalAccruedEmissions: BigInt(e.lastSeenTotalAccruedEmissions.toString()),
149
+ index: e.index,
150
+ }));
151
+ }
152
+ if (this.flavor.flavor === "kamino") {
153
+ return this.flavor.kaminoSyState.account.emissions.map((e) => ({
154
+ escrowAccountAddress: e.escrowAccount,
155
+ mint: e.mint,
156
+ tokenProgramAddress: e.tokenProgram,
157
+ totalClaimed: BigInt(e.totalClaimedEmissions.toString()),
158
+ lastSeenTotalAccruedEmissions: BigInt(e.lastSeenTotalAccruedEmissions.toString()),
159
+ index: e.index,
160
+ }));
161
+ }
162
+ if (this.flavor.flavor === "jitoRestaking") {
163
+ return this.flavor.jitoSyState.account.emissions.map((e) => ({
164
+ escrowAccountAddress: e.escrowAccount,
165
+ mint: e.mint,
166
+ tokenProgramAddress: e.tokenProgram,
167
+ totalClaimed: BigInt(e.totalClaimedEmissions.toString()),
168
+ lastSeenTotalAccruedEmissions: BigInt(e.lastSeenTotalAccruedEmissions.toString()),
169
+ index: e.index,
170
+ }));
171
+ }
172
+ if (this.flavor.flavor === "perena") {
173
+ return this.flavor.perenaSyState.account.emissions.map((e) => ({
174
+ escrowAccountAddress: e.escrowAccount,
175
+ mint: e.mint,
176
+ tokenProgramAddress: e.tokenProgram,
177
+ totalClaimed: BigInt(e.totalClaimedEmissions.toString()),
178
+ lastSeenTotalAccruedEmissions: BigInt(e.lastSeenTotalAccruedEmissions.toString()),
179
+ index: e.index,
180
+ }));
181
+ }
182
+ if (this.flavor.flavor === "generic") {
183
+ return this.flavor.genericSyState.account.emissions.map((e) => ({
184
+ escrowAccountAddress: e.escrowAccount,
185
+ mint: e.mint,
186
+ tokenProgramAddress: e.tokenProgram,
187
+ totalClaimed: BigInt(e.totalClaimedEmissions.toString()),
188
+ lastSeenTotalAccruedEmissions: BigInt(e.lastSeenTotalAccruedEmissions.toString()),
189
+ index: e.index,
190
+ }));
191
+ }
192
+ throw new Error("Unknown flavor");
193
+ }
194
+ /** Get the escrow token account addresses for the emissions, in order */
195
+ get emissionTokenAccounts() {
196
+ return this.emissions.map((e) => e.escrowAccountAddress);
197
+ }
198
+ /** Pass-through SY account owned by the market */
199
+ get tokenSyEscrow() {
200
+ return this.state.tokenSyEscrow;
201
+ }
202
+ /** Pass-through YT account owned by the market */
203
+ get tokenYtEscrow() {
204
+ return this.state.tokenYtEscrow;
205
+ }
206
+ /** SY account that holds treasury SY fees from PT trading */
207
+ get tokenFeeTreasurySy() {
208
+ return this.state.tokenFeeTreasurySy;
209
+ }
210
+ /** PT account that holds treasury PT fees from PT trading */
211
+ get tokenFeeTreasuryPt() {
212
+ return this.state.tokenFeeTreasuryPt;
213
+ }
214
+ /** Market liquidity for PT */
215
+ get tokenPtEscrow() {
216
+ return this.state.tokenPtEscrow;
217
+ }
218
+ get currentSyExchangeRate() {
219
+ return this.flavor.currentSyExchangeRate;
220
+ }
221
+ /** Special account for event emit self-cpi */
222
+ get eventAuthority() {
223
+ return (0, utils_1.emitEventAuthority)(this.clmmProgram.programId);
224
+ }
225
+ get secondsRemaining() {
226
+ const timeNow = Date.now() / 1000;
227
+ return Math.max(0, Math.round(Number(this.state.financials.expirationTs) - timeNow));
228
+ }
229
+ /** Annualize a rate given the number of seconds remaining until maturity */
230
+ static annualize(rate, secondsRemaining) {
231
+ return (rate * SECONDS_PER_YEAR) / secondsRemaining;
232
+ }
233
+ static annualizeApy(rate, secondsRemaining) {
234
+ return (1 + rate) ** (SECONDS_PER_YEAR / secondsRemaining) - 1;
235
+ }
236
+ /** The fee rate taken off of trade fees (typically around 20%) expressed as a BPS number */
237
+ get feeTreasuryBps() {
238
+ return this.state.configurationOptions.treasuryFeeBps;
239
+ }
240
+ /** The fee rate taken off of trade fees (typically around 20%) expressed as a rational number */
241
+ get feeTreasuryRate() {
242
+ return this.feeTreasuryBps / 10_000;
243
+ }
244
+ /** Get the owner of the treasury fee accounts: tokenFeeTreasuryPt & tokenFeeTreasurySy */
245
+ static async fetchTreasuryFeeOwner(tokenFeeTreasury, connection) {
246
+ const { owner } = await (0, spl_token_1.getAccount)(connection, tokenFeeTreasury);
247
+ return owner;
248
+ }
249
+ /** Deposit a pair of tokens as liquidity to the market
250
+ * Adds PT & SY from the `depositor` to the market
251
+ *
252
+ * Due to unforeseeable slippage, the PT & SY amounts intended are effectively the maximum amounts
253
+ * The minimum LP tokens to receive is specified by `minLpOut`
254
+ *
255
+ * The token accounts themselves are optional, and will be derived from the depositor's wallet if not provided
256
+ */
257
+ async ixDepositLiquidity({ ptInIntent, syInIntent, depositor, lowerTickKey, upperTickKey, ptSrc: ptSrcParam, sySrc: sySrcParam, lpPosition: lpPositionParam, }) {
258
+ const tokenProgram = spl_token_1.TOKEN_PROGRAM_ID;
259
+ const sySrc = sySrcParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, depositor, true, spl_token_1.TOKEN_PROGRAM_ID);
260
+ const ptSrc = ptSrcParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, depositor, true, spl_token_1.TOKEN_PROGRAM_ID);
261
+ const lpPosition = lpPositionParam || anchor_1.web3.Keypair.generate();
262
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
263
+ ...this.cpiSyAccounts.depositSy,
264
+ ...this.cpiSyAccounts.getPositionState,
265
+ ]);
266
+ const ix = await this.clmmProgram.methods
267
+ .depositLiquidity(convertApyToApyBp(lowerTickKey), convertApyToApyBp(upperTickKey), new anchor_1.BN(ptInIntent.toString()), new anchor_1.BN(syInIntent.toString()))
268
+ .accountsStrict({
269
+ depositor,
270
+ market: this.selfAddress,
271
+ tokenPtSrc: ptSrc,
272
+ tokenSySrc: sySrc,
273
+ tokenPtEscrow: this.tokenPtEscrow,
274
+ tokenSyEscrow: this.tokenSyEscrow,
275
+ addressLookupTable: this.addressLookupTable,
276
+ syProgram: this.syProgram,
277
+ tokenProgram,
278
+ eventAuthority: this.eventAuthority,
279
+ program: this.clmmProgram.programId,
280
+ lpPosition: lpPosition.publicKey,
281
+ ticks: this.ticksKey,
282
+ systemProgram: anchor_1.web3.SystemProgram.programId,
283
+ })
284
+ .remainingAccounts(remainingAccounts)
285
+ .instruction();
286
+ return {
287
+ ix: ix,
288
+ signers: lpPosition,
289
+ };
290
+ }
291
+ /**
292
+ * Redeem LP tokens for PT & SY (liquidity removal)
293
+ *
294
+ * The lpIn is exactly the amount of LP tokens to burn
295
+ * The minimum PT & SY out are specified by minPtOut & minSyOut
296
+ * The transaction may fail due to unforeseeable slippage on the redemption rate
297
+ *
298
+ * The token accounts themselves are optional, and will be derived from the withdrawer's wallet if not provided
299
+ */
300
+ async ixWithdrawLiquidity({ lpIn, withdrawer, lpPosition, minPtOut, minSyOut, ptDst: ptDstParam, syDst: syDstParam, }) {
301
+ const ptDst = ptDstParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, withdrawer, true, spl_token_1.TOKEN_PROGRAM_ID);
302
+ const syDst = syDstParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, withdrawer, true, spl_token_1.TOKEN_PROGRAM_ID);
303
+ const ptDstAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(withdrawer, ptDst, withdrawer, this.mintPt);
304
+ const syDstAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(withdrawer, syDst, withdrawer, this.mintSy);
305
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
306
+ ...this.cpiSyAccounts.withdrawSy,
307
+ ...this.cpiSyAccounts.getPositionState,
308
+ ]);
309
+ const ixs = await this.clmmProgram.methods
310
+ .withdrawLiquidity(new anchor_1.BN(lpIn.toString()), new anchor_1.BN(minPtOut.toString()), new anchor_1.BN(minSyOut.toString()))
311
+ .accountsStrict({
312
+ owner: withdrawer,
313
+ market: this.selfAddress,
314
+ tokenPtDst: ptDst,
315
+ tokenSyDst: syDst,
316
+ tokenPtEscrow: this.tokenPtEscrow,
317
+ tokenSyEscrow: this.tokenSyEscrow,
318
+ addressLookupTable: this.addressLookupTable,
319
+ syProgram: this.syProgram,
320
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
321
+ eventAuthority: this.eventAuthority,
322
+ program: this.clmmProgram.programId,
323
+ systemProgram: anchor_1.web3.SystemProgram.programId,
324
+ lpPosition,
325
+ ticks: this.ticksKey,
326
+ })
327
+ .remainingAccounts(remainingAccounts)
328
+ .instruction();
329
+ return { ixs: [ixs], setupIxs: [ptDstAtaIx, syDstAtaIx] };
330
+ }
331
+ async ixTradePt({ trader, traderAmount, outConstraint, swapDirection, tokenPt: tokenPtParam, tokenSy: tokenSyParam, lnImpliedApyLimit, }) {
332
+ const tokenPt = tokenPtParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, trader, true, spl_token_1.TOKEN_PROGRAM_ID);
333
+ const tokenSy = tokenSyParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, trader, true, spl_token_1.TOKEN_PROGRAM_ID);
334
+ const tokenSyAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(trader, tokenSy, trader, this.mintSy);
335
+ const tokenPtAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(trader, tokenPt, trader, this.mintPt);
336
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
337
+ ...this.cpiSyAccounts.getSyState,
338
+ ...this.cpiSyAccounts.getPositionState,
339
+ ...this.cpiSyAccounts.depositSy,
340
+ ...this.cpiSyAccounts.withdrawSy,
341
+ ]);
342
+ let outConstraintOptional = outConstraint ? new anchor_1.BN(outConstraint.toString()) : null;
343
+ let lnImpliedApyLimitOptional = lnImpliedApyLimit ? lnImpliedApyLimit : null;
344
+ const ix = await this.clmmProgram.methods
345
+ .tradePt(new anchor_1.BN(traderAmount.toString()), swapDirection, outConstraintOptional, lnImpliedApyLimitOptional)
346
+ .accountsStrict({
347
+ trader,
348
+ market: this.selfAddress,
349
+ tokenPtTrader: tokenPt,
350
+ tokenSyTrader: tokenSy,
351
+ tokenSyEscrow: this.tokenSyEscrow,
352
+ tokenPtEscrow: this.tokenPtEscrow,
353
+ addressLookupTable: this.addressLookupTable,
354
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
355
+ syProgram: this.syProgram,
356
+ tokenFeeTreasurySy: this.tokenFeeTreasurySy,
357
+ eventAuthority: this.eventAuthority,
358
+ program: this.clmmProgram.programId,
359
+ tokenFeeTreasuryPt: this.tokenFeeTreasuryPt,
360
+ ticks: this.ticksKey,
361
+ })
362
+ .remainingAccounts(remainingAccounts)
363
+ .instruction();
364
+ return { ixs: [ix], setupIxs: [tokenPtAtaIx, tokenSyAtaIx] };
365
+ }
366
+ async ixTradePtExactOut({ trader, amountOut, swapDirection, amountInConstraint, tokenPt: tokenPtParam, tokenSy: tokenSyParam, lnImpliedApyLimit, }) {
367
+ const tokenPt = tokenPtParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, trader, true, spl_token_1.TOKEN_PROGRAM_ID);
368
+ const tokenSy = tokenSyParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, trader, true, spl_token_1.TOKEN_PROGRAM_ID);
369
+ const tokenSyAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(trader, tokenSy, trader, this.mintSy);
370
+ const tokenPtAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(trader, tokenPt, trader, this.mintPt);
371
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
372
+ ...this.cpiSyAccounts.getSyState,
373
+ ...this.cpiSyAccounts.getPositionState,
374
+ ...this.cpiSyAccounts.depositSy,
375
+ ...this.cpiSyAccounts.withdrawSy,
376
+ ]);
377
+ const amountInConstraintOptional = amountInConstraint !== undefined ? new anchor_1.BN(amountInConstraint.toString()) : null;
378
+ const lnImpliedApyLimitOptional = lnImpliedApyLimit ? lnImpliedApyLimit : null;
379
+ const ix = await this.clmmProgram.methods
380
+ .tradePtExactOut(new anchor_1.BN(amountOut.toString()), swapDirection, amountInConstraintOptional, lnImpliedApyLimitOptional)
381
+ .accountsStrict({
382
+ trader,
383
+ market: this.selfAddress,
384
+ tokenPtTrader: tokenPt,
385
+ tokenSyTrader: tokenSy,
386
+ tokenSyEscrow: this.tokenSyEscrow,
387
+ tokenPtEscrow: this.tokenPtEscrow,
388
+ addressLookupTable: this.addressLookupTable,
389
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
390
+ syProgram: this.syProgram,
391
+ tokenFeeTreasurySy: this.tokenFeeTreasurySy,
392
+ eventAuthority: this.eventAuthority,
393
+ program: this.clmmProgram.programId,
394
+ tokenFeeTreasuryPt: this.tokenFeeTreasuryPt,
395
+ ticks: this.ticksKey,
396
+ })
397
+ .remainingAccounts(remainingAccounts)
398
+ .instruction();
399
+ return { ixs: [ix], setupIxs: [tokenPtAtaIx, tokenSyAtaIx] };
400
+ }
401
+ /** Buy PT with SY
402
+ *
403
+ * The trader is the account that sends the SY
404
+ * The amountPt is the exact amount of PT the trader intends to buy
405
+ * The syConstraint is the maximum amount of SY the trader is willing to spend
406
+ *
407
+ * The token accounts themselves are optional, and will be derived from the trader's wallet if not provided
408
+ */
409
+ async ixBuyPt({ trader, amountSy, outConstraint, tokenPt, tokenSy, lnImpliedApyLimit, }) {
410
+ return this.ixTradePt({
411
+ trader,
412
+ traderAmount: amountSy,
413
+ outConstraint: outConstraint,
414
+ swapDirection: { syToPt: {} },
415
+ tokenPt,
416
+ tokenSy,
417
+ lnImpliedApyLimit,
418
+ });
419
+ }
420
+ /**
421
+ * Sell PT for SY
422
+ * The trader is the account that sends the PT
423
+ * The amountPt is the exact amount of PT the trader intends to sell
424
+ * The minSyReceive is the minimum amount of SY the trader is willing to receive
425
+ *
426
+ * The token accounts themselves are optional, and will be derived from the trader's wallet if not provided
427
+ */
428
+ async ixSellPt({ trader, amountPt, outConstraint, tokenPt, tokenSy, lnImpliedApyLimit, }) {
429
+ return this.ixTradePt({
430
+ trader,
431
+ traderAmount: amountPt,
432
+ outConstraint: outConstraint,
433
+ swapDirection: { ptToSy: {} },
434
+ tokenPt,
435
+ tokenSy,
436
+ lnImpliedApyLimit,
437
+ });
438
+ }
439
+ /**
440
+ * Buy exact amount of PT with SY
441
+ *
442
+ * The trader specifies the exact amount of PT they want to receive
443
+ * The maxSyIn is the maximum amount of SY the trader is willing to spend
444
+ */
445
+ async ixBuyPtExactOut({ trader, amountPt, maxSyIn, tokenPt, tokenSy, lnImpliedApyLimit, }) {
446
+ return this.ixTradePtExactOut({
447
+ trader,
448
+ amountOut: amountPt,
449
+ amountInConstraint: maxSyIn,
450
+ swapDirection: { syToPt: {} },
451
+ tokenPt,
452
+ tokenSy,
453
+ lnImpliedApyLimit,
454
+ });
455
+ }
456
+ /**
457
+ * Sell PT for exact amount of SY
458
+ *
459
+ * The trader specifies the exact amount of SY they want to receive
460
+ * The maxPtIn is the maximum amount of PT the trader is willing to spend
461
+ */
462
+ async ixSellPtExactOut({ trader, amountSy, maxPtIn, tokenPt, tokenSy, lnImpliedApyLimit, }) {
463
+ return this.ixTradePtExactOut({
464
+ trader,
465
+ amountOut: amountSy,
466
+ amountInConstraint: maxPtIn,
467
+ swapDirection: { ptToSy: {} },
468
+ tokenPt,
469
+ tokenSy,
470
+ lnImpliedApyLimit,
471
+ });
472
+ }
473
+ /** Buy YT with SY
474
+ *
475
+ * The trader is the account that sends the SY
476
+ *
477
+ * The ytOut is the exact amount of YT the trader intends to buy
478
+ *
479
+ * The maxSyIn is the maximum amount of SY the trader is willing to spend
480
+ *
481
+ * The token accounts themselves are optional, and will be derived from the trader's wallet if not provided
482
+ */
483
+ async ixBuyYt({ trader, ytOut, maxSyIn, ytTrader: ytTraderParam, ptTrader: ptTraderParam, syTrader: syTraderParam, lnImpliedApyLimit, }) {
484
+ const syTrader = syTraderParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, trader, true, spl_token_1.TOKEN_PROGRAM_ID);
485
+ const ptTrader = ptTraderParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, trader, true, spl_token_1.TOKEN_PROGRAM_ID);
486
+ const ytTrader = ytTraderParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintYt, trader, true, spl_token_1.TOKEN_PROGRAM_ID);
487
+ const syTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(trader, syTrader, trader, this.mintSy);
488
+ const ptTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(trader, ptTrader, trader, this.mintPt);
489
+ const ytTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(trader, ytTrader, trader, this.mintYt);
490
+ const stripAccounts = this.cpiCoreAccounts.stripSy;
491
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
492
+ ...this.cpiSyAccounts.getSyState,
493
+ ...this.cpiSyAccounts.withdrawSy,
494
+ ...this.cpiSyAccounts.depositSy,
495
+ ...stripAccounts,
496
+ ]);
497
+ let lnImpliedApyLimitOptional = lnImpliedApyLimit ? lnImpliedApyLimit : null;
498
+ const ix = await this.clmmProgram.methods
499
+ .buyYt(new anchor_1.BN(maxSyIn.toString()), new anchor_1.BN(ytOut.toString()), lnImpliedApyLimitOptional)
500
+ .accountsStrict({
501
+ trader,
502
+ market: this.selfAddress,
503
+ tokenYtTrader: ytTrader,
504
+ tokenPtTrader: ptTrader,
505
+ tokenSyTrader: syTrader,
506
+ tokenSyEscrow: this.tokenSyEscrow,
507
+ tokenPtEscrow: this.tokenPtEscrow,
508
+ addressLookupTable: this.addressLookupTable,
509
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
510
+ syProgram: this.syProgram,
511
+ tokenFeeTreasurySy: this.tokenFeeTreasurySy,
512
+ eventAuthority: this.eventAuthority,
513
+ program: this.clmmProgram.programId,
514
+ tokenFeeTreasuryPt: this.tokenFeeTreasuryPt,
515
+ ticks: this.ticksKey,
516
+ tokenYtEscrow: this.tokenYtEscrow,
517
+ exponentCoreProgram: this.state.exponentCoreProgram,
518
+ })
519
+ .remainingAccounts(remainingAccounts)
520
+ .instruction();
521
+ return { ixs: [ix], setupIxs: [syTraderAtaIx, ptTraderAtaIx, ytTraderAtaIx] };
522
+ }
523
+ /** Sell YT for SY
524
+ *
525
+ * The trader is the account that sends the YT
526
+ *
527
+ * The amountYt is the exact amount of YT the trader intends to sell
528
+ *
529
+ * The minSyOut is the minimum amount of SY the trader is willing to receive
530
+ *
531
+ * The token accounts themselves are optional, and will be derived from the trader's wallet if not provided
532
+ */
533
+ async ixSellYt({ trader, ytIn, minSyOut, ytSrc: ytSrcParam, ptSrc: ptSrcParam, syDst: syDstParam, lnImpliedApyLimit, }) {
534
+ const syDst = syDstParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, trader, true, spl_token_1.TOKEN_PROGRAM_ID);
535
+ const ptSrc = ptSrcParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, trader, true, spl_token_1.TOKEN_PROGRAM_ID);
536
+ const ytSrc = ytSrcParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintYt, trader, true, spl_token_1.TOKEN_PROGRAM_ID);
537
+ const syDstAtaIxs = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(trader, syDst, trader, this.mintSy);
538
+ const ptSrcAtaIxs = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(trader, ptSrc, trader, this.mintPt);
539
+ const ytSrcAtaIxs = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(trader, ytSrc, trader, this.mintYt);
540
+ const mergeAccounts = this.cpiCoreAccounts.mergeSy;
541
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
542
+ ...this.cpiSyAccounts.getSyState,
543
+ ...this.cpiSyAccounts.getPositionState,
544
+ ...this.cpiSyAccounts.depositSy,
545
+ ...mergeAccounts,
546
+ ]);
547
+ let lnImpliedApyLimitOptional = lnImpliedApyLimit ? lnImpliedApyLimit : null;
548
+ const ix = await this.clmmProgram.methods
549
+ .sellYt(new anchor_1.BN(ytIn.toString()), new anchor_1.BN(minSyOut.toString()), lnImpliedApyLimitOptional)
550
+ .accountsStrict({
551
+ trader,
552
+ market: this.selfAddress,
553
+ tokenYtTrader: ytSrc,
554
+ tokenPtTrader: ptSrc,
555
+ tokenSyTrader: syDst,
556
+ tokenSyEscrow: this.tokenSyEscrow,
557
+ tokenPtEscrow: this.tokenPtEscrow,
558
+ addressLookupTable: this.addressLookupTable,
559
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
560
+ syProgram: this.syProgram,
561
+ tokenFeeTreasurySy: this.tokenFeeTreasurySy,
562
+ eventAuthority: this.eventAuthority,
563
+ program: this.clmmProgram.programId,
564
+ tokenFeeTreasuryPt: this.tokenFeeTreasuryPt,
565
+ ticks: this.ticksKey,
566
+ tokenYtEscrow: this.tokenYtEscrow,
567
+ exponentCoreProgram: this.state.exponentCoreProgram,
568
+ })
569
+ .remainingAccounts(remainingAccounts)
570
+ .instruction();
571
+ return { ixs: [ix], setupIxs: [syDstAtaIxs, ptSrcAtaIxs, ytSrcAtaIxs] };
572
+ }
573
+ async ixModifyMarketSetting({ signer, adminAction }) {
574
+ return this.clmmProgram.methods
575
+ .modifyMarketSetting(adminAction)
576
+ .accountsStrict({
577
+ market: this.selfAddress,
578
+ signer,
579
+ systemProgram: anchor_1.web3.SystemProgram.programId,
580
+ })
581
+ .instruction();
582
+ }
583
+ /**
584
+ * Add a new farm to the market to distribute rewards to LP holders
585
+ *
586
+ * @param signer - The admin address that signs the transaction
587
+ * @param farmMint - The mint address of the farm reward token
588
+ * @param farmTokenProgram - The token program for the farm reward token
589
+ * @param emissionsRate - The rate of emissions per second (in token smallest units)
590
+ * @param untilTimestamp - Unix timestamp when the farm emissions should end
591
+ * @param farmTokenSrc - Optional source token account for the farm rewards (derived from signer if not provided)
592
+ * @param feePayer - Optional fee payer for account reallocation (defaults to signer)
593
+ */
594
+ async ixAddFarm({ signer, farmMint, farmTokenProgram, emissionsRate, untilTimestamp, farmTokenSrc: farmTokenSrcParam, feePayer: feePayerParam, }) {
595
+ const feePayer = feePayerParam || signer;
596
+ const farmTokenEscrow = (0, spl_token_1.getAssociatedTokenAddressSync)(farmMint, this.selfAddress, true, farmTokenProgram);
597
+ const farmTokenSrc = farmTokenSrcParam || (0, spl_token_1.getAssociatedTokenAddressSync)(farmMint, signer, true, farmTokenProgram);
598
+ const farmTokenEscrowAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(feePayer, farmTokenEscrow, this.selfAddress, farmMint, farmTokenProgram);
599
+ const ix = await this.clmmProgram.methods
600
+ .addFarm(new anchor_1.BN(emissionsRate.toString()), untilTimestamp)
601
+ .accountsStrict({
602
+ market: this.selfAddress,
603
+ ticks: this.ticksKey,
604
+ signer,
605
+ feePayer,
606
+ mintNew: farmMint,
607
+ tokenSource: farmTokenSrc,
608
+ tokenFarm: farmTokenEscrow,
609
+ tokenProgram: farmTokenProgram,
610
+ systemProgram: anchor_1.web3.SystemProgram.programId,
611
+ eventAuthority: this.eventAuthority,
612
+ program: this.clmmProgram.programId,
613
+ })
614
+ .instruction();
615
+ return {
616
+ ixs: [ix],
617
+ setupIxs: [farmTokenEscrowAtaIx],
618
+ };
619
+ }
620
+ /**
621
+ * Modify an existing farm's emissions rate and/or expiration timestamp
622
+ *
623
+ * If the new parameters require more tokens than previously undistributed,
624
+ * additional tokens will be transferred from the signer's token account.
625
+ * If fewer tokens are needed, the surplus will be returned to the signer.
626
+ *
627
+ * @param signer - The admin address that signs the transaction
628
+ * @param farmMint - The mint address of the farm reward token
629
+ * @param farmTokenProgram - The token program for the farm reward token
630
+ * @param newRate - The new rate of emissions per second (in token smallest units)
631
+ * @param untilTimestamp - New unix timestamp when the farm emissions should end
632
+ * @param farmTokenSrc - Optional source/destination token account (derived from signer if not provided)
633
+ */
634
+ async ixModifyFarm({ signer, farmMint, farmTokenProgram, newRate, untilTimestamp, farmTokenSrc: farmTokenSrcParam, }) {
635
+ const farmTokenEscrow = (0, spl_token_1.getAssociatedTokenAddressSync)(farmMint, this.selfAddress, true, farmTokenProgram);
636
+ const farmTokenSrc = farmTokenSrcParam || (0, spl_token_1.getAssociatedTokenAddressSync)(farmMint, signer, true, farmTokenProgram);
637
+ const ix = await this.clmmProgram.methods
638
+ .modifyFarm(untilTimestamp, new anchor_1.BN(newRate.toString()))
639
+ .accountsStrict({
640
+ market: this.selfAddress,
641
+ ticks: this.ticksKey,
642
+ signer,
643
+ mint: farmMint,
644
+ tokenSource: farmTokenSrc,
645
+ tokenFarm: farmTokenEscrow,
646
+ tokenProgram: farmTokenProgram,
647
+ eventAuthority: this.eventAuthority,
648
+ program: this.clmmProgram.programId,
649
+ })
650
+ .instruction();
651
+ return {
652
+ ixs: [ix],
653
+ };
654
+ }
655
+ async ixWrapperBuyPt({ owner, minPtOut, baseIn, tokenSyTrader: tokenSyTraderParam, tokenPtTrader: tokenPtTraderParam, tokenBaseTrader: tokenBaseTraderParam, lnImpliedApyLimit, }) {
656
+ const tokenSyTrader = tokenSyTraderParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
657
+ const tokenPtTrader = tokenPtTraderParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
658
+ const tokenBaseTrader = tokenBaseTraderParam ||
659
+ (0, spl_token_1.getAssociatedTokenAddressSync)(this.flavor.mintBase, owner, true, this.flavor.baseTokenProgram);
660
+ const tokenSyTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenSyTrader, owner, this.mintSy);
661
+ const tokenPtTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenPtTrader, owner, this.mintPt);
662
+ const tokenBaseTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenBaseTrader, owner, this.flavor.mintBase);
663
+ const mintSyIx = await this.flavor.ixMintSy({
664
+ amountBase: "0",
665
+ depositor: owner,
666
+ depositorBaseTokenAccount: tokenBaseTrader,
667
+ depositorSyTokenAccount: tokenSyTrader,
668
+ });
669
+ const mintSyRemAccounts = mintSyIx.keys;
670
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
671
+ ...this.cpiSyAccounts.getSyState,
672
+ ...this.cpiSyAccounts.depositSy,
673
+ ...this.cpiSyAccounts.getPositionState,
674
+ ]);
675
+ let lnImpliedApyLimitOptional = lnImpliedApyLimit ? lnImpliedApyLimit : null;
676
+ const ix = await this.clmmProgram.methods
677
+ .buyPt(new anchor_1.BN(minPtOut.toString()), new anchor_1.BN(baseIn.toString()), lnImpliedApyLimitOptional, mintSyRemAccounts.length)
678
+ .accountsStrict({
679
+ addressLookupTable: this.addressLookupTable,
680
+ buyer: owner,
681
+ market: this.selfAddress,
682
+ tokenSyTrader,
683
+ tokenPtTrader,
684
+ tokenSyEscrow: this.tokenSyEscrow,
685
+ tokenPtEscrow: this.tokenPtEscrow,
686
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
687
+ syProgram: this.syProgram,
688
+ tokenFeeTreasurySy: this.state.tokenFeeTreasurySy,
689
+ eventAuthority: this.eventAuthority,
690
+ program: this.clmmProgram.programId,
691
+ tokenFeeTreasuryPt: this.state.tokenFeeTreasuryPt,
692
+ ticks: this.ticksKey,
693
+ })
694
+ .remainingAccounts(mintSyRemAccounts.concat(remainingAccounts))
695
+ .instruction();
696
+ return {
697
+ ixs: [...(await this.flavor.preIxs({ signer: owner })), ix, ...(await this.flavor.postIxs({ signer: owner }))],
698
+ setupIxs: [tokenSyTraderAtaIx, tokenPtTraderAtaIx, tokenBaseTraderAtaIx],
699
+ };
700
+ }
701
+ async ixWrapperSellPt({ owner, amount, minBaseOut, tokenSyTrader: tokenSyTraderParam, tokenPtTrader: tokenPtTraderParam, tokenBaseTrader: tokenBaseTraderParam, lnImpliedApyLimit, }) {
702
+ const tokenSyTrader = tokenSyTraderParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
703
+ const tokenPtTrader = tokenPtTraderParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
704
+ const tokenBaseTrader = tokenBaseTraderParam ||
705
+ (0, spl_token_1.getAssociatedTokenAddressSync)(this.flavor.mintBase, owner, true, this.flavor.baseTokenProgram);
706
+ const tokenSyTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenSyTrader, owner, this.mintSy);
707
+ const tokenPtTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenPtTrader, owner, this.mintPt);
708
+ const tokenBaseTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenBaseTrader, owner, this.flavor.mintBase);
709
+ const redeemSyIx = await this.flavor.ixRedeemSy({
710
+ amountSy: "0",
711
+ redeemer: owner,
712
+ redeemerBaseTokenAccount: tokenBaseTrader,
713
+ redeemerSyTokenAccount: tokenSyTrader,
714
+ });
715
+ const redeemSyRemAccounts = redeemSyIx.keys;
716
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
717
+ ...this.cpiSyAccounts.getSyState,
718
+ ...this.cpiSyAccounts.getPositionState,
719
+ ...this.cpiSyAccounts.withdrawSy,
720
+ ]);
721
+ let lnImpliedApyLimitOptional = lnImpliedApyLimit ? lnImpliedApyLimit : null;
722
+ const ix = await this.clmmProgram.methods
723
+ .sellPt(new anchor_1.BN(amount.toString()), new anchor_1.BN(minBaseOut.toString()), lnImpliedApyLimitOptional, redeemSyRemAccounts.length)
724
+ .accountsStrict({
725
+ seller: owner,
726
+ market: this.selfAddress,
727
+ tokenPtTrader,
728
+ addressLookupTable: this.addressLookupTable,
729
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
730
+ syProgram: this.syProgram,
731
+ tokenSyTrader,
732
+ tokenPtEscrow: this.tokenPtEscrow,
733
+ tokenSyEscrow: this.tokenSyEscrow,
734
+ tokenFeeTreasurySy: this.state.tokenFeeTreasurySy,
735
+ eventAuthority: this.eventAuthority,
736
+ program: this.clmmProgram.programId,
737
+ ticks: this.ticksKey,
738
+ tokenFeeTreasuryPt: this.tokenFeeTreasuryPt,
739
+ })
740
+ .remainingAccounts(redeemSyRemAccounts.concat(remainingAccounts))
741
+ .instruction();
742
+ return {
743
+ ixs: [...(await this.flavor.preIxs({ signer: owner })), ix, ...(await this.flavor.postIxs({ signer: owner }))],
744
+ setupIxs: [tokenSyTraderAtaIx, tokenPtTraderAtaIx, tokenBaseTraderAtaIx],
745
+ };
746
+ }
747
+ async ixWrapperBuyYt({ owner, ytOut, maxBaseIn, tokenSyTrader: tokenSyTraderParam, tokenPtTrader: tokenPtTraderParam, tokenYtTrader: tokenYtTraderParam, tokenBaseTrader: tokenBaseTraderParam, }) {
748
+ const tokenSyTrader = tokenSyTraderParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
749
+ const tokenPtTrader = tokenPtTraderParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
750
+ const tokenYtTrader = tokenYtTraderParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintYt, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
751
+ const tokenBaseTrader = tokenBaseTraderParam ||
752
+ (0, spl_token_1.getAssociatedTokenAddressSync)(this.flavor.mintBase, owner, true, this.flavor.baseTokenProgram);
753
+ const tokenSyTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenSyTrader, owner, this.mintSy);
754
+ const tokenPtTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenPtTrader, owner, this.mintPt);
755
+ const tokenYtTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenYtTrader, owner, this.mintYt);
756
+ const mintSyIx = await this.flavor.ixMintSy({
757
+ amountBase: "0",
758
+ depositor: owner,
759
+ depositorBaseTokenAccount: tokenBaseTrader,
760
+ depositorSyTokenAccount: tokenSyTrader,
761
+ });
762
+ const depositYtAccounts = await this.depositYtAccounts({
763
+ owner,
764
+ ytSrc: tokenYtTrader,
765
+ });
766
+ const mintSyRemAccounts = mintSyIx.keys;
767
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
768
+ ...this.cpiSyAccounts.getSyState,
769
+ ...this.cpiSyAccounts.getPositionState,
770
+ ...this.cpiSyAccounts.withdrawSy,
771
+ ...this.cpiCoreAccounts.stripSy,
772
+ ...this.cpiSyAccounts.getPositionState,
773
+ ]);
774
+ const depositYtAccounts_until = mintSyRemAccounts.length + depositYtAccounts.keys.length;
775
+ const allRemainingAccounts = mintSyRemAccounts.concat(depositYtAccounts.keys).concat(remainingAccounts);
776
+ const ix1 = await this.clmmProgram.methods
777
+ .wrapperBuyYt(new anchor_1.BN(ytOut.toString()), new anchor_1.BN(maxBaseIn.toString()), mintSyRemAccounts.length, depositYtAccounts_until)
778
+ .accountsStrict({
779
+ buyer: owner,
780
+ market: this.selfAddress,
781
+ tokenSyTrader,
782
+ tokenYtTrader,
783
+ tokenPtTrader,
784
+ tokenSyEscrow: this.tokenSyEscrow,
785
+ tokenPtEscrow: this.tokenPtEscrow,
786
+ marketAddressLookupTable: this.addressLookupTable,
787
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
788
+ syProgram: this.syProgram,
789
+ systemProgram: anchor_1.web3.SystemProgram.programId,
790
+ tokenFeeTreasurySy: this.state.tokenFeeTreasurySy,
791
+ eventAuthority: this.eventAuthority,
792
+ program: this.clmmProgram.programId,
793
+ tokenYtEscrow: this.tokenYtEscrow,
794
+ tokenFeeTreasuryPt: this.tokenFeeTreasuryPt,
795
+ ticks: this.ticksKey,
796
+ exponentCoreProgram: this.state.exponentCoreProgram,
797
+ })
798
+ .remainingAccounts(allRemainingAccounts)
799
+ .instruction();
800
+ return {
801
+ ixs: [...(await this.flavor.preIxs({ signer: owner })), ix1],
802
+ setupIxs: [tokenSyTraderAtaIx, tokenPtTraderAtaIx, tokenYtTraderAtaIx],
803
+ };
804
+ }
805
+ async ixWrapperSellYt({ owner, amount, minBaseOut, tokenBaseTrader: tokenBaseTraderParam, tokenSyTrader: tokenSyTraderParam, tokenYtTrader: tokenYtTraderParam, tokenPtTrader: tokenPtTraderParam, }) {
806
+ const tokenBaseTrader = tokenBaseTraderParam ||
807
+ (0, spl_token_1.getAssociatedTokenAddressSync)(this.flavor.mintBase, owner, true, this.flavor.baseTokenProgram);
808
+ const tokenSyTrader = tokenSyTraderParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
809
+ const tokenYtTrader = tokenYtTraderParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintYt, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
810
+ const tokenPtTrader = tokenPtTraderParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
811
+ const tokenSyTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenSyTrader, owner, this.mintSy);
812
+ const tokenPtTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenPtTrader, owner, this.mintPt);
813
+ const tokenYtTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenYtTrader, owner, this.mintYt);
814
+ const tokenBaseTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenBaseTrader, owner, this.flavor.mintBase);
815
+ const redeemSyIx = await this.flavor.ixRedeemSy({
816
+ amountSy: "0",
817
+ redeemer: owner,
818
+ redeemerBaseTokenAccount: tokenBaseTrader,
819
+ redeemerSyTokenAccount: tokenSyTrader,
820
+ });
821
+ const redeemSyRemAccounts = redeemSyIx.keys;
822
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
823
+ ...this.cpiSyAccounts.getSyState,
824
+ ...this.cpiSyAccounts.getPositionState,
825
+ ...this.cpiCoreAccounts.mergeSy,
826
+ ...this.cpiSyAccounts.withdrawSy,
827
+ ...this.cpiSyAccounts.depositSy,
828
+ ]);
829
+ const ix1 = await this.clmmProgram.methods
830
+ .wrapperSellYt(new anchor_1.BN(amount.toString()), new anchor_1.BN(minBaseOut.toString()), redeemSyRemAccounts.length)
831
+ .accountsStrict({
832
+ seller: owner,
833
+ market: this.selfAddress,
834
+ tokenYtTrader,
835
+ marketAddressLookupTable: this.addressLookupTable,
836
+ tokenPtTrader,
837
+ tokenPtEscrow: this.tokenPtEscrow,
838
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
839
+ syProgram: this.syProgram,
840
+ tokenSyTrader,
841
+ tokenSyEscrow: this.tokenSyEscrow,
842
+ tokenFeeTreasurySy: this.state.tokenFeeTreasurySy,
843
+ eventAuthority: this.eventAuthority,
844
+ program: this.clmmProgram.programId,
845
+ tokenYtEscrow: this.tokenYtEscrow,
846
+ tokenFeeTreasuryPt: this.tokenFeeTreasuryPt,
847
+ ticks: this.ticksKey,
848
+ exponentCoreProgram: this.state.exponentCoreProgram,
849
+ })
850
+ .remainingAccounts(redeemSyRemAccounts.concat(remainingAccounts))
851
+ .instruction();
852
+ return {
853
+ ixs: [ix1, ...(await this.flavor.preIxs({ signer: owner }))],
854
+ setupIxs: [tokenSyTraderAtaIx, tokenPtTraderAtaIx, tokenYtTraderAtaIx, tokenBaseTraderAtaIx],
855
+ };
856
+ }
857
+ /** Provide liquidity from a base asset - and receive YT and LP tokens in return */
858
+ async ixWrapperProvideLiquidity({ depositor, amountBase, minLpOut, lowerTickApy, upperTickApy, tokenSyDepositor: tokenSyDepositorParam, tokenYtDepositor: tokenYtDepositorParam, tokenPtDepositor: tokenPtDepositorParam, tokenBaseDepositor: tokenBaseDepositorParam, lpPosition: lpPositionParam, }) {
859
+ const tokenSyDepositor = tokenSyDepositorParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, depositor, true, spl_token_1.TOKEN_PROGRAM_ID);
860
+ const tokenYtDepositor = tokenYtDepositorParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintYt, depositor, true, spl_token_1.TOKEN_PROGRAM_ID);
861
+ const tokenPtDepositor = tokenPtDepositorParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, depositor, true, spl_token_1.TOKEN_PROGRAM_ID);
862
+ const tokenBaseDepositor = tokenBaseDepositorParam ||
863
+ (0, spl_token_1.getAssociatedTokenAddressSync)(this.flavor.mintBase, depositor, true, this.flavor.baseTokenProgram);
864
+ const lpPosition = lpPositionParam || anchor_1.web3.Keypair.generate();
865
+ const tokenSyDepositorAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(depositor, tokenSyDepositor, depositor, this.mintSy);
866
+ const tokenYtDepositorAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(depositor, tokenYtDepositor, depositor, this.mintYt);
867
+ const tokenPtDepositorAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(depositor, tokenPtDepositor, depositor, this.mintPt);
868
+ const amountBaseBn = new anchor_1.BN(amountBase.toString());
869
+ const minLpOutBn = new anchor_1.BN(minLpOut.toString());
870
+ const mintSyIx = await this.flavor.ixMintSy({
871
+ // argument does not matter - since we are just getting the keys
872
+ amountBase: "0",
873
+ depositor,
874
+ depositorBaseTokenAccount: tokenBaseDepositor,
875
+ depositorSyTokenAccount: tokenSyDepositor,
876
+ });
877
+ const mintSyRemAccounts = mintSyIx.keys;
878
+ const unorderedRemainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
879
+ ...this.cpiSyAccounts.getSyState,
880
+ ...this.cpiSyAccounts.getPositionState,
881
+ ...this.cpiCoreAccounts.stripSy,
882
+ ...this.cpiSyAccounts.depositSy,
883
+ ]);
884
+ const depositYtAccounts = await this.depositYtAccounts({
885
+ owner: depositor,
886
+ ytSrc: tokenYtDepositor,
887
+ });
888
+ const depositAccountsUntil = mintSyRemAccounts.length + depositYtAccounts.keys.length;
889
+ const allRemainingAccounts = [...mintSyRemAccounts, ...depositYtAccounts.keys, ...unorderedRemainingAccounts];
890
+ const ix = await this.clmmProgram.methods
891
+ .wrapperProvideLiquidity(convertApyToApyBp(lowerTickApy), convertApyToApyBp(upperTickApy), amountBaseBn, minLpOutBn, mintSyRemAccounts.length, depositAccountsUntil)
892
+ .accountsStrict({
893
+ depositor,
894
+ market: this.selfAddress,
895
+ tokenPtEscrow: this.tokenPtEscrow,
896
+ tokenSyEscrow: this.tokenSyEscrow,
897
+ tokenSyDepositor,
898
+ tokenYtDepositor,
899
+ tokenPtDepositor,
900
+ mintYt: this.vault.mintYt,
901
+ mintPt: this.vault.mintPt,
902
+ systemProgram: anchor_1.web3.SystemProgram.programId,
903
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
904
+ syProgram: this.syProgram,
905
+ marketAddressLookupTable: this.addressLookupTable,
906
+ eventAuthority: this.eventAuthority,
907
+ program: this.clmmProgram.programId,
908
+ lpPosition: lpPosition.publicKey,
909
+ tokenYtEscrow: this.tokenYtEscrow,
910
+ ticks: this.ticksKey,
911
+ exponentCoreProgram: this.state.exponentCoreProgram,
912
+ })
913
+ .remainingAccounts(allRemainingAccounts)
914
+ .instruction();
915
+ // console.log("ix accounts length", ix.keys.length)
916
+ return {
917
+ ixs: [
918
+ ...(await this.flavor.preIxs({ signer: depositor })),
919
+ ix,
920
+ ...(await this.flavor.postIxs({ signer: depositor })),
921
+ ],
922
+ signers: [lpPosition],
923
+ setupIxs: [tokenSyDepositorAtaIx, tokenYtDepositorAtaIx, tokenPtDepositorAtaIx],
924
+ };
925
+ }
926
+ async ixProvideLiquidityClassic({ depositor, amountBase, amountPt, minLpOut, lowerTickApy, upperTickApy, tokenSyDepositor: tokenSyDepositorParam, tokenYtDepositor: tokenYtDepositorParam, tokenPtDepositor: tokenPtDepositorParam, tokenBaseDepositor: tokenBaseDepositorParam, }) {
927
+ const tokenSyDepositor = tokenSyDepositorParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, depositor, true, spl_token_1.TOKEN_PROGRAM_ID);
928
+ const tokenYtDepositor = tokenYtDepositorParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintYt, depositor, true, spl_token_1.TOKEN_PROGRAM_ID);
929
+ const tokenPtDepositor = tokenPtDepositorParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, depositor, true, spl_token_1.TOKEN_PROGRAM_ID);
930
+ const tokenBaseDepositor = tokenBaseDepositorParam ||
931
+ (0, spl_token_1.getAssociatedTokenAddressSync)(this.flavor.mintBase, depositor, true, this.flavor.baseTokenProgram);
932
+ const lpPosition = anchor_1.web3.Keypair.generate();
933
+ const tokenSyAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(depositor, tokenSyDepositor, depositor, this.mintSy);
934
+ const tokenYtAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(depositor, tokenYtDepositor, depositor, this.mintYt);
935
+ const tokenPtAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(depositor, tokenPtDepositor, depositor, this.mintPt);
936
+ const tokenBaseAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(depositor, tokenBaseDepositor, depositor, this.flavor.mintBase, this.flavor.baseTokenProgram);
937
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
938
+ ...this.cpiSyAccounts.depositSy,
939
+ ...this.cpiSyAccounts.withdrawSy,
940
+ ...this.cpiCoreAccounts.stripSy,
941
+ ...this.cpiSyAccounts.getPositionState,
942
+ ]);
943
+ const mintSyIx = await this.flavor.ixMintSy({
944
+ amountBase: "0",
945
+ depositor,
946
+ depositorBaseTokenAccount: tokenBaseDepositor,
947
+ depositorSyTokenAccount: tokenSyDepositor,
948
+ });
949
+ const mintSyRemAccounts = mintSyIx.keys;
950
+ const ix = await this.clmmProgram.methods
951
+ .wrapperProvideLiquidityClassic(convertApyToApyBp(lowerTickApy), convertApyToApyBp(upperTickApy), new anchor_1.BN(amountBase.toString()), new anchor_1.BN(amountPt.toString()), new anchor_1.BN(minLpOut.toString()), mintSyRemAccounts.length)
952
+ .accountsStrict({
953
+ depositor,
954
+ lpPosition: lpPosition.publicKey,
955
+ market: this.selfAddress,
956
+ tokenPtEscrow: this.tokenPtEscrow,
957
+ tokenSyEscrow: this.tokenSyEscrow,
958
+ syProgram: this.syProgram,
959
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
960
+ marketAddressLookupTable: this.addressLookupTable,
961
+ tokenPtDepositor,
962
+ tokenSyDepositor,
963
+ systemProgram: anchor_1.web3.SystemProgram.programId,
964
+ eventAuthority: this.eventAuthority,
965
+ program: this.clmmProgram.programId,
966
+ ticks: this.ticksKey,
967
+ })
968
+ .remainingAccounts(mintSyRemAccounts.concat(remainingAccounts))
969
+ .instruction();
970
+ return {
971
+ ixs: [
972
+ ...(await this.flavor.preIxs({ signer: depositor })),
973
+ ix,
974
+ ...(await this.flavor.postIxs({ signer: depositor })),
975
+ ],
976
+ signers: [lpPosition],
977
+ setupIxs: [tokenSyAtaIx, tokenYtAtaIx, tokenPtAtaIx, tokenBaseAtaIx],
978
+ };
979
+ }
980
+ async ixWithdrawLiquidityToBase({ owner, amountLp, minBaseOut, lpPosition, tokenSyWithdrawer: tokenSyWithdrawerParam, tokenYtWithdrawer: tokenYtWithdrawerParam, tokenPtWithdrawer: tokenPtWithdrawerParam, tokenBaseWithdrawer: tokenBaseWithdrawerParam, }) {
981
+ const tokenSyWithdrawer = tokenSyWithdrawerParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
982
+ const tokenYtWithdrawer = tokenYtWithdrawerParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintYt, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
983
+ const tokenPtWithdrawer = tokenPtWithdrawerParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
984
+ const tokenBaseWithdrawer = tokenBaseWithdrawerParam ||
985
+ (0, spl_token_1.getAssociatedTokenAddressSync)(this.flavor.mintBase, owner, true, this.flavor.baseTokenProgram);
986
+ const tokenSyAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenSyWithdrawer, owner, this.mintSy);
987
+ const tokenYtAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenYtWithdrawer, owner, this.mintYt);
988
+ const tokenPtAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenPtWithdrawer, owner, this.mintPt);
989
+ const tokenBaseAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenBaseWithdrawer, owner, this.flavor.mintBase, this.flavor.baseTokenProgram);
990
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
991
+ ...this.cpiSyAccounts.withdrawSy,
992
+ ...this.cpiSyAccounts.getPositionState,
993
+ ]);
994
+ const redeemSyIx = await this.flavor.ixRedeemSy({
995
+ amountSy: "0",
996
+ redeemer: owner,
997
+ redeemerBaseTokenAccount: tokenBaseWithdrawer,
998
+ redeemerSyTokenAccount: tokenSyWithdrawer,
999
+ });
1000
+ const redeemSyRemAccounts = redeemSyIx.keys;
1001
+ const minSyOut = Number(minBaseOut) / this.currentSyExchangeRate;
1002
+ const ix = await this.clmmProgram.methods
1003
+ .wrapperWithdrawLiquidity(new anchor_1.BN(amountLp.toString()), new anchor_1.BN(minSyOut.toFixed(0).toString()), redeemSyRemAccounts.length)
1004
+ .accountsStrict({
1005
+ market: this.selfAddress,
1006
+ tokenPtEscrow: this.tokenPtEscrow,
1007
+ tokenSyEscrow: this.tokenSyEscrow,
1008
+ lpPosition,
1009
+ marketAddressLookupTable: this.addressLookupTable,
1010
+ eventAuthority: this.eventAuthority,
1011
+ syProgram: this.syProgram,
1012
+ systemProgram: anchor_1.web3.SystemProgram.programId,
1013
+ tokenFeeTreasurySy: this.state.tokenFeeTreasurySy,
1014
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
1015
+ tokenPtWithdrawer,
1016
+ tokenSyWithdrawer,
1017
+ withdrawer: owner,
1018
+ ticks: this.ticksKey,
1019
+ tokenFeeTreasuryPt: this.tokenFeeTreasuryPt,
1020
+ program: this.clmmProgram.programId,
1021
+ })
1022
+ .remainingAccounts(redeemSyRemAccounts.concat(remainingAccounts))
1023
+ .instruction();
1024
+ return {
1025
+ ixs: [...(await this.flavor.preIxs({ signer: owner })), ix, ...(await this.flavor.postIxs({ signer: owner }))],
1026
+ setupIxs: [tokenSyAtaIx, tokenYtAtaIx, tokenPtAtaIx, tokenBaseAtaIx],
1027
+ };
1028
+ }
1029
+ async ixWithdrawLiquidityClassic({ owner, amountLp, lpPosition, tokenSyWithdrawer: tokenSyWithdrawerParam, tokenYtWithdrawer: tokenYtWithdrawerParam, tokenPtWithdrawer: tokenPtWithdrawerParam, tokenBaseWithdrawer: tokenBaseWithdrawerParam, }) {
1030
+ const tokenSyWithdrawer = tokenSyWithdrawerParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
1031
+ const tokenYtWithdrawer = tokenYtWithdrawerParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintYt, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
1032
+ const tokenPtWithdrawer = tokenPtWithdrawerParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
1033
+ const tokenBaseWithdrawer = tokenBaseWithdrawerParam ||
1034
+ (0, spl_token_1.getAssociatedTokenAddressSync)(this.flavor.mintBase, owner, true, this.flavor.baseTokenProgram);
1035
+ const tokenSyAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenSyWithdrawer, owner, this.mintSy);
1036
+ const tokenYtAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenYtWithdrawer, owner, this.mintYt);
1037
+ const tokenPtAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenPtWithdrawer, owner, this.mintPt);
1038
+ const tokenBaseAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenBaseWithdrawer, owner, this.flavor.mintBase, this.flavor.baseTokenProgram);
1039
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
1040
+ ...this.cpiSyAccounts.withdrawSy,
1041
+ ...this.cpiSyAccounts.getPositionState,
1042
+ ]);
1043
+ const redeemSyIx = await this.flavor.ixRedeemSy({
1044
+ amountSy: "0",
1045
+ redeemer: owner,
1046
+ redeemerBaseTokenAccount: tokenBaseWithdrawer,
1047
+ redeemerSyTokenAccount: tokenSyWithdrawer,
1048
+ });
1049
+ const redeemSyRemAccounts = redeemSyIx.keys;
1050
+ const ixn = await this.clmmProgram.methods
1051
+ .wrapperWithdrawLiquidityClassic(new anchor_1.BN(amountLp.toString()), redeemSyRemAccounts.length)
1052
+ .accountsStrict({
1053
+ market: this.selfAddress,
1054
+ tokenPtEscrow: this.tokenPtEscrow,
1055
+ tokenSyEscrow: this.tokenSyEscrow,
1056
+ lpPosition,
1057
+ marketAddressLookupTable: this.addressLookupTable,
1058
+ eventAuthority: this.eventAuthority,
1059
+ syProgram: this.syProgram,
1060
+ systemProgram: anchor_1.web3.SystemProgram.programId,
1061
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
1062
+ tokenPtWithdrawer,
1063
+ tokenSyWithdrawer,
1064
+ withdrawer: owner,
1065
+ ticks: this.ticksKey,
1066
+ program: this.clmmProgram.programId,
1067
+ })
1068
+ .remainingAccounts(redeemSyRemAccounts.concat(remainingAccounts))
1069
+ .instruction();
1070
+ return {
1071
+ ixs: [...(await this.flavor.preIxs({ signer: owner })), ixn, ...(await this.flavor.postIxs({ signer: owner }))],
1072
+ setupIxs: [tokenSyAtaIx, tokenYtAtaIx, tokenPtAtaIx, tokenBaseAtaIx],
1073
+ };
1074
+ }
1075
+ async getUserLpPositions(owner, market) {
1076
+ const lpPositions = await (await this.clmmProgram.account.lpPosition.all()).filter((lpPos) => lpPos.account.owner.toString() === owner.toString() && lpPos.account.market.toString() === market.toString());
1077
+ return {
1078
+ lpPositions: [lpPositions],
1079
+ };
1080
+ }
1081
+ // async ixCloseMarket({ owner }: { owner: web3.PublicKey }) {
1082
+ // const ixn = await this.clmmProgram.methods
1083
+ // .closeMarket()
1084
+ // .accountsStrict({
1085
+ // market: this.selfAddress,
1086
+ // systemProgram: web3.SystemProgram.programId,
1087
+ // payer: owner,
1088
+ // ticks: this.ticksKey,
1089
+ // program: this.clmmProgram.programId,
1090
+ // eventAuthority: this.eventAuthority,
1091
+ // rent: web3.SYSVAR_RENT_PUBKEY,
1092
+ // })
1093
+ // .instruction()
1094
+ // return {
1095
+ // ixs: [ixn],
1096
+ // }
1097
+ // }
1098
+ async ixMarketAccureEmissions({ owner, lpPosition }) {
1099
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([...this.cpiSyAccounts.getPositionState]);
1100
+ const ixn = await this.clmmProgram.methods
1101
+ .marketAccrueEmission()
1102
+ .accountsStrict({
1103
+ market: this.selfAddress,
1104
+ systemProgram: anchor_1.web3.SystemProgram.programId,
1105
+ ticks: this.ticksKey,
1106
+ program: this.clmmProgram.programId,
1107
+ eventAuthority: this.eventAuthority,
1108
+ lpPosition,
1109
+ owner,
1110
+ addressLookupTable: this.addressLookupTable,
1111
+ syProgram: this.syProgram,
1112
+ })
1113
+ .remainingAccounts(remainingAccounts)
1114
+ .instruction();
1115
+ return {
1116
+ ixs: [ixn],
1117
+ };
1118
+ }
1119
+ /**
1120
+ * Calculate the current price per unit of liquidity (principal only) for a tick range.
1121
+ * Mirrors the on-chain `liquidity_unit_price_in_asset` helper but performs the
1122
+ * principal aggregation client-side using the fetched ticks account.
1123
+ *
1124
+ * @param lowerTickKey - Inclusive tick key (APY in parts-per-million) for the left boundary
1125
+ * @param upperTickKey - Exclusive tick key for the right boundary
1126
+ * @param ticksOverride - Optional ticks account (defaults to the instance state)
1127
+ * @param syExchangeRateOverride - Optional SY exchange rate (defaults to current flavor rate)
1128
+ * @returns Price per unit of liquidity in underlying asset terms (principal only)
1129
+ */
1130
+ liquidityUnitPriceInAsset({ lowerTickKey, upperTickKey, ticksOverride, syExchangeRateOverride, }) {
1131
+ if (lowerTickKey >= upperTickKey) {
1132
+ throw new Error("lowerTickKey must be less than upperTickKey");
1133
+ }
1134
+ const ticksAccount = ticksOverride ?? this.state.ticks;
1135
+ if (!ticksAccount) {
1136
+ throw new Error("Ticks account data is unavailable");
1137
+ }
1138
+ const relevantIntervals = ticksAccount.ticksTree.filter((tick) => tick.apyBasePoints >= lowerTickKey && tick.apyBasePoints < upperTickKey);
1139
+ if (relevantIntervals.length === 0) {
1140
+ return 0;
1141
+ }
1142
+ let totalPrincipalPt = 0n;
1143
+ let totalPrincipalSy = 0n;
1144
+ let totalShareSupply = 0n;
1145
+ for (const interval of relevantIntervals) {
1146
+ totalPrincipalPt += interval.principalPt;
1147
+ totalPrincipalSy += interval.principalSy;
1148
+ totalShareSupply += interval.principalShareSupply;
1149
+ }
1150
+ if (totalShareSupply === 0n) {
1151
+ return 0;
1152
+ }
1153
+ const timeFactor = this.secondsRemaining / SECONDS_PER_YEAR;
1154
+ const ptAssetValuePerToken = Math.exp(-timeFactor * ticksAccount.currentSpotPrice);
1155
+ const syExchangeRate = syExchangeRateOverride ?? this.currentSyExchangeRate;
1156
+ const principalPtValue = new decimal_js_1.default(totalPrincipalPt.toString()).mul(ptAssetValuePerToken);
1157
+ const principalSyValue = new decimal_js_1.default(totalPrincipalSy.toString()).mul(syExchangeRate);
1158
+ const principalValue = principalPtValue.plus(principalSyValue);
1159
+ return principalValue.div(new decimal_js_1.default(totalShareSupply.toString())).toNumber();
1160
+ }
1161
+ /**
1162
+ * Compute fee growth inside a tick range using Uniswap V3 formula
1163
+ *
1164
+ * @param lowerTick - Lower tick boundary
1165
+ * @param upperTick - Upper tick boundary
1166
+ * @param feeGlobalPt - Optional: Override global PT fees (for historical calculations)
1167
+ * @param feeGlobalSy - Optional: Override global SY fees (for historical calculations)
1168
+ * @returns Object with inside_sy and inside_pt fee growth values
1169
+ */
1170
+ static computeFeeInsideForRange({ currentTickPrice, lowerTickPrice, upperTickPrice, feeGrowthIndexGlobalPt, feeGrowthIndexGlobalSy, lowerTickOutsidePt, lowerTickOutsideSy, upperTickOutsidePt, upperTickOutsideSy, }) {
1171
+ // Uniswap V3 formula for computing fee inside a range
1172
+ let insideSy;
1173
+ let insidePt;
1174
+ if (currentTickPrice < lowerTickPrice) {
1175
+ // Price below range: inside = outside(lower) - outside(upper)
1176
+ insideSy = lowerTickOutsideSy - upperTickOutsideSy;
1177
+ insidePt = lowerTickOutsidePt - upperTickOutsidePt;
1178
+ }
1179
+ else if (currentTickPrice >= upperTickPrice) {
1180
+ // Price above range: inside = outside(upper) - outside(lower)
1181
+ insideSy = upperTickOutsideSy - lowerTickOutsideSy;
1182
+ insidePt = upperTickOutsidePt - lowerTickOutsidePt;
1183
+ }
1184
+ else {
1185
+ // Price in range: inside = global - outside(lower) - outside(upper)
1186
+ insideSy = feeGrowthIndexGlobalSy - lowerTickOutsideSy - upperTickOutsideSy;
1187
+ insidePt = feeGrowthIndexGlobalPt - lowerTickOutsidePt - upperTickOutsidePt;
1188
+ }
1189
+ return { insideSy, insidePt };
1190
+ }
1191
+ /**
1192
+ * Calculate claimable fees for a position
1193
+ * Uses Q64.64 fixed-point math: tokens = floor((L * Δindex) >> 64)
1194
+ *
1195
+ * @param lpBalance - Position's liquidity balance
1196
+ * @param feeInsideLastSy - Last snapshot of inside SY fee growth
1197
+ * @param feeInsideLastPt - Last snapshot of inside PT fee growth
1198
+ * @param currentInsideSy - Current inside SY fee growth
1199
+ * @param currentInsidePt - Current inside PT fee growth
1200
+ * @param tokensOwedSy - Previously owed SY fees
1201
+ * @param tokensOwedPt - Previously owed PT fees
1202
+ * @returns Object with claimable and total fees
1203
+ */
1204
+ static calculateClaimableFees({ lpBalance, feeInsideLastSy, feeInsideLastPt, currentInsideSy, currentInsidePt, tokensOwedSy, tokensOwedPt, }) {
1205
+ // Calculate delta (growth since last snapshot)
1206
+ const deltaSy = currentInsideSy > feeInsideLastSy ? currentInsideSy - feeInsideLastSy : 0n;
1207
+ const deltaPt = currentInsidePt > feeInsideLastPt ? currentInsidePt - feeInsideLastPt : 0n;
1208
+ // Calculate claimable fees using Q64.64 math: tokens = floor((L * Δindex) >> 64)
1209
+ const claimableSy = (lpBalance * deltaSy) >> 64n;
1210
+ const claimablePt = (lpBalance * deltaPt) >> 64n;
1211
+ //? TotalPt and TotalSy don't make sense here because tokensOwedSy and tokensOwedPt are always 0
1212
+ // Calculate totals
1213
+ const totalSy = claimableSy + tokensOwedSy;
1214
+ const totalPt = claimablePt + tokensOwedPt;
1215
+ return {
1216
+ claimableSy,
1217
+ claimablePt,
1218
+ tokensOwedSy,
1219
+ tokensOwedPt,
1220
+ totalSy,
1221
+ totalPt,
1222
+ };
1223
+ }
1224
+ /**
1225
+ * Calculate historical fee APY for a tick range
1226
+ *
1227
+ * @param feeGrowthDeltaSy - Change in global SY fee growth over period
1228
+ * @param feeGrowthDeltaPt - Change in global PT fee growth over period
1229
+ * @param avgLiquidity - Average liquidity in the range during period
1230
+ * @param hoursElapsed - Number of hours in the period
1231
+ * @returns Object with fee APY metrics
1232
+ */
1233
+ static calculateHistoricalFeeApy({ feeGrowthDeltaSy, feeGrowthDeltaPt, avgLiquidity, hoursElapsed, }) {
1234
+ if (avgLiquidity === 0n || hoursElapsed === 0) {
1235
+ return {
1236
+ feeApySy: 0,
1237
+ feeApyPt: 0,
1238
+ feeApyTotal: 0,
1239
+ totalFeesSy: 0n,
1240
+ totalFeesPt: 0n,
1241
+ };
1242
+ }
1243
+ // Calculate total fees earned in the period using Q64.64 math
1244
+ const totalFeesSy = (feeGrowthDeltaSy * avgLiquidity) >> 64n;
1245
+ const totalFeesPt = (feeGrowthDeltaPt * avgLiquidity) >> 64n;
1246
+ // Annualization factor (hours in a year / hours elapsed)
1247
+ const hoursPerYear = 8760;
1248
+ const annualizationFactor = hoursPerYear / hoursElapsed;
1249
+ // Calculate APY as: (fees / avg_liquidity) * annualization_factor * 100
1250
+ const feeApySy = (Number((totalFeesSy * 10000n) / avgLiquidity) / 100) * annualizationFactor;
1251
+ const feeApyPt = (Number((totalFeesPt * 10000n) / avgLiquidity) / 100) * annualizationFactor;
1252
+ const feeApyTotal = feeApySy + feeApyPt;
1253
+ return {
1254
+ feeApySy,
1255
+ feeApyPt,
1256
+ feeApyTotal,
1257
+ totalFeesSy,
1258
+ totalFeesPt,
1259
+ };
1260
+ }
1261
+ async depositYtAccounts({ owner, ytSrc: ytSrcParam, }) {
1262
+ const ytSrc = ytSrcParam || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintYt, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
1263
+ const userYieldPosition = this.corePda.yieldPosition({ vault: this.state.vault.selfAddress, owner });
1264
+ const yieldPosition = this.corePda.vaultYieldPosition({ vault: this.state.vault.selfAddress });
1265
+ const escrowYt = this.corePda.escrowYt({ vault: this.state.vault.selfAddress });
1266
+ const mainAccounts = {
1267
+ depositor: owner,
1268
+ ytSrc,
1269
+ vault: this.state.vault.selfAddress,
1270
+ userYieldPosition: userYieldPosition,
1271
+ escrowYt: escrowYt,
1272
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
1273
+ syProgram: this.state.syProgram,
1274
+ addressLookupTable: this.vault.addressLookupTable,
1275
+ yieldPosition,
1276
+ systemProgram: anchor_1.web3.SystemProgram.programId,
1277
+ eventAuthority: this.coreEventAuthority,
1278
+ program: this.state.exponentCoreProgram,
1279
+ };
1280
+ const remainingAccounts = this.cpiSyAccounts.getSyState;
1281
+ const depositIx = await this.coreProgram.methods
1282
+ .depositYt(new anchor_1.BN(0))
1283
+ .accountsStrict(mainAccounts)
1284
+ .remainingAccounts(remainingAccounts)
1285
+ .instruction();
1286
+ return depositIx;
1287
+ }
1288
+ static calcEstimatedYieldForPosition(marketSnapshotDataCurrent, marketSnapshotDataHistory, lowerPricePercentage, upperPricePercentage, baseTokenAmount) {
1289
+ //? Prices in format of 1 + percentage / 100
1290
+ const lowerPrice = 1 + lowerPricePercentage / 100;
1291
+ //? Prices in format of 1 + percentage / 100
1292
+ const upperPrice = 1 + upperPricePercentage / 100;
1293
+ const { syNeeded: userSyProvided, ptNeeded: userPtProvided } = (0, market_three_math_1.calcDepositSyAndPtFromBaseAmount)({
1294
+ expirationTs: Number(marketSnapshotDataCurrent.financials.expirationTs) - marketSnapshotDataCurrent.snapshotTimeUnix,
1295
+ currentSpotPrice: marketSnapshotDataCurrent.currentSpotPrice,
1296
+ syExchangeRate: marketSnapshotDataCurrent.syExchangeRate,
1297
+ lowerPrice,
1298
+ upperPrice,
1299
+ baseTokenAmount: baseTokenAmount,
1300
+ });
1301
+ const [lowerFeeGrowthOutsidePtHistory, lowerFeeGrowthOutsideSyHistory] = lowerPrice <= marketSnapshotDataHistory.currentSpotPrice
1302
+ ? [marketSnapshotDataHistory.feeGrowthIndexGlobalPt, marketSnapshotDataHistory.feeGrowthIndexGlobalSy]
1303
+ : [0n, 0n];
1304
+ const [upperFeeGrowthOutsidePtHistory, upperFeeGrowthOutsideSyHistory] = upperPrice <= marketSnapshotDataHistory.currentSpotPrice
1305
+ ? [marketSnapshotDataHistory.feeGrowthIndexGlobalPt, marketSnapshotDataHistory.feeGrowthIndexGlobalSy]
1306
+ : [0n, 0n];
1307
+ const { insideSy: insideSyHistory, insidePt: insidePtHistory } = MarketThree.computeFeeInsideForRange({
1308
+ currentTickPrice: marketSnapshotDataHistory.currentSpotPrice,
1309
+ lowerTickPrice: lowerPrice,
1310
+ upperTickPrice: upperPrice,
1311
+ feeGrowthIndexGlobalPt: marketSnapshotDataHistory.feeGrowthIndexGlobalPt,
1312
+ feeGrowthIndexGlobalSy: marketSnapshotDataHistory.feeGrowthIndexGlobalSy,
1313
+ lowerTickOutsidePt: lowerFeeGrowthOutsidePtHistory,
1314
+ lowerTickOutsideSy: lowerFeeGrowthOutsideSyHistory,
1315
+ upperTickOutsidePt: upperFeeGrowthOutsidePtHistory,
1316
+ upperTickOutsideSy: upperFeeGrowthOutsideSyHistory,
1317
+ });
1318
+ const { liquidityTarget: liquidityTargetCurrent, syNeeded, ptNeeded, } = computeLiquidityTargetAndTokenNeedsForSnapshot(marketSnapshotDataCurrent, {
1319
+ lowerPrice,
1320
+ upperPrice,
1321
+ maxSy: userSyProvided,
1322
+ maxPt: userPtProvided,
1323
+ });
1324
+ const { insideSy: insideSyCurrent, insidePt: insidePtCurrent } = MarketThree.computeFeeInsideForRange({
1325
+ currentTickPrice: marketSnapshotDataCurrent.currentSpotPrice,
1326
+ lowerTickPrice: lowerPrice,
1327
+ upperTickPrice: upperPrice,
1328
+ feeGrowthIndexGlobalPt: BigInt(marketSnapshotDataCurrent.feeGrowthIndexGlobalPt),
1329
+ feeGrowthIndexGlobalSy: BigInt(marketSnapshotDataCurrent.feeGrowthIndexGlobalSy),
1330
+ lowerTickOutsidePt: BigInt(lowerFeeGrowthOutsidePtHistory),
1331
+ lowerTickOutsideSy: BigInt(lowerFeeGrowthOutsideSyHistory),
1332
+ upperTickOutsidePt: BigInt(upperFeeGrowthOutsidePtHistory),
1333
+ upperTickOutsideSy: BigInt(upperFeeGrowthOutsideSyHistory),
1334
+ });
1335
+ //? Single invocation
1336
+ const { claimablePt: ptExpectedFees, claimableSy: syExpectedFees } = MarketThree.calculateClaimableFees({
1337
+ lpBalance: BigInt(liquidityTargetCurrent),
1338
+ feeInsideLastSy: insideSyHistory,
1339
+ feeInsideLastPt: insidePtHistory,
1340
+ currentInsideSy: insideSyCurrent,
1341
+ currentInsidePt: insidePtCurrent,
1342
+ tokensOwedSy: 0n,
1343
+ tokensOwedPt: 0n,
1344
+ });
1345
+ //? As we don't have autocompounding, use 1 as annualization factor
1346
+ const ANNUALIZATION_FACTOR = 1;
1347
+ //? Convert SY amounts to baseToken: baseToken = syAmount / syExchangeRate
1348
+ const syNeededBaseToken = syNeeded > 0 ? syNeeded * marketSnapshotDataCurrent.syExchangeRate : 0;
1349
+ const syExpectedFeesBaseToken = syExpectedFees > 0n ? Number(syExpectedFees) * marketSnapshotDataCurrent.syExchangeRate : 0;
1350
+ const ptPriceInBaseToken = (0, market_three_math_1.calcPtPriceInAsset)(marketSnapshotDataCurrent.currentSpotPrice, Number(marketSnapshotDataCurrent.financials.expirationTs) - marketSnapshotDataCurrent.snapshotTimeUnix);
1351
+ const ptNeededBaseToken = ptNeeded * ptPriceInBaseToken;
1352
+ const ptExpectedFeesBaseToken = Number(ptExpectedFees) * ptPriceInBaseToken;
1353
+ //? Calculate total baseToken value of the position
1354
+ const totalPositionValueBaseToken = syNeededBaseToken + ptNeededBaseToken;
1355
+ //? Calculate total fees earned in baseToken
1356
+ const totalFeesBaseToken = syExpectedFeesBaseToken + ptExpectedFeesBaseToken;
1357
+ //? Calculate unified fee rate: total fees / total position value
1358
+ const totalFeeRate = totalPositionValueBaseToken > 0 ? totalFeesBaseToken / totalPositionValueBaseToken : 0;
1359
+ //? Annualize the fee rate
1360
+ const totalFeeRateAnnualized = totalFeeRate * ANNUALIZATION_FACTOR;
1361
+ return {
1362
+ totalFeeRate: totalFeeRateAnnualized,
1363
+ ptExpectedFees,
1364
+ syExpectedFees,
1365
+ expectedFeesBaseToken: totalFeesBaseToken,
1366
+ };
1367
+ }
1368
+ static calcGlobalFeeRate(marketSnapshotDataCurrent, marketSnapshotDataHistory) {
1369
+ const { financials: financialsCurrent, feeGrowthIndexGlobalPt: feeGrowthIndexGlobalPtCurrent, feeGrowthIndexGlobalSy: feeGrowthIndexGlobalSyCurrent, currentSpotPrice, currentPrefixSum, syExchangeRate, } = marketSnapshotDataCurrent;
1370
+ const { feeGrowthIndexGlobalPt: feeGrowthIndexGlobalPtHistory, feeGrowthIndexGlobalSy: feeGrowthIndexGlobalSyHistory, } = marketSnapshotDataHistory;
1371
+ const ptPriceInBaseToken = (0, market_three_math_1.calcPtPriceInAsset)(currentSpotPrice, Number(financialsCurrent.expirationTs) - marketSnapshotDataCurrent.snapshotTimeUnix);
1372
+ const feePt = Number(feeGrowthIndexGlobalPtCurrent - feeGrowthIndexGlobalPtHistory) / Number(currentPrefixSum);
1373
+ const feePtInBaseToken = feePt * ptPriceInBaseToken;
1374
+ const feeSy = Number(feeGrowthIndexGlobalSyCurrent - feeGrowthIndexGlobalSyHistory) / Number(currentPrefixSum);
1375
+ const feeSyInBaseToken = feeSy * syExchangeRate;
1376
+ const totalFeesInBaseToken = feePtInBaseToken + feeSyInBaseToken;
1377
+ const ptLiquidityInBaseToken = Number(financialsCurrent.ptBalance) * ptPriceInBaseToken;
1378
+ const syLiquidityInBaseToken = Number(financialsCurrent.syBalance) * syExchangeRate;
1379
+ const tvlInBaseToken = ptLiquidityInBaseToken + syLiquidityInBaseToken;
1380
+ const totalFeeRate = totalFeesInBaseToken / tvlInBaseToken;
1381
+ return {
1382
+ totalFeeRate,
1383
+ totalFeesInBaseToken,
1384
+ tvlInBaseToken,
1385
+ };
1386
+ }
1387
+ /**
1388
+ * Returns PT and SY amounts that will be received on liquidity removal from a position
1389
+ * If liquidityToRemove is not provided, assume that the full position balance will be removed
1390
+ */
1391
+ getPtAndSyOnWithdrawLiquidity(position, liquidityToRemove) {
1392
+ const { ticks, emissions } = this.state;
1393
+ return (0, market_three_math_1.getPtAndSyOnWithdrawLiquidity)(emissions, ticks, position, liquidityToRemove ?? position.lpBalance);
1394
+ }
1395
+ }
1396
+ exports.MarketThree = MarketThree;
1397
+ /**
1398
+ * Convert apy percents to input format
1399
+ */
1400
+ function convertApyToApyBp(price) {
1401
+ return price * 1e4;
1402
+ }
1403
+ /** Wrapper for computeLiquidityTargetAndTokenNeeds that takes a MarketSnapshotData as input */
1404
+ function computeLiquidityTargetAndTokenNeedsForSnapshot(marketSnapshotData, params) {
1405
+ const EPSILON_CLAMP = 1e-18;
1406
+ const { lowerPrice, upperPrice, maxSy, maxPt } = params;
1407
+ const { financials, currentSpotPrice, syExchangeRate, snapshotTimeUnix } = marketSnapshotData;
1408
+ const expirationTsNumber = Number(financials.expirationTs);
1409
+ const secondsRemaining = Math.max(0, expirationTsNumber - snapshotTimeUnix);
1410
+ const effSnap = new market_three_math_1.EffSnap((0, market_three_math_1.normalizedTimeRemaining)(secondsRemaining), syExchangeRate);
1411
+ const priceEffLower = effSnap.getEffectivePrice(lowerPrice);
1412
+ const priceEffUpper = effSnap.getEffectivePrice(upperPrice);
1413
+ return (0, market_three_math_1.computeLiquidityTargetAndTokenNeeds)(effSnap, currentSpotPrice, priceEffLower, priceEffUpper, lowerPrice, upperPrice, 0, 0, 0, maxSy, maxPt, EPSILON_CLAMP);
1414
+ }
1415
+ //# sourceMappingURL=marketThree.js.map