@exponent-labs/exponent-sdk 0.0.3

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 (68) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/build/addressLookupTableUtil.d.ts +12 -0
  3. package/build/addressLookupTableUtil.js +32 -0
  4. package/build/addressLookupTableUtil.js.map +1 -0
  5. package/build/environment.d.ts +10 -0
  6. package/build/environment.js +13 -0
  7. package/build/environment.js.map +1 -0
  8. package/build/events.d.ts +339 -0
  9. package/build/events.js +231 -0
  10. package/build/events.js.map +1 -0
  11. package/build/flavors.d.ts +24 -0
  12. package/build/flavors.js +713 -0
  13. package/build/flavors.js.map +1 -0
  14. package/build/index.d.ts +11 -0
  15. package/build/index.js +45 -0
  16. package/build/index.js.map +1 -0
  17. package/build/lpPosition.d.ts +35 -0
  18. package/build/lpPosition.js +103 -0
  19. package/build/lpPosition.js.map +1 -0
  20. package/build/market.d.ts +567 -0
  21. package/build/market.js +1445 -0
  22. package/build/market.js.map +1 -0
  23. package/build/syPosition.d.ts +6 -0
  24. package/build/syPosition.js +115 -0
  25. package/build/syPosition.js.map +1 -0
  26. package/build/tokenUtil.d.ts +3 -0
  27. package/build/tokenUtil.js +23 -0
  28. package/build/tokenUtil.js.map +1 -0
  29. package/build/utils/altUtil.d.ts +8 -0
  30. package/build/utils/altUtil.js +35 -0
  31. package/build/utils/altUtil.js.map +1 -0
  32. package/build/utils/binSolver.d.ts +1 -0
  33. package/build/utils/binSolver.js +45 -0
  34. package/build/utils/binSolver.js.map +1 -0
  35. package/build/utils/binSolver.test.d.ts +1 -0
  36. package/build/utils/binSolver.test.js +15 -0
  37. package/build/utils/binSolver.test.js.map +1 -0
  38. package/build/utils/index.d.ts +6 -0
  39. package/build/utils/index.js +31 -0
  40. package/build/utils/index.js.map +1 -0
  41. package/build/utils/ix.d.ts +6 -0
  42. package/build/utils/ix.js +3 -0
  43. package/build/utils/ix.js.map +1 -0
  44. package/build/vault.d.ts +289 -0
  45. package/build/vault.js +615 -0
  46. package/build/vault.js.map +1 -0
  47. package/build/ytPosition.d.ts +86 -0
  48. package/build/ytPosition.js +231 -0
  49. package/build/ytPosition.js.map +1 -0
  50. package/jest.config.js +5 -0
  51. package/package.json +42 -0
  52. package/src/addressLookupTableUtil.ts +34 -0
  53. package/src/environment.ts +19 -0
  54. package/src/events.ts +595 -0
  55. package/src/flavors.ts +773 -0
  56. package/src/index.ts +11 -0
  57. package/src/lpPosition.ts +129 -0
  58. package/src/market.ts +2338 -0
  59. package/src/syPosition.ts +151 -0
  60. package/src/tokenUtil.ts +20 -0
  61. package/src/utils/altUtil.ts +47 -0
  62. package/src/utils/binSolver.test.ts +15 -0
  63. package/src/utils/binSolver.ts +44 -0
  64. package/src/utils/index.ts +32 -0
  65. package/src/utils/ix.ts +7 -0
  66. package/src/vault.ts +999 -0
  67. package/src/ytPosition.ts +313 -0
  68. package/tsconfig.json +38 -0
@@ -0,0 +1,1445 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Market = exports.MyWallet = void 0;
4
+ const anchor_1 = require("@coral-xyz/anchor");
5
+ const exponent_fetcher_1 = require("@exponent-labs/exponent-fetcher");
6
+ const exponent_ix_1 = require("@exponent-labs/exponent-ix");
7
+ const spl_token_1 = require("@solana/spl-token");
8
+ const addressLookupTableUtil_1 = require("./addressLookupTableUtil");
9
+ const tokenUtil_1 = require("./tokenUtil");
10
+ const flavors_1 = require("./flavors");
11
+ const exponent_idl_1 = require("@exponent-labs/exponent-idl");
12
+ const anchor_2 = require("@coral-xyz/anchor");
13
+ const exponent_pda_1 = require("@exponent-labs/exponent-pda");
14
+ const vault_1 = require("./vault");
15
+ const market_math_1 = require("@exponent-labs/market-math");
16
+ const utils_1 = require("./utils");
17
+ const precise_number_1 = require("@exponent-labs/precise-number");
18
+ const altUtil_1 = require("./utils/altUtil");
19
+ const syPosition_1 = require("./syPosition");
20
+ const exponent_ix_2 = require("@exponent-labs/exponent-ix");
21
+ const SECONDS_PER_YEAR = 365 * 24 * 60 * 60;
22
+ class MyWallet {
23
+ payer;
24
+ constructor(payer) {
25
+ this.payer = payer;
26
+ this.payer = payer;
27
+ }
28
+ async signTransaction(tx) {
29
+ if (tx instanceof anchor_1.web3.Transaction) {
30
+ tx.partialSign(this.payer);
31
+ }
32
+ else {
33
+ tx.sign([this.payer]);
34
+ }
35
+ return tx;
36
+ }
37
+ async signAllTransactions(txs) {
38
+ return txs.map((t) => {
39
+ if (t instanceof anchor_1.web3.Transaction) {
40
+ t.partialSign(this.payer);
41
+ }
42
+ else if (t instanceof anchor_1.web3.VersionedTransaction) {
43
+ t.sign([this.payer]);
44
+ }
45
+ return t;
46
+ });
47
+ }
48
+ get publicKey() {
49
+ return this.payer.publicKey;
50
+ }
51
+ }
52
+ exports.MyWallet = MyWallet;
53
+ class Market {
54
+ state;
55
+ selfAddress;
56
+ env;
57
+ connection;
58
+ coreProgram;
59
+ xponIx;
60
+ xponPda;
61
+ constructor(state, selfAddress, env, connection) {
62
+ this.state = state;
63
+ this.selfAddress = selfAddress;
64
+ this.env = env;
65
+ this.connection = connection;
66
+ this.xponPda = new exponent_pda_1.ExponentPDA(env.coreProgramId);
67
+ this.xponIx = new exponent_ix_1.ExponentIx(env.coreProgramId);
68
+ const mockWallet = new MyWallet(anchor_1.web3.Keypair.generate());
69
+ this.coreProgram = new anchor_1.Program(exponent_idl_1.IDL, new anchor_1.AnchorProvider(connection, mockWallet));
70
+ }
71
+ static async load(env, connection, address, vault) {
72
+ const fetcher = new exponent_fetcher_1.ExponentFetcher({ connection });
73
+ const m = await fetcher.fetchMarket(address);
74
+ const [[lpSupply, sySupply], alt, loadedVault] = await Promise.all([
75
+ (0, tokenUtil_1.getMultipleMintSupply)(connection, [m.mintLp, m.mintSy]),
76
+ (0, addressLookupTableUtil_1.fetchAddressLookupTable)(connection, m.addressLookupTable),
77
+ vault || vault_1.Vault.load(env, connection, m.vault),
78
+ ]);
79
+ const cpiAccounts = (0, addressLookupTableUtil_1.makeCpiAccountMetaLists)(alt, m.cpiAccounts);
80
+ const flavor = (() => {
81
+ switch (loadedVault.flavor.flavor) {
82
+ case "marginfi":
83
+ return (0, flavors_1.makeFlavorMarginfiSync)(loadedVault.flavor);
84
+ case "kamino":
85
+ return (0, flavors_1.makeFlavorKaminoSync)(loadedVault.flavor);
86
+ case "jitoRestaking":
87
+ return (0, flavors_1.makeFlavorJitoRestakingSync)(loadedVault.flavor);
88
+ case "perena":
89
+ return (0, flavors_1.makeFlavorPerenaSync)(loadedVault.flavor);
90
+ case "generic":
91
+ return (0, flavors_1.makeFlavorGenericSync)(loadedVault.flavor);
92
+ default:
93
+ throw new Error(`Unknown flavor: ${loadedVault.flavor}`);
94
+ }
95
+ })();
96
+ const syPosition = await (0, syPosition_1.makeSyPosition)(fetcher, flavor, m.syProgram, address);
97
+ const state = {
98
+ ...m,
99
+ vault: loadedVault,
100
+ cpiAccounts,
101
+ lpSupply,
102
+ sySupply,
103
+ flavor,
104
+ syPosition,
105
+ };
106
+ return new Market(state, address, env, connection);
107
+ }
108
+ async reload(conn = this.connection) {
109
+ const m = await Market.load(this.env, conn, this.selfAddress);
110
+ this.state = m.state;
111
+ return m;
112
+ }
113
+ /** Convert to a JSON representation */
114
+ toJson() {
115
+ return toJson(this);
116
+ }
117
+ get vault() {
118
+ return this.state.vault;
119
+ }
120
+ get flavor() {
121
+ return this.state.flavor;
122
+ }
123
+ get lpSupply() {
124
+ return this.state.lpSupply;
125
+ }
126
+ get syBalance() {
127
+ return this.state.syBalance;
128
+ }
129
+ get ptBalance() {
130
+ return this.state.ptBalance;
131
+ }
132
+ get mintSy() {
133
+ return this.state.mintSy;
134
+ }
135
+ get mintPt() {
136
+ return this.state.mintPt;
137
+ }
138
+ get statusFlags() {
139
+ return this.state.statusFlags;
140
+ }
141
+ get mintYt() {
142
+ return this.vault.mintYt;
143
+ }
144
+ get mintLp() {
145
+ return this.state.mintLp;
146
+ }
147
+ get addressLookupTable() {
148
+ return this.state.addressLookupTable;
149
+ }
150
+ get syProgram() {
151
+ return this.state.syProgram;
152
+ }
153
+ get cpiAccounts() {
154
+ return this.state.cpiAccounts;
155
+ }
156
+ get marketEmissions() {
157
+ return this.state.emissions;
158
+ }
159
+ get emissions() {
160
+ if (this.flavor.flavor === "marginfi") {
161
+ return this.flavor.mfiSyState.account.emissions.map((e) => ({
162
+ escrowAccountAddress: e.escrowAccount,
163
+ mint: e.mint,
164
+ tokenProgramAddress: e.tokenProgram,
165
+ totalClaimed: BigInt(e.totalClaimedEmissions.toString()),
166
+ lastSeenTotalAccruedEmissions: BigInt(e.lastSeenTotalAccruedEmissions.toString()),
167
+ index: e.index,
168
+ }));
169
+ }
170
+ if (this.flavor.flavor === "kamino") {
171
+ return this.flavor.kaminoSyState.account.emissions.map((e) => ({
172
+ escrowAccountAddress: e.escrowAccount,
173
+ mint: e.mint,
174
+ tokenProgramAddress: e.tokenProgram,
175
+ totalClaimed: BigInt(e.totalClaimedEmissions.toString()),
176
+ lastSeenTotalAccruedEmissions: BigInt(e.lastSeenTotalAccruedEmissions.toString()),
177
+ index: e.index,
178
+ }));
179
+ }
180
+ if (this.flavor.flavor === "jitoRestaking") {
181
+ return this.flavor.jitoSyState.account.emissions.map((e) => ({
182
+ escrowAccountAddress: e.escrowAccount,
183
+ mint: e.mint,
184
+ tokenProgramAddress: e.tokenProgram,
185
+ totalClaimed: BigInt(e.totalClaimedEmissions.toString()),
186
+ lastSeenTotalAccruedEmissions: BigInt(e.lastSeenTotalAccruedEmissions.toString()),
187
+ index: e.index,
188
+ }));
189
+ }
190
+ if (this.flavor.flavor === "perena") {
191
+ return this.flavor.perenaSyState.account.emissions.map((e) => ({
192
+ escrowAccountAddress: e.escrowAccount,
193
+ mint: e.mint,
194
+ tokenProgramAddress: e.tokenProgram,
195
+ totalClaimed: BigInt(e.totalClaimedEmissions.toString()),
196
+ lastSeenTotalAccruedEmissions: BigInt(e.lastSeenTotalAccruedEmissions.toString()),
197
+ index: e.index,
198
+ }));
199
+ }
200
+ if (this.flavor.flavor === "generic") {
201
+ return this.flavor.genericSyState.account.emissions.map((e) => ({
202
+ escrowAccountAddress: e.escrowAccount,
203
+ mint: e.mint,
204
+ tokenProgramAddress: e.tokenProgram,
205
+ totalClaimed: BigInt(e.totalClaimedEmissions.toString()),
206
+ lastSeenTotalAccruedEmissions: BigInt(e.lastSeenTotalAccruedEmissions.toString()),
207
+ index: e.index,
208
+ }));
209
+ }
210
+ throw new Error("Unknown flavor");
211
+ }
212
+ /** Get the escrow token account addresses for the emissions, in order */
213
+ get emissionTokenAccounts() {
214
+ return this.emissions.map((e) => e.escrowAccountAddress);
215
+ }
216
+ /** Pass-through SY account owned by the market */
217
+ get tokenSyEscrow() {
218
+ return this.state.tokenSyEscrow;
219
+ }
220
+ /** SY account that holds treasury SY fees from PT trading */
221
+ get tokenFeeTreasurySy() {
222
+ return this.state.tokenFeeTreasurySy;
223
+ }
224
+ /** Market liquidity for PT */
225
+ get tokenPtEscrow() {
226
+ return this.state.tokenPtEscrow;
227
+ }
228
+ get tokenLpEscrow() {
229
+ return this.state.tokenLpEscrow;
230
+ }
231
+ get currentSyExchangeRate() {
232
+ return this.flavor.currentSyExchangeRate;
233
+ }
234
+ /** Special account for event emit self-cpi */
235
+ get eventAuthority() {
236
+ return (0, utils_1.emitEventAuthority)(this.env.coreProgramId);
237
+ }
238
+ get currentPtPriceInSy() {
239
+ return this.currentPtPriceInAsset / this.currentSyExchangeRate;
240
+ }
241
+ get currentPtPriceInAsset() {
242
+ const c = this.marketCalculator();
243
+ return c.exchangeRate;
244
+ }
245
+ get ptDiscount() {
246
+ return 1 / this.currentPtPriceInAsset;
247
+ }
248
+ get lpPriceInAsset() {
249
+ // Calculate total value of liquidity in asset units
250
+ const liquidityPoolTvl = Number(this.syBalance) * this.flavor.currentSyExchangeRate + Number(this.ptBalance) / this.currentPtPriceInAsset;
251
+ // Return LP price in asset units (0 if no supply to avoid division by zero)
252
+ return Number(this.lpSupply) === 0 ? 0 : liquidityPoolTvl / Number(this.lpSupply);
253
+ }
254
+ get secondsRemaining() {
255
+ const now = Date.now() / 1000;
256
+ return Math.max(0, Math.round(this.state.expirationTs - now));
257
+ }
258
+ get absolutePtYield() {
259
+ const ptAssetExchangeRate = this.ptDiscount;
260
+ return (1 - ptAssetExchangeRate) / ptAssetExchangeRate;
261
+ }
262
+ /** Annualize a rate given the number of seconds remaining until maturity */
263
+ static annualize(r, secondsRemaining) {
264
+ return (r * SECONDS_PER_YEAR) / secondsRemaining;
265
+ }
266
+ /** Annualized PT fixed rate */
267
+ get ptApr() {
268
+ return Market.annualize(this.absolutePtYield, this.secondsRemaining);
269
+ }
270
+ /** The fee rate taken off of trade fees (typically around 20%) expressed as a BPS number */
271
+ get feeTreasuryBps() {
272
+ return this.state.feeTreasurySyBps;
273
+ }
274
+ /** The fee rate on assets when trading PT
275
+ * Expressed as a rational number
276
+ * eg 0.01 = 1%
277
+ */
278
+ get feeRatePtTrade() {
279
+ return 1 - this.marketCalculator().feeRate;
280
+ }
281
+ /** The fee rate taken off of trade fees (typically around 20%) expressed as a rational number */
282
+ get feeTreasuryRate() {
283
+ return this.feeTreasuryBps / 10_000;
284
+ }
285
+ /** Calculate amonut of LP tokens to expect for tokens in */
286
+ lpOutForTokensIn(syInIntent, ptInIntent) {
287
+ return (0, market_math_1.lpOutForTokensIn)({
288
+ syIntent: Number(syInIntent),
289
+ ptIntent: Number(ptInIntent),
290
+ lpSupply: Number(this.lpSupply),
291
+ syLiquidity: Number(this.syBalance),
292
+ ptLiquidity: Number(this.ptBalance),
293
+ });
294
+ }
295
+ marketCalculator() {
296
+ const secondsRemaining = Math.max(0, Math.round(this.state.expirationTs - Date.now() / 1000));
297
+ return new market_math_1.MarketCalculator({
298
+ liquiditySy: parseInt(this.syBalance.toString()),
299
+ liquidityPt: parseInt(this.ptBalance.toString()),
300
+ currentSyExchangeRate: this.currentSyExchangeRate,
301
+ lnFeeRateRoot: this.state.lnFeeRateRoot,
302
+ secondsRemaining,
303
+ lpTokenSupply: this.lpSupply,
304
+ rateScalarRoot: this.state.rateScalarRoot,
305
+ lastLnImpliedRate: this.state.lastLnImpliedRate,
306
+ maxNetBalanceChangeNegativePercentage: this.state.liquidityNetBalanceLimits.maxNetBalanceChangeNegativePercentage,
307
+ maxNetBalanceChangePositivePercentage: this.state.liquidityNetBalanceLimits.maxNetBalanceChangePositivePercentage,
308
+ windowStartTimestamp: this.state.liquidityNetBalanceLimits.windowStartTimestamp,
309
+ windowStartNetBalance: this.state.liquidityNetBalanceLimits.windowStartNetBalance.toNumber(),
310
+ windowDurationSeconds: this.state.liquidityNetBalanceLimits.windowDurationSeconds,
311
+ });
312
+ }
313
+ /** Deposit a pair of tokens as liquidity to the market
314
+ * Adds PT & SY from the `depositor` to the market
315
+ *
316
+ * Due to unforeseeable slippage, the PT & SY amounts intended are effectively the maximum amounts
317
+ * The minimum LP tokens to receive is specified by `minLpOut`
318
+ *
319
+ * The token accounts themselves are optional, and will be derived from the depositor's wallet if not provided
320
+ */
321
+ async ixDepositLiquidity({ ptInIntent, syInIntent, minLpOut, depositor, ptSrc, sySrc, lpDst, }) {
322
+ const tokenProgram = spl_token_1.TOKEN_PROGRAM_ID;
323
+ sySrc = sySrc || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, depositor, true, spl_token_1.TOKEN_PROGRAM_ID);
324
+ ptSrc = ptSrc || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, depositor, true, spl_token_1.TOKEN_PROGRAM_ID);
325
+ lpDst = lpDst || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintLp, depositor, true, spl_token_1.TOKEN_PROGRAM_ID);
326
+ const syRemAccounts = this.cpiAccounts.depositSy;
327
+ return this.coreProgram.methods
328
+ .marketTwoDepositLiquidity(new anchor_2.BN(ptInIntent.toString()), new anchor_2.BN(syInIntent.toString()), new anchor_2.BN(minLpOut.toString()))
329
+ .accountsStrict({
330
+ depositor,
331
+ market: this.selfAddress,
332
+ mintLp: this.mintLp,
333
+ tokenPtSrc: ptSrc,
334
+ tokenSySrc: sySrc,
335
+ tokenLpDst: lpDst,
336
+ tokenPtEscrow: this.tokenPtEscrow,
337
+ tokenSyEscrow: this.tokenSyEscrow,
338
+ addressLookupTable: this.addressLookupTable,
339
+ syProgram: this.syProgram,
340
+ tokenProgram,
341
+ eventAuthority: this.vault.eventAuthority,
342
+ program: this.coreProgram.programId,
343
+ })
344
+ .remainingAccounts(syRemAccounts)
345
+ .instruction();
346
+ }
347
+ async ixModifyMarketSetting({ signer, adminAction }) {
348
+ return this.coreProgram.methods
349
+ .modifyMarketSetting(adminAction)
350
+ .accountsStrict({
351
+ market: this.selfAddress,
352
+ adminState: (0, utils_1.getExponentAdminStatePda)(),
353
+ signer,
354
+ systemProgram: anchor_1.web3.SystemProgram.programId,
355
+ })
356
+ .instruction();
357
+ }
358
+ async ixModifyFarm({ newRate, untilTimestamp, signer, farmMint, farmTokenProgram, farmTokenSrc, }) {
359
+ farmTokenSrc = farmTokenSrc || (0, spl_token_1.getAssociatedTokenAddressSync)(farmMint, signer, true, farmTokenProgram);
360
+ const tokenFarm = (0, spl_token_1.getAssociatedTokenAddressSync)(farmMint, this.selfAddress, true, farmTokenProgram);
361
+ return this.coreProgram.methods
362
+ .modifyFarm(untilTimestamp, new anchor_2.BN(newRate.toString()))
363
+ .accountsStrict({
364
+ adminState: (0, utils_1.getExponentAdminStatePda)(),
365
+ market: this.selfAddress,
366
+ mint: farmMint,
367
+ tokenFarm: tokenFarm,
368
+ signer,
369
+ tokenProgram: farmTokenProgram,
370
+ tokenSource: farmTokenSrc,
371
+ })
372
+ .instruction();
373
+ }
374
+ /**
375
+ * Redeem LP tokens for PT & SY (liquidity removal)
376
+ *
377
+ * The lpIn is exactly the amount of LP tokens to burn
378
+ * The minimum PT & SY out are specified by minPtOut & minSyOut
379
+ * The transaction may fail due to unforeseeable slippage on the redemption rate
380
+ *
381
+ * The token accounts themselves are optional, and will be derived from the withdrawer's wallet if not provided
382
+ */
383
+ async ixWithdrawLiquidity({ lpIn, withdrawer, minPtOut, minSyOut, ptDst, syDst, lpSrc, }) {
384
+ ptDst = ptDst || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, withdrawer, true, spl_token_1.TOKEN_PROGRAM_ID);
385
+ syDst = syDst || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, withdrawer, true, spl_token_1.TOKEN_PROGRAM_ID);
386
+ lpSrc = lpSrc || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintLp, withdrawer, true, spl_token_1.TOKEN_PROGRAM_ID);
387
+ const ptDstAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(withdrawer, ptDst, withdrawer, this.mintPt);
388
+ const syDstAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(withdrawer, syDst, withdrawer, this.mintSy);
389
+ const lpSrcAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(withdrawer, lpSrc, withdrawer, this.mintLp);
390
+ const syRemAccounts = this.cpiAccounts.withdrawSy;
391
+ const ixs = await this.coreProgram.methods
392
+ .marketTwoWithdrawLiquidity(new anchor_2.BN(lpIn.toString()), new anchor_2.BN(minPtOut.toString()), new anchor_2.BN(minSyOut.toString()))
393
+ .accountsStrict({
394
+ withdrawer,
395
+ market: this.selfAddress,
396
+ mintLp: this.mintLp,
397
+ tokenPtDst: ptDst,
398
+ tokenSyDst: syDst,
399
+ tokenLpSrc: lpSrc,
400
+ tokenPtEscrow: this.tokenPtEscrow,
401
+ tokenSyEscrow: this.tokenSyEscrow,
402
+ addressLookupTable: this.addressLookupTable,
403
+ syProgram: this.syProgram,
404
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
405
+ eventAuthority: this.vault.eventAuthority,
406
+ program: this.coreProgram.programId,
407
+ })
408
+ .remainingAccounts(syRemAccounts)
409
+ .instruction();
410
+ return { ixs: [ixs], setupIxs: [ptDstAtaIx, syDstAtaIx, lpSrcAtaIx] };
411
+ }
412
+ /** Buy PT with SY
413
+ *
414
+ * The trader is the account that sends the SY
415
+ * The amountPt is the exact amount of PT the trader intends to buy
416
+ * The syConstraint is the maximum amount of SY the trader is willing to spend
417
+ *
418
+ * The token accounts themselves are optional, and will be derived from the trader's wallet if not provided
419
+ */
420
+ async ixBuyPt({ trader, amountPt, maxSySpend, tokenPt, tokenSy, }) {
421
+ return this.ixTradePt({
422
+ trader,
423
+ traderPt: amountPt,
424
+ syConstraint: maxSySpend,
425
+ isBuy: true,
426
+ tokenPt,
427
+ tokenSy,
428
+ });
429
+ }
430
+ /**
431
+ * Sell PT for SY
432
+ * The trader is the account that sends the PT
433
+ * The amountPt is the exact amount of PT the trader intends to sell
434
+ * The minSyReceive is the minimum amount of SY the trader is willing to receive
435
+ *
436
+ * The token accounts themselves are optional, and will be derived from the trader's wallet if not provided
437
+ */
438
+ async ixSellPt({ trader, amountPt, minSyReceive, tokenPt, tokenSy, }) {
439
+ return this.ixTradePt({
440
+ trader,
441
+ traderPt: amountPt,
442
+ syConstraint: minSyReceive,
443
+ isBuy: false,
444
+ tokenPt,
445
+ tokenSy,
446
+ });
447
+ }
448
+ async ixTradePt({ trader, traderPt, syConstraint, isBuy, tokenPt, tokenSy, }) {
449
+ tokenPt = tokenPt || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, trader, true, spl_token_1.TOKEN_PROGRAM_ID);
450
+ tokenSy = tokenSy || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, trader, true, spl_token_1.TOKEN_PROGRAM_ID);
451
+ const tokenSyAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(trader, tokenSy, trader, this.mintSy);
452
+ const tokenPtAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(trader, tokenPt, trader, this.mintPt);
453
+ const remainingAccounts = [
454
+ ...this.cpiAccounts.getSyState,
455
+ ...this.cpiAccounts.depositSy,
456
+ ...this.cpiAccounts.withdrawSy,
457
+ ];
458
+ const netTradePtBN = new anchor_2.BN(traderPt.toString()).mul(isBuy ? new anchor_2.BN(1) : new anchor_2.BN(-1));
459
+ const syConstraintBN = new anchor_2.BN(syConstraint.toString()).mul(isBuy ? new anchor_2.BN(-1) : new anchor_2.BN(1));
460
+ const ix = await this.coreProgram.methods
461
+ .tradePt(netTradePtBN, syConstraintBN)
462
+ .accountsStrict({
463
+ trader,
464
+ market: this.selfAddress,
465
+ tokenPtTrader: tokenPt,
466
+ tokenSyTrader: tokenSy,
467
+ tokenSyEscrow: this.tokenSyEscrow,
468
+ tokenPtEscrow: this.tokenPtEscrow,
469
+ addressLookupTable: this.addressLookupTable,
470
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
471
+ syProgram: this.syProgram,
472
+ tokenFeeTreasurySy: this.vault.state.treasurySyTokenAccount,
473
+ eventAuthority: this.vault.eventAuthority,
474
+ program: this.coreProgram.programId,
475
+ })
476
+ .remainingAccounts(remainingAccounts)
477
+ .instruction();
478
+ return { ixs: [ix], setupIxs: [tokenPtAtaIx, tokenSyAtaIx] };
479
+ }
480
+ /** Sell YT for SY
481
+ *
482
+ * The trader is the account that sends the YT
483
+ *
484
+ * The amountYt is the exact amount of YT the trader intends to sell
485
+ *
486
+ * The minSyOut is the minimum amount of SY the trader is willing to receive
487
+ *
488
+ * The token accounts themselves are optional, and will be derived from the trader's wallet if not provided
489
+ */
490
+ async ixSellYt({ trader, ytIn, minSyOut, ytSrc, ptSrc, syDst, }) {
491
+ syDst = syDst || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, trader, true, spl_token_1.TOKEN_PROGRAM_ID);
492
+ ptSrc = ptSrc || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, trader, true, spl_token_1.TOKEN_PROGRAM_ID);
493
+ ytSrc = ytSrc || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintYt, trader, true, spl_token_1.TOKEN_PROGRAM_ID);
494
+ const syDstAtaIxs = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(trader, syDst, trader, this.mintSy);
495
+ const ptSrcAtaIxs = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(trader, ptSrc, trader, this.mintPt);
496
+ const ytSrcAtaIxs = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(trader, ytSrc, trader, this.mintYt);
497
+ const mergeAccounts = this.vault.mergeAccounts({ owner: trader, ytSrc, ptSrc, syDst });
498
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
499
+ ...this.cpiAccounts.getSyState,
500
+ ...this.cpiAccounts.depositSy,
501
+ ...mergeAccounts.remainingAccounts,
502
+ ]);
503
+ remainingAccounts.push({ pubkey: this.coreProgram.programId, isWritable: false, isSigner: false });
504
+ const ix = await this.coreProgram.methods
505
+ .sellYt(new anchor_2.BN(ytIn.toString()), new anchor_2.BN(minSyOut.toString()))
506
+ .accountsStrict({
507
+ trader,
508
+ market: this.selfAddress,
509
+ tokenYtTrader: ytSrc,
510
+ tokenPtTrader: ptSrc,
511
+ tokenSyTrader: syDst,
512
+ tokenSyEscrow: this.tokenSyEscrow,
513
+ tokenPtEscrow: this.tokenPtEscrow,
514
+ addressLookupTable: this.addressLookupTable,
515
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
516
+ vault: mergeAccounts.mainAccounts.vault,
517
+ authorityVault: mergeAccounts.mainAccounts.authority,
518
+ tokenSyEscrowVault: mergeAccounts.mainAccounts.escrowSy,
519
+ mintYt: this.mintYt,
520
+ mintPt: this.mintPt,
521
+ addressLookupTableVault: mergeAccounts.mainAccounts.addressLookupTable,
522
+ yieldPositionVault: mergeAccounts.mainAccounts.yieldPosition,
523
+ syProgram: this.syProgram,
524
+ tokenFeeTreasurySy: this.vault.state.treasurySyTokenAccount,
525
+ eventAuthority: this.vault.eventAuthority,
526
+ program: this.coreProgram.programId,
527
+ })
528
+ .remainingAccounts(remainingAccounts)
529
+ .instruction();
530
+ return { ixs: [ix], setupIxs: [syDstAtaIxs, ptSrcAtaIxs, ytSrcAtaIxs] };
531
+ }
532
+ /** Buy YT with SY
533
+ *
534
+ * The trader is the account that sends the SY
535
+ *
536
+ * The ytOut is the exact amount of YT the trader intends to buy
537
+ *
538
+ * The maxSyIn is the maximum amount of SY the trader is willing to spend
539
+ *
540
+ * The token accounts themselves are optional, and will be derived from the trader's wallet if not provided
541
+ */
542
+ async ixBuyYt({ trader, ytOut, maxSyIn, ytTrader, ptTrader, syTrader, }) {
543
+ syTrader = syTrader || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, trader, true, spl_token_1.TOKEN_PROGRAM_ID);
544
+ ptTrader = ptTrader || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, trader, true, spl_token_1.TOKEN_PROGRAM_ID);
545
+ ytTrader = ytTrader || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintYt, trader, true, spl_token_1.TOKEN_PROGRAM_ID);
546
+ const syTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(trader, syTrader, trader, this.mintSy);
547
+ const ptTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(trader, ptTrader, trader, this.mintPt);
548
+ const ytTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(trader, ytTrader, trader, this.mintYt);
549
+ const stripAccounts = this.vault.stripAccounts({
550
+ depositor: trader,
551
+ ytDst: ytTrader,
552
+ ptDst: ptTrader,
553
+ sySrc: syTrader,
554
+ });
555
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
556
+ ...this.cpiAccounts.getSyState,
557
+ ...this.cpiAccounts.withdrawSy,
558
+ ...this.cpiAccounts.depositSy,
559
+ ...stripAccounts.remainingAccounts,
560
+ ]);
561
+ remainingAccounts.push({ pubkey: this.coreProgram.programId, isWritable: false, isSigner: false });
562
+ const ix = await this.coreProgram.methods
563
+ .buyYt(new anchor_2.BN(maxSyIn.toString()), new anchor_2.BN(ytOut.toString()))
564
+ .accountsStrict({
565
+ trader,
566
+ market: this.selfAddress,
567
+ tokenYtTrader: ytTrader,
568
+ tokenPtTrader: ptTrader,
569
+ tokenSyTrader: syTrader,
570
+ tokenSyEscrow: this.tokenSyEscrow,
571
+ tokenPtEscrow: this.tokenPtEscrow,
572
+ addressLookupTable: this.addressLookupTable,
573
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
574
+ syProgram: this.syProgram,
575
+ vault: stripAccounts.mainAccounts.vault,
576
+ vaultAuthority: stripAccounts.mainAccounts.authority,
577
+ tokenSyEscrowVault: stripAccounts.mainAccounts.escrowSy,
578
+ mintYt: this.mintYt,
579
+ mintPt: this.mintPt,
580
+ addressLookupTableVault: stripAccounts.mainAccounts.addressLookupTable,
581
+ yieldPosition: stripAccounts.mainAccounts.yieldPosition,
582
+ tokenFeeTreasurySy: this.vault.state.treasurySyTokenAccount,
583
+ eventAuthority: this.vault.eventAuthority,
584
+ program: this.coreProgram.programId,
585
+ })
586
+ .remainingAccounts(remainingAccounts)
587
+ .instruction();
588
+ return { ixs: [ix], setupIxs: [syTraderAtaIx, ptTraderAtaIx, ytTraderAtaIx] };
589
+ }
590
+ async ixInitLpPosition({ owner, feePayer }) {
591
+ const lpPosition = this.xponPda.marketLpPosition({ market: this.selfAddress, owner });
592
+ return this.coreProgram.methods
593
+ .initLpPosition()
594
+ .accountsStrict({
595
+ owner,
596
+ feePayer: feePayer || owner,
597
+ lpPosition,
598
+ market: this.selfAddress,
599
+ systemProgram: anchor_1.web3.SystemProgram.programId,
600
+ eventAuthority: this.vault.eventAuthority,
601
+ program: this.coreProgram.programId,
602
+ })
603
+ .instruction();
604
+ }
605
+ /** Deposit LP tokens into the farming module to earn rewards */
606
+ async ixDepositLp({ owner, amount, lpSrc }) {
607
+ lpSrc = lpSrc || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintLp, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
608
+ const lpPosition = this.xponPda.marketLpPosition({ market: this.selfAddress, owner });
609
+ return this.coreProgram.methods
610
+ .marketDepositLp(new anchor_2.BN(amount.toString()))
611
+ .accountsStrict({
612
+ owner,
613
+ lpPosition,
614
+ tokenLpSrc: lpSrc,
615
+ tokenLpEscrow: this.tokenLpEscrow,
616
+ market: this.selfAddress,
617
+ addressLookupTable: this.addressLookupTable,
618
+ syProgram: this.syProgram,
619
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
620
+ mintLp: this.mintLp,
621
+ systemProgram: anchor_1.web3.SystemProgram.programId,
622
+ eventAuthority: this.vault.eventAuthority,
623
+ program: this.coreProgram.programId,
624
+ })
625
+ .remainingAccounts(this.cpiAccounts.getPositionState)
626
+ .instruction();
627
+ }
628
+ /** Withdraw LP tokens from the farming module */
629
+ async ixWithdrawLp({ owner, amount, lpDst }) {
630
+ lpDst = lpDst || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintLp, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
631
+ const lpPosition = this.xponPda.marketLpPosition({ market: this.selfAddress, owner });
632
+ return this.coreProgram.methods
633
+ .marketWithdrawLp(new anchor_2.BN(amount.toString()))
634
+ .accountsStrict({
635
+ owner,
636
+ lpPosition,
637
+ tokenLpDst: lpDst,
638
+ tokenLpEscrow: this.tokenLpEscrow,
639
+ market: this.selfAddress,
640
+ addressLookupTable: this.addressLookupTable,
641
+ mintLp: this.mintLp,
642
+ syProgram: this.syProgram,
643
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
644
+ systemProgram: anchor_1.web3.SystemProgram.programId,
645
+ eventAuthority: this.vault.eventAuthority,
646
+ program: this.coreProgram.programId,
647
+ })
648
+ .remainingAccounts(this.cpiAccounts.getPositionState)
649
+ .instruction();
650
+ }
651
+ async ixWrapperCollectInterest({ claimer, tokenSyDst }) {
652
+ const yieldPosition = this.xponPda.yieldPosition({ owner: claimer, vault: this.vault.selfAddress });
653
+ tokenSyDst = tokenSyDst || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, claimer, true, spl_token_1.TOKEN_PROGRAM_ID);
654
+ const tokenBaseClaimer = (0, spl_token_1.getAssociatedTokenAddressSync)(this.flavor.mintBase, claimer, true, this.flavor.baseTokenProgram);
655
+ const tokenBaseClaimerAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(claimer, tokenBaseClaimer, claimer, this.flavor.mintBase);
656
+ const tokenSyClaimer = (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, claimer, true);
657
+ const tokenSyClaimerAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(claimer, tokenSyClaimer, claimer, this.mintSy);
658
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
659
+ ...this.vault.cpiAccounts.getSyState,
660
+ ...this.vault.cpiAccounts.withdrawSy,
661
+ ]);
662
+ const redeemSyIx = await this.flavor.ixRedeemSy({
663
+ amountSy: "0",
664
+ redeemer: claimer,
665
+ redeemerBaseTokenAccount: tokenBaseClaimer,
666
+ redeemerSyTokenAccount: tokenSyDst,
667
+ });
668
+ const ix = await this.coreProgram.methods
669
+ .wrapperCollectInterest(redeemSyIx.keys.length)
670
+ .accountsStrict({
671
+ addressLookupTable: this.vault.addressLookupTable,
672
+ authority: this.vault.state.authority,
673
+ claimer,
674
+ escrowSy: this.vault.escrowSy,
675
+ syProgram: this.syProgram,
676
+ vault: this.vault.selfAddress,
677
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
678
+ treasurySyTokenAccount: this.vault.state.treasurySyTokenAccount,
679
+ yieldPosition: yieldPosition,
680
+ tokenSyDst,
681
+ eventAuthority: this.vault.eventAuthority,
682
+ program: this.coreProgram.programId,
683
+ })
684
+ .remainingAccounts(redeemSyIx.keys.concat(remainingAccounts))
685
+ .instruction();
686
+ return {
687
+ ixs: [
688
+ ...(await this.flavor.preIxs({ signer: claimer })),
689
+ ix,
690
+ ...(await this.flavor.postIxs({ signer: claimer })),
691
+ ],
692
+ setupIxs: [tokenBaseClaimerAtaIx, tokenSyClaimerAtaIx],
693
+ };
694
+ }
695
+ async ixWrapperBuyPt({ owner, ptOut, maxBaseIn, tokenSyTrader, tokenPtTrader, tokenBaseTrader, }) {
696
+ tokenSyTrader = tokenSyTrader || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
697
+ tokenPtTrader = tokenPtTrader || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
698
+ tokenBaseTrader =
699
+ tokenBaseTrader || (0, spl_token_1.getAssociatedTokenAddressSync)(this.flavor.mintBase, owner, true, this.flavor.baseTokenProgram);
700
+ const tokenSyTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenSyTrader, owner, this.mintSy);
701
+ const tokenPtTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenPtTrader, owner, this.mintPt);
702
+ const tokenBaseTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenBaseTrader, owner, this.flavor.mintBase);
703
+ const mintSyIx = await this.flavor.ixMintSy({
704
+ amountBase: "0",
705
+ depositor: owner,
706
+ depositorBaseTokenAccount: tokenBaseTrader,
707
+ depositorSyTokenAccount: tokenSyTrader,
708
+ });
709
+ const mintSyRemAccounts = mintSyIx.keys;
710
+ console.log("mintSyRemAccounts", mintSyRemAccounts);
711
+ mintSyRemAccounts.push({
712
+ pubkey: this.coreProgram.programId,
713
+ isWritable: false,
714
+ isSigner: false,
715
+ });
716
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
717
+ ...this.cpiAccounts.getSyState,
718
+ ...this.cpiAccounts.depositSy,
719
+ // ...this.cpiAccounts.withdrawSy,
720
+ ]);
721
+ const ix = await this.coreProgram.methods
722
+ .wrapperBuyPt(new anchor_2.BN(ptOut.toString()), new anchor_2.BN(maxBaseIn.toString()), mintSyRemAccounts.length)
723
+ .accountsStrict({
724
+ addressLookupTable: this.addressLookupTable,
725
+ buyer: owner,
726
+ market: this.selfAddress,
727
+ tokenSyTrader,
728
+ tokenPtTrader,
729
+ tokenSyEscrow: this.tokenSyEscrow,
730
+ tokenPtEscrow: this.tokenPtEscrow,
731
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
732
+ syProgram: this.syProgram,
733
+ tokenFeeTreasurySy: this.state.tokenFeeTreasurySy,
734
+ eventAuthority: this.vault.eventAuthority,
735
+ program: this.coreProgram.programId,
736
+ })
737
+ .remainingAccounts(mintSyRemAccounts.concat(remainingAccounts))
738
+ .instruction();
739
+ return {
740
+ ixs: [...(await this.flavor.preIxs({ signer: owner })), ix, ...(await this.flavor.postIxs({ signer: owner }))],
741
+ setupIxs: [tokenSyTraderAtaIx, tokenPtTraderAtaIx, tokenBaseTraderAtaIx],
742
+ };
743
+ }
744
+ async ixWrapperSellPt({ owner, amount, minBaseOut, tokenSyTrader, tokenPtTrader, tokenBaseTrader, }) {
745
+ tokenSyTrader = tokenSyTrader || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
746
+ tokenPtTrader = tokenPtTrader || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
747
+ tokenBaseTrader =
748
+ tokenBaseTrader || (0, spl_token_1.getAssociatedTokenAddressSync)(this.flavor.mintBase, owner, true, this.flavor.baseTokenProgram);
749
+ const tokenSyTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenSyTrader, owner, this.mintSy);
750
+ const tokenPtTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenPtTrader, owner, this.mintPt);
751
+ const tokenBaseTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenBaseTrader, owner, this.flavor.mintBase);
752
+ const redeemSyIx = await this.flavor.ixRedeemSy({
753
+ amountSy: "0",
754
+ redeemer: owner,
755
+ redeemerBaseTokenAccount: tokenBaseTrader,
756
+ redeemerSyTokenAccount: tokenSyTrader,
757
+ });
758
+ const redeemSyRemAccounts = redeemSyIx.keys;
759
+ redeemSyRemAccounts.push({
760
+ pubkey: this.coreProgram.programId,
761
+ isWritable: false,
762
+ isSigner: false,
763
+ });
764
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([...this.cpiAccounts.getSyState, ...this.cpiAccounts.withdrawSy]);
765
+ const ix = await this.coreProgram.methods
766
+ .wrapperSellPt(new anchor_2.BN(amount.toString()), new anchor_2.BN(minBaseOut.toString()), redeemSyRemAccounts.length)
767
+ .accountsStrict({
768
+ seller: owner,
769
+ market: this.selfAddress,
770
+ tokenPtTrader,
771
+ addressLookupTable: this.addressLookupTable,
772
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
773
+ syProgram: this.syProgram,
774
+ tokenSyTrader,
775
+ tokenPtEscrow: this.tokenPtEscrow,
776
+ tokenSyEscrow: this.tokenSyEscrow,
777
+ tokenFeeTreasurySy: this.state.tokenFeeTreasurySy,
778
+ eventAuthority: this.vault.eventAuthority,
779
+ program: this.coreProgram.programId,
780
+ })
781
+ .remainingAccounts(redeemSyRemAccounts.concat(remainingAccounts))
782
+ .instruction();
783
+ return {
784
+ ixs: [...(await this.flavor.preIxs({ signer: owner })), ix, ...(await this.flavor.postIxs({ signer: owner }))],
785
+ setupIxs: [tokenSyTraderAtaIx, tokenPtTraderAtaIx, tokenBaseTraderAtaIx],
786
+ };
787
+ }
788
+ async ixWrapperBuyYt({ owner, ytOut, maxBaseIn, tokenSyTrader, tokenPtTrader, tokenYtTrader, tokenBaseTrader, }) {
789
+ tokenSyTrader = tokenSyTrader || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
790
+ tokenPtTrader = tokenPtTrader || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
791
+ tokenYtTrader = tokenYtTrader || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintYt, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
792
+ tokenBaseTrader =
793
+ tokenBaseTrader || (0, spl_token_1.getAssociatedTokenAddressSync)(this.flavor.mintBase, owner, true, this.flavor.baseTokenProgram);
794
+ const tokenSyTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenSyTrader, owner, this.mintSy);
795
+ const tokenPtTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenPtTrader, owner, this.mintPt);
796
+ const tokenYtTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenYtTrader, owner, this.mintYt);
797
+ const mintSyIx = await this.flavor.ixMintSy({
798
+ amountBase: "0",
799
+ depositor: owner,
800
+ depositorBaseTokenAccount: tokenBaseTrader,
801
+ depositorSyTokenAccount: tokenSyTrader,
802
+ });
803
+ const mintSyRemAccounts = mintSyIx.keys;
804
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
805
+ ...this.cpiAccounts.getSyState,
806
+ ...this.vault.cpiAccounts.depositSy,
807
+ ...this.vault.cpiAccounts.getSyState,
808
+ ...this.cpiAccounts.withdrawSy,
809
+ ...this.cpiAccounts.getPositionState,
810
+ ]);
811
+ const allRemainingAccounts = mintSyRemAccounts.concat(remainingAccounts);
812
+ const ix1 = await this.coreProgram.methods
813
+ .wrapperBuyYt(new anchor_2.BN(ytOut.toString()), new anchor_2.BN(maxBaseIn.toString()), mintSyRemAccounts.length)
814
+ .accountsStrict({
815
+ buyer: owner,
816
+ market: this.selfAddress,
817
+ tokenSyTrader,
818
+ tokenYtTrader,
819
+ tokenPtTrader,
820
+ tokenSyEscrow: this.tokenSyEscrow,
821
+ tokenPtEscrow: this.tokenPtEscrow,
822
+ marketAddressLookupTable: this.addressLookupTable,
823
+ vault: this.vault.selfAddress,
824
+ vaultAuthority: this.vault.authority,
825
+ tokenSyEscrowVault: this.vault.escrowSy,
826
+ vaultAddressLookupTable: this.vault.addressLookupTable,
827
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
828
+ syProgram: this.syProgram,
829
+ mintPt: this.vault.mintPt,
830
+ yieldPosition: this.vault.state.yieldPositonAddress,
831
+ mintYt: this.vault.mintYt,
832
+ escrowYt: this.vault.escrowYt,
833
+ systemProgram: anchor_1.web3.SystemProgram.programId,
834
+ userYieldPosition: this.xponPda.yieldPosition({ vault: this.vault.selfAddress, owner }),
835
+ tokenFeeTreasurySy: this.state.tokenFeeTreasurySy,
836
+ eventAuthority: this.vault.eventAuthority,
837
+ program: this.coreProgram.programId,
838
+ })
839
+ .remainingAccounts(allRemainingAccounts)
840
+ .instruction();
841
+ const ix2 = await this.coreProgram.methods
842
+ .depositYt(new anchor_2.BN(ytOut.toString()))
843
+ .accountsStrict({
844
+ depositor: owner,
845
+ vault: this.vault.selfAddress,
846
+ userYieldPosition: this.xponPda.yieldPosition({ vault: this.vault.selfAddress, owner }),
847
+ ytSrc: tokenYtTrader,
848
+ escrowYt: this.vault.escrowYt,
849
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
850
+ syProgram: this.syProgram,
851
+ addressLookupTable: this.vault.addressLookupTable,
852
+ systemProgram: anchor_1.web3.SystemProgram.programId,
853
+ eventAuthority: this.vault.eventAuthority,
854
+ program: this.coreProgram.programId,
855
+ yieldPosition: this.vault.state.yieldPositonAddress,
856
+ })
857
+ .remainingAccounts(remainingAccounts)
858
+ .instruction();
859
+ return {
860
+ ixs: [
861
+ ...(await this.flavor.preIxs({ signer: owner })),
862
+ ix1,
863
+ ...(await this.flavor.postIxs({ signer: owner })),
864
+ ix2,
865
+ ],
866
+ setupIxs: [tokenSyTraderAtaIx, tokenPtTraderAtaIx, tokenYtTraderAtaIx],
867
+ };
868
+ }
869
+ async ixWrapperSellYt({ owner, amount, minBaseOut, tokenBaseTrader, tokenSyTrader, tokenYtTrader, tokenPtTrader, }) {
870
+ tokenBaseTrader =
871
+ tokenBaseTrader || (0, spl_token_1.getAssociatedTokenAddressSync)(this.flavor.mintBase, owner, true, this.flavor.baseTokenProgram);
872
+ tokenSyTrader = tokenSyTrader || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
873
+ tokenYtTrader = tokenYtTrader || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintYt, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
874
+ tokenPtTrader = tokenPtTrader || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
875
+ const tokenSyTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenSyTrader, owner, this.mintSy);
876
+ const tokenPtTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenPtTrader, owner, this.mintPt);
877
+ const tokenYtTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenYtTrader, owner, this.mintYt);
878
+ const tokenBaseTraderAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenBaseTrader, owner, this.flavor.mintBase);
879
+ const redeemSyIx = await this.flavor.ixRedeemSy({
880
+ amountSy: "0",
881
+ redeemer: owner,
882
+ redeemerBaseTokenAccount: tokenBaseTrader,
883
+ redeemerSyTokenAccount: tokenSyTrader,
884
+ });
885
+ const redeemSyRemAccounts = redeemSyIx.keys;
886
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
887
+ ...this.cpiAccounts.getSyState,
888
+ ...this.cpiAccounts.withdrawSy,
889
+ ...this.vault.cpiAccounts.depositSy,
890
+ ]);
891
+ console.log(" remaining accounts length", remainingAccounts.length);
892
+ // remainingAccounts.push({
893
+ // pubkey: this.coreProgram.programId,
894
+ // isWritable: false,
895
+ // isSigner: false,
896
+ // })
897
+ const ix1 = await this.coreProgram.methods
898
+ .withdrawYt(new anchor_2.BN(amount.toString()))
899
+ .accountsStrict({
900
+ ytDst: tokenYtTrader,
901
+ escrowYt: this.vault.escrowYt,
902
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
903
+ syProgram: this.syProgram,
904
+ addressLookupTable: this.vault.addressLookupTable,
905
+ systemProgram: anchor_1.web3.SystemProgram.programId,
906
+ eventAuthority: this.vault.eventAuthority,
907
+ program: this.coreProgram.programId,
908
+ yieldPosition: this.vault.state.yieldPositonAddress,
909
+ userYieldPosition: this.xponPda.yieldPosition({ vault: this.vault.selfAddress, owner }),
910
+ authority: this.vault.authority,
911
+ owner,
912
+ vault: this.vault.selfAddress,
913
+ })
914
+ .remainingAccounts(remainingAccounts)
915
+ .instruction();
916
+ const ix2 = await this.coreProgram.methods
917
+ .wrapperSellYt(new anchor_2.BN(amount.toString()), new anchor_2.BN(minBaseOut.toString()), redeemSyRemAccounts.length)
918
+ .accountsStrict({
919
+ seller: owner,
920
+ market: this.selfAddress,
921
+ tokenYtTrader,
922
+ marketAddressLookupTable: this.addressLookupTable,
923
+ vault: this.vault.selfAddress,
924
+ vaultAuthority: this.vault.authority,
925
+ tokenPtTrader,
926
+ tokenPtEscrow: this.tokenPtEscrow,
927
+ tokenSyEscrowVault: this.vault.escrowSy,
928
+ vaultAddressLookupTable: this.vault.addressLookupTable,
929
+ yieldPosition: this.vault.state.yieldPositonAddress,
930
+ mintPt: this.vault.mintPt,
931
+ mintYt: this.vault.mintYt,
932
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
933
+ syProgram: this.syProgram,
934
+ tokenSyTrader,
935
+ tokenSyEscrow: this.tokenSyEscrow,
936
+ tokenFeeTreasurySy: this.state.tokenFeeTreasurySy,
937
+ eventAuthority: this.vault.eventAuthority,
938
+ program: this.coreProgram.programId,
939
+ })
940
+ .remainingAccounts(redeemSyRemAccounts.concat(remainingAccounts))
941
+ .instruction();
942
+ return {
943
+ ixs: [
944
+ ix1,
945
+ ...(await this.flavor.preIxs({ signer: owner })),
946
+ ix2,
947
+ ...(await this.flavor.postIxs({ signer: owner })),
948
+ ],
949
+ setupIxs: [tokenSyTraderAtaIx, tokenPtTraderAtaIx, tokenYtTraderAtaIx, tokenBaseTraderAtaIx],
950
+ };
951
+ }
952
+ async ixCollectMarketEmission({ owner, emissionIndex, emissionDst, }) {
953
+ const emission = this.emissions[emissionIndex];
954
+ const tokenEmissionDst = emissionDst || (0, spl_token_1.getAssociatedTokenAddressSync)(emission.mint, owner, true, emission.tokenProgramAddress);
955
+ const tokenEmissionDstIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenEmissionDst, owner, emission.mint);
956
+ const ix = await this.coreProgram.methods
957
+ .marketCollectEmission(emissionIndex)
958
+ .accountsStrict({
959
+ addressLookupTable: this.addressLookupTable,
960
+ lpPosition: this.xponPda.marketLpPosition({ market: this.selfAddress, owner }),
961
+ market: this.selfAddress,
962
+ owner,
963
+ syProgram: this.syProgram,
964
+ tokenEmissionDst,
965
+ tokenEmissionEscrow: this.marketEmissions.trackers[emissionIndex].tokenEscrow,
966
+ tokenProgram: emission.tokenProgramAddress,
967
+ program: this.coreProgram.programId,
968
+ eventAuthority: this.eventAuthority,
969
+ })
970
+ .remainingAccounts(this.cpiAccounts.claimEmission[emissionIndex])
971
+ .instruction();
972
+ return {
973
+ ixs: [ix],
974
+ setupIxs: [tokenEmissionDstIx],
975
+ };
976
+ }
977
+ /** Provide liquidity from a base asset - and receive YT and LP tokens in return */
978
+ async ixProvideLiquidityNoPriceImpact({ depositor, amountBase, minLpOut, tokenSyDepositor, tokenYtDepositor, tokenPtDepositor, tokenBaseDepositor, tokenLpDepositor, }) {
979
+ tokenSyDepositor = tokenSyDepositor || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, depositor, true, spl_token_1.TOKEN_PROGRAM_ID);
980
+ tokenYtDepositor = tokenYtDepositor || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintYt, depositor, true, spl_token_1.TOKEN_PROGRAM_ID);
981
+ tokenPtDepositor = tokenPtDepositor || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, depositor, true, spl_token_1.TOKEN_PROGRAM_ID);
982
+ tokenBaseDepositor =
983
+ tokenBaseDepositor ||
984
+ (0, spl_token_1.getAssociatedTokenAddressSync)(this.flavor.mintBase, depositor, true, this.flavor.baseTokenProgram);
985
+ tokenLpDepositor = tokenLpDepositor || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintLp, depositor, true, spl_token_1.TOKEN_PROGRAM_ID);
986
+ const tokenSyDepositorAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(depositor, tokenSyDepositor, depositor, this.mintSy);
987
+ const tokenYtDepositorAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(depositor, tokenYtDepositor, depositor, this.mintYt);
988
+ const tokenPtDepositorAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(depositor, tokenPtDepositor, depositor, this.mintPt);
989
+ const tokenLpDepositorAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(depositor, tokenLpDepositor, depositor, this.mintLp);
990
+ const amountBaseBn = new anchor_2.BN(amountBase.toString());
991
+ const minLpOutBn = new anchor_2.BN(minLpOut.toString());
992
+ // TODO - fix this
993
+ const mintSyIx = await this.flavor.ixMintSy({
994
+ // argument does not matter - since we are just getting the keys
995
+ amountBase: "0",
996
+ depositor,
997
+ depositorBaseTokenAccount: tokenBaseDepositor,
998
+ depositorSyTokenAccount: tokenSyDepositor,
999
+ });
1000
+ const mintSyRemAccounts = mintSyIx.keys;
1001
+ // Log vault accounts before filtering
1002
+ const beforeVaultAccounts = [...this.vault.cpiAccounts.getSyState, ...this.vault.cpiAccounts.depositSy];
1003
+ console.log("Before filtering vault accounts:", beforeVaultAccounts.length, "accounts");
1004
+ // Filter out TOKEN_PROGRAM_ID and SystemProgram.programId from vault remaining accounts
1005
+ const vaultCpiRemainingAccounts = beforeVaultAccounts.filter((account) => account.pubkey.toBase58() !== spl_token_1.TOKEN_PROGRAM_ID.toBase58());
1006
+ // Log vault accounts after filtering
1007
+ console.log("After filtering vault accounts:", vaultCpiRemainingAccounts.length, "accounts");
1008
+ // Log market accounts before filtering
1009
+ const beforeMarketAccounts = [...this.cpiAccounts.depositSy];
1010
+ console.log("Before filtering market accounts:", beforeMarketAccounts.length, "accounts");
1011
+ // Filter out TOKEN_PROGRAM_ID and SystemProgram.programId from market remaining accounts
1012
+ const marketCpiRemainingAccounts = beforeMarketAccounts.filter((account) => account.pubkey.toBase58() !== spl_token_1.TOKEN_PROGRAM_ID.toBase58() &&
1013
+ account.pubkey.toBase58() !== anchor_1.web3.SystemProgram.programId.toBase58() &&
1014
+ account.pubkey.toBase58() !== this.selfAddress.toBase58());
1015
+ // Log market accounts after filtering
1016
+ console.log("After filtering market accounts:", marketCpiRemainingAccounts.length, "accounts");
1017
+ // These remaining accounts can be in any order, and they can be unique-ified
1018
+ const unorderedRemainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
1019
+ ...vaultCpiRemainingAccounts,
1020
+ ...marketCpiRemainingAccounts,
1021
+ ]);
1022
+ const allRemainingAccounts = [...mintSyRemAccounts, ...unorderedRemainingAccounts];
1023
+ const lpPosition = this.xponPda.marketLpPosition({ market: this.selfAddress, owner: depositor });
1024
+ const ix = await this.coreProgram.methods
1025
+ .wrapperProvideLiquidity(amountBaseBn, minLpOutBn, mintSyRemAccounts.length)
1026
+ .accountsStrict({
1027
+ depositor,
1028
+ authority: this.vault.authority,
1029
+ vault: this.vault.selfAddress,
1030
+ market: this.selfAddress,
1031
+ tokenPtEscrow: this.tokenPtEscrow,
1032
+ tokenSyEscrow: this.tokenSyEscrow,
1033
+ tokenLpDst: tokenLpDepositor,
1034
+ mintLp: this.mintLp,
1035
+ escrowSy: this.vault.escrowSy,
1036
+ escrowYt: this.vault.escrowYt,
1037
+ tokenSyDepositor,
1038
+ tokenYtDepositor,
1039
+ tokenPtDepositor,
1040
+ mintYt: this.vault.mintYt,
1041
+ mintPt: this.vault.mintPt,
1042
+ userYieldPosition: this.xponPda.yieldPosition({ vault: this.vault.selfAddress, owner: depositor }),
1043
+ systemProgram: anchor_1.web3.SystemProgram.programId,
1044
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
1045
+ syProgram: this.syProgram,
1046
+ marketAddressLookupTable: this.addressLookupTable,
1047
+ vaultAddressLookupTable: this.vault.addressLookupTable,
1048
+ vaultRobotYieldPosition: this.vault.state.yieldPositonAddress,
1049
+ eventAuthority: this.vault.eventAuthority,
1050
+ program: this.coreProgram.programId,
1051
+ lpPosition,
1052
+ tokenLpEscrow: this.tokenLpEscrow,
1053
+ })
1054
+ .remainingAccounts(allRemainingAccounts)
1055
+ .instruction();
1056
+ console.log("ix accounts length", ix.keys.length);
1057
+ return {
1058
+ ixs: [
1059
+ ...(await this.flavor.preIxs({ signer: depositor })),
1060
+ ix,
1061
+ ...(await this.flavor.postIxs({ signer: depositor })),
1062
+ ],
1063
+ setupIxs: [tokenSyDepositorAtaIx, tokenYtDepositorAtaIx, tokenPtDepositorAtaIx, tokenLpDepositorAtaIx],
1064
+ };
1065
+ }
1066
+ async ixProvideLiquidityBase({ depositor, amountBase, minLpOut, externalPtToBuy, externalSyConstraint, tokenSyDepositor, tokenYtDepositor, tokenPtDepositor, tokenBaseDepositor, tokenLpDepositor, }) {
1067
+ tokenSyDepositor = tokenSyDepositor || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, depositor, true, spl_token_1.TOKEN_PROGRAM_ID);
1068
+ tokenYtDepositor = tokenYtDepositor || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintYt, depositor, true, spl_token_1.TOKEN_PROGRAM_ID);
1069
+ tokenPtDepositor = tokenPtDepositor || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, depositor, true, spl_token_1.TOKEN_PROGRAM_ID);
1070
+ tokenBaseDepositor =
1071
+ tokenBaseDepositor ||
1072
+ (0, spl_token_1.getAssociatedTokenAddressSync)(this.flavor.mintBase, depositor, true, this.flavor.baseTokenProgram);
1073
+ tokenLpDepositor = tokenLpDepositor || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintLp, depositor, true, spl_token_1.TOKEN_PROGRAM_ID);
1074
+ const tokenSyAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(depositor, tokenSyDepositor, depositor, this.mintSy);
1075
+ const tokenYtAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(depositor, tokenYtDepositor, depositor, this.mintYt);
1076
+ const tokenPtAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(depositor, tokenPtDepositor, depositor, this.mintPt);
1077
+ const tokenBaseAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(depositor, tokenBaseDepositor, depositor, this.flavor.mintBase, this.flavor.baseTokenProgram);
1078
+ const tokenLpAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(depositor, tokenLpDepositor, depositor, this.mintLp);
1079
+ const lpPosition = this.xponPda.marketLpPosition({ market: this.selfAddress, owner: depositor });
1080
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
1081
+ ...this.cpiAccounts.depositSy,
1082
+ ...this.cpiAccounts.getPositionState,
1083
+ ]);
1084
+ const mintSyIx = await this.flavor.ixMintSy({
1085
+ amountBase: "0",
1086
+ depositor,
1087
+ depositorBaseTokenAccount: tokenBaseDepositor,
1088
+ depositorSyTokenAccount: tokenSyDepositor,
1089
+ });
1090
+ const mintSyRemAccounts = mintSyIx.keys;
1091
+ const ix = await this.coreProgram.methods
1092
+ .wrapperProvideLiquidityBase(new anchor_2.BN(amountBase.toString()), new anchor_2.BN(minLpOut.toString()), mintSyRemAccounts.length, new anchor_2.BN(externalPtToBuy.toString()), new anchor_2.BN(externalSyConstraint.toString()))
1093
+ .accountsStrict({
1094
+ depositor,
1095
+ lpPosition,
1096
+ market: this.selfAddress,
1097
+ tokenPtEscrow: this.tokenPtEscrow,
1098
+ tokenSyEscrow: this.tokenSyEscrow,
1099
+ tokenLpDst: tokenLpDepositor,
1100
+ mintLp: this.mintLp,
1101
+ syProgram: this.syProgram,
1102
+ tokenFeeTreasurySy: this.state.tokenFeeTreasurySy,
1103
+ tokenLpEscrow: this.tokenLpEscrow,
1104
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
1105
+ marketAddressLookupTable: this.addressLookupTable,
1106
+ tokenPtDepositor,
1107
+ tokenSyDepositor,
1108
+ systemProgram: anchor_1.web3.SystemProgram.programId,
1109
+ eventAuthority: this.vault.eventAuthority,
1110
+ program: this.coreProgram.programId,
1111
+ })
1112
+ .remainingAccounts(mintSyRemAccounts.concat(remainingAccounts))
1113
+ .instruction();
1114
+ return {
1115
+ ixs: [
1116
+ ...(await this.flavor.preIxs({ signer: depositor })),
1117
+ ix,
1118
+ ...(await this.flavor.postIxs({ signer: depositor })),
1119
+ ],
1120
+ setupIxs: [tokenSyAtaIx, tokenYtAtaIx, tokenPtAtaIx, tokenBaseAtaIx, tokenLpAtaIx],
1121
+ };
1122
+ }
1123
+ async ixProvideLiquidityClassic({ depositor, amountBase, amountPt, minLpOut, tokenSyDepositor, tokenYtDepositor, tokenPtDepositor, tokenBaseDepositor, tokenLpDepositor, }) {
1124
+ tokenSyDepositor = tokenSyDepositor || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, depositor, true, spl_token_1.TOKEN_PROGRAM_ID);
1125
+ tokenYtDepositor = tokenYtDepositor || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintYt, depositor, true, spl_token_1.TOKEN_PROGRAM_ID);
1126
+ tokenPtDepositor = tokenPtDepositor || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, depositor, true, spl_token_1.TOKEN_PROGRAM_ID);
1127
+ tokenBaseDepositor =
1128
+ tokenBaseDepositor ||
1129
+ (0, spl_token_1.getAssociatedTokenAddressSync)(this.flavor.mintBase, depositor, true, this.flavor.baseTokenProgram);
1130
+ tokenLpDepositor = tokenLpDepositor || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintLp, depositor, true, spl_token_1.TOKEN_PROGRAM_ID);
1131
+ const tokenSyAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(depositor, tokenSyDepositor, depositor, this.mintSy);
1132
+ const tokenYtAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(depositor, tokenYtDepositor, depositor, this.mintYt);
1133
+ const tokenPtAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(depositor, tokenPtDepositor, depositor, this.mintPt);
1134
+ const tokenLpAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(depositor, tokenLpDepositor, depositor, this.mintLp);
1135
+ const lpPosition = this.xponPda.marketLpPosition({ market: this.selfAddress, owner: depositor });
1136
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
1137
+ ...this.cpiAccounts.depositSy,
1138
+ ...this.cpiAccounts.getPositionState,
1139
+ ]);
1140
+ const mintSyIx = await this.flavor.ixMintSy({
1141
+ amountBase: "0",
1142
+ depositor,
1143
+ depositorBaseTokenAccount: tokenBaseDepositor,
1144
+ depositorSyTokenAccount: tokenSyDepositor,
1145
+ });
1146
+ const mintSyRemAccounts = mintSyIx.keys;
1147
+ const ix = await this.coreProgram.methods
1148
+ .wrapperProvideLiquidityClassic(new anchor_2.BN(amountBase.toString()), new anchor_2.BN(amountPt.toString()), new anchor_2.BN(minLpOut.toString()), mintSyRemAccounts.length)
1149
+ .accountsStrict({
1150
+ depositor,
1151
+ lpPosition,
1152
+ market: this.selfAddress,
1153
+ tokenPtEscrow: this.tokenPtEscrow,
1154
+ tokenSyEscrow: this.tokenSyEscrow,
1155
+ tokenLpDst: tokenLpDepositor,
1156
+ mintLp: this.mintLp,
1157
+ syProgram: this.syProgram,
1158
+ tokenLpEscrow: this.tokenLpEscrow,
1159
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
1160
+ marketAddressLookupTable: this.addressLookupTable,
1161
+ tokenPtDepositor,
1162
+ tokenSyDepositor,
1163
+ systemProgram: anchor_1.web3.SystemProgram.programId,
1164
+ eventAuthority: this.vault.eventAuthority,
1165
+ program: this.coreProgram.programId,
1166
+ })
1167
+ .remainingAccounts(mintSyRemAccounts.concat(remainingAccounts))
1168
+ .instruction();
1169
+ return {
1170
+ ixs: [
1171
+ ...(await this.flavor.preIxs({ signer: depositor })),
1172
+ ix,
1173
+ ...(await this.flavor.postIxs({ signer: depositor })),
1174
+ ],
1175
+ setupIxs: [tokenSyAtaIx, tokenYtAtaIx, tokenPtAtaIx, tokenLpAtaIx],
1176
+ };
1177
+ }
1178
+ async ixWithdrawLiquidityToBase({ owner, amountLp, minBaseOut, tokenSyWithdrawer, tokenYtWithdrawer, tokenPtWithdrawer, tokenBaseWithdrawer, tokenLpWithdrawer, }) {
1179
+ tokenSyWithdrawer = tokenSyWithdrawer || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
1180
+ tokenYtWithdrawer = tokenYtWithdrawer || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintYt, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
1181
+ tokenPtWithdrawer = tokenPtWithdrawer || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
1182
+ tokenBaseWithdrawer =
1183
+ tokenBaseWithdrawer ||
1184
+ (0, spl_token_1.getAssociatedTokenAddressSync)(this.flavor.mintBase, owner, true, this.flavor.baseTokenProgram);
1185
+ tokenLpWithdrawer = tokenLpWithdrawer || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintLp, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
1186
+ const tokenSyAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenSyWithdrawer, owner, this.mintSy);
1187
+ const tokenYtAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenYtWithdrawer, owner, this.mintYt);
1188
+ const tokenPtAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenPtWithdrawer, owner, this.mintPt);
1189
+ const tokenBaseAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenBaseWithdrawer, owner, this.flavor.mintBase, this.flavor.baseTokenProgram);
1190
+ const tokenLpAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenLpWithdrawer, owner, this.mintLp);
1191
+ const lpPosition = this.xponPda.marketLpPosition({ market: this.selfAddress, owner });
1192
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
1193
+ ...this.cpiAccounts.withdrawSy,
1194
+ ...this.cpiAccounts.getPositionState,
1195
+ ]);
1196
+ const redeemSyIx = await this.flavor.ixRedeemSy({
1197
+ amountSy: "0",
1198
+ redeemer: owner,
1199
+ redeemerBaseTokenAccount: tokenBaseWithdrawer,
1200
+ redeemerSyTokenAccount: tokenSyWithdrawer,
1201
+ });
1202
+ const redeemSyRemAccounts = redeemSyIx.keys;
1203
+ const minSyOut = Number(minBaseOut) / this.currentSyExchangeRate;
1204
+ const ix = await this.coreProgram.methods
1205
+ .wrapperWithdrawLiquidity(new anchor_2.BN(amountLp.toString()), new anchor_2.BN(minSyOut.toFixed(0).toString()), redeemSyRemAccounts.length)
1206
+ .accountsStrict({
1207
+ market: this.selfAddress,
1208
+ tokenPtEscrow: this.tokenPtEscrow,
1209
+ tokenSyEscrow: this.tokenSyEscrow,
1210
+ tokenLpSrc: tokenLpWithdrawer,
1211
+ lpPosition,
1212
+ marketAddressLookupTable: this.addressLookupTable,
1213
+ eventAuthority: this.vault.eventAuthority,
1214
+ program: this.coreProgram.programId,
1215
+ syProgram: this.syProgram,
1216
+ systemProgram: anchor_1.web3.SystemProgram.programId,
1217
+ tokenFeeTreasurySy: this.state.tokenFeeTreasurySy,
1218
+ tokenLpEscrow: this.tokenLpEscrow,
1219
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
1220
+ tokenPtWithdrawer,
1221
+ tokenSyWithdrawer,
1222
+ mintLp: this.mintLp,
1223
+ withdrawer: owner,
1224
+ })
1225
+ .remainingAccounts(redeemSyRemAccounts.concat(remainingAccounts))
1226
+ .instruction();
1227
+ return {
1228
+ ixs: [...(await this.flavor.preIxs({ signer: owner })), ix, ...(await this.flavor.postIxs({ signer: owner }))],
1229
+ setupIxs: [tokenSyAtaIx, tokenYtAtaIx, tokenPtAtaIx, tokenBaseAtaIx, tokenLpAtaIx],
1230
+ };
1231
+ }
1232
+ async ixWithdrawLiquidityClassic({ owner, amountLp, minBaseOut, tokenSyWithdrawer, tokenYtWithdrawer, tokenPtWithdrawer, tokenBaseWithdrawer, tokenLpWithdrawer, }) {
1233
+ tokenSyWithdrawer = tokenSyWithdrawer || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintSy, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
1234
+ tokenYtWithdrawer = tokenYtWithdrawer || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintYt, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
1235
+ tokenPtWithdrawer = tokenPtWithdrawer || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintPt, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
1236
+ tokenBaseWithdrawer =
1237
+ tokenBaseWithdrawer ||
1238
+ (0, spl_token_1.getAssociatedTokenAddressSync)(this.flavor.mintBase, owner, true, this.flavor.baseTokenProgram);
1239
+ tokenLpWithdrawer = tokenLpWithdrawer || (0, spl_token_1.getAssociatedTokenAddressSync)(this.mintLp, owner, true, spl_token_1.TOKEN_PROGRAM_ID);
1240
+ const tokenSyAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenSyWithdrawer, owner, this.mintSy);
1241
+ const tokenYtAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenYtWithdrawer, owner, this.mintYt);
1242
+ const tokenPtAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenPtWithdrawer, owner, this.mintPt);
1243
+ const tokenBaseAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenBaseWithdrawer, owner, this.flavor.mintBase, this.flavor.baseTokenProgram);
1244
+ const tokenLpAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenLpWithdrawer, owner, this.mintLp);
1245
+ const lpPosition = this.xponPda.marketLpPosition({ market: this.selfAddress, owner });
1246
+ const remainingAccounts = (0, utils_1.uniqueRemainingAccounts)([
1247
+ ...this.cpiAccounts.withdrawSy,
1248
+ ...this.cpiAccounts.getPositionState,
1249
+ ]);
1250
+ const redeemSyIx = await this.flavor.ixRedeemSy({
1251
+ amountSy: "0",
1252
+ redeemer: owner,
1253
+ redeemerBaseTokenAccount: tokenBaseWithdrawer,
1254
+ redeemerSyTokenAccount: tokenSyWithdrawer,
1255
+ });
1256
+ const redeemSyRemAccounts = redeemSyIx.keys;
1257
+ const ixn = await this.coreProgram.methods
1258
+ .wrapperWithdrawLiquidityClassic(new anchor_2.BN(amountLp.toString()), redeemSyRemAccounts.length)
1259
+ .accountsStrict({
1260
+ market: this.selfAddress,
1261
+ tokenPtEscrow: this.tokenPtEscrow,
1262
+ tokenSyEscrow: this.tokenSyEscrow,
1263
+ tokenLpSrc: tokenLpWithdrawer,
1264
+ lpPosition,
1265
+ marketAddressLookupTable: this.addressLookupTable,
1266
+ eventAuthority: this.vault.eventAuthority,
1267
+ program: this.coreProgram.programId,
1268
+ syProgram: this.syProgram,
1269
+ systemProgram: anchor_1.web3.SystemProgram.programId,
1270
+ tokenLpEscrow: this.tokenLpEscrow,
1271
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
1272
+ tokenPtWithdrawer,
1273
+ tokenSyWithdrawer,
1274
+ mintLp: this.mintLp,
1275
+ withdrawer: owner,
1276
+ })
1277
+ .remainingAccounts(redeemSyRemAccounts.concat(remainingAccounts))
1278
+ .instruction();
1279
+ return {
1280
+ ixs: [...(await this.flavor.preIxs({ signer: owner })), ixn, ...(await this.flavor.postIxs({ signer: owner }))],
1281
+ setupIxs: [tokenSyAtaIx, tokenYtAtaIx, tokenPtAtaIx, tokenBaseAtaIx, tokenLpAtaIx],
1282
+ };
1283
+ }
1284
+ async claimFarmEmissions({ owner, mint, tokenProgram, tokenDst, }) {
1285
+ tokenDst = tokenDst || (0, spl_token_1.getAssociatedTokenAddressSync)(mint, owner, true, tokenProgram);
1286
+ const lpPosition = this.xponPda.marketLpPosition({ market: this.selfAddress, owner });
1287
+ const tokenFarm = (0, spl_token_1.getAssociatedTokenAddressSync)(mint, this.selfAddress, true, tokenProgram);
1288
+ const tokenAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, tokenDst, owner, mint);
1289
+ const ix = await this.coreProgram.methods
1290
+ .claimFarmEmissions({ all: {} })
1291
+ .accountsStrict({
1292
+ market: this.selfAddress,
1293
+ lpPosition,
1294
+ mint,
1295
+ tokenFarm,
1296
+ owner,
1297
+ tokenDst,
1298
+ tokenProgram,
1299
+ eventAuthority: this.eventAuthority,
1300
+ program: this.coreProgram.programId,
1301
+ })
1302
+ .instruction();
1303
+ return {
1304
+ ixs: [ix],
1305
+ setupIxs: [tokenAtaIx],
1306
+ };
1307
+ }
1308
+ async ixAddStandaloneEmission({ signer, emissionMint, emissionTokenProgram = spl_token_1.TOKEN_PROGRAM_ID, altAddresses, cpiAccounts, }) {
1309
+ const altUtil = (0, altUtil_1.extendAddressLookupTable)(altAddresses, cpiAccounts);
1310
+ const tokenEmission = (0, spl_token_1.getAssociatedTokenAddressSync)(emissionMint, this.selfAddress, true, emissionTokenProgram);
1311
+ const ix = await this.coreProgram.methods
1312
+ .addMarketEmission(altUtil.cpiAccountIndexes)
1313
+ .accountsStrict({
1314
+ market: this.selfAddress,
1315
+ adminState: (0, utils_1.getExponentAdminStatePda)(),
1316
+ feePayer: signer,
1317
+ mintNew: emissionMint,
1318
+ signer,
1319
+ systemProgram: anchor_1.web3.SystemProgram.programId,
1320
+ tokenEmission,
1321
+ tokenProgram: emissionTokenProgram,
1322
+ })
1323
+ .instruction();
1324
+ return {
1325
+ extendAddressLookupTableExtensionAccounts: altUtil.addressLookupTableExtension,
1326
+ addMarketEmissionIx: ix,
1327
+ };
1328
+ }
1329
+ async addFarm({ signer, farmMint, farmRewardTokenProgram, emissionsRate, untilTimestamp, farmRewardSrc, feePayer, }) {
1330
+ feePayer = feePayer || signer;
1331
+ const farmRewardEscrow = (0, spl_token_1.getAssociatedTokenAddressSync)(farmMint, this.selfAddress, true, farmRewardTokenProgram);
1332
+ farmRewardSrc = farmRewardSrc || (0, spl_token_1.getAssociatedTokenAddressSync)(farmMint, signer, true, farmRewardTokenProgram);
1333
+ const ix = await this.coreProgram.methods
1334
+ .addFarm(new anchor_2.BN(emissionsRate), untilTimestamp)
1335
+ .accountsStrict({
1336
+ adminState: (0, utils_1.getExponentAdminStatePda)(),
1337
+ market: this.selfAddress,
1338
+ feePayer,
1339
+ signer,
1340
+ mintNew: farmMint,
1341
+ tokenFarm: farmRewardEscrow,
1342
+ tokenProgram: farmRewardTokenProgram,
1343
+ systemProgram: anchor_1.web3.SystemProgram.programId,
1344
+ tokenSource: farmRewardSrc,
1345
+ })
1346
+ .instruction();
1347
+ return {
1348
+ ixs: [ix],
1349
+ };
1350
+ }
1351
+ /** Calculate available liquidity for PT trades
1352
+ * @param is_buy - true if buying PT with SY, false if selling PT for SY
1353
+ * @param size_pt - amount of PT to trade (in PT decimals)
1354
+ * @returns amount of PT that can be traded given current liquidity
1355
+ */
1356
+ liquidityAvailable(is_buy, size_pt) {
1357
+ const calc = this.marketCalculator();
1358
+ if (is_buy) {
1359
+ // When buying PT, we're limited by SY liquidity
1360
+ // Convert PT amount to SY using current price
1361
+ const syNeeded = Number(size_pt) * calc.exchangeRate;
1362
+ // Available SY in the market
1363
+ const syAvailable = Number(this.syBalance);
1364
+ if (syNeeded <= syAvailable) {
1365
+ return size_pt;
1366
+ }
1367
+ else {
1368
+ // Calculate max PT that can be bought with available SY
1369
+ return BigInt(Math.floor(syAvailable / calc.exchangeRate));
1370
+ }
1371
+ }
1372
+ else {
1373
+ // When selling PT, we're limited by PT liquidity in the market
1374
+ const ptAvailable = this.ptBalance;
1375
+ if (size_pt <= ptAvailable) {
1376
+ return size_pt;
1377
+ }
1378
+ else {
1379
+ return ptAvailable;
1380
+ }
1381
+ }
1382
+ }
1383
+ }
1384
+ exports.Market = Market;
1385
+ function toJson(m) {
1386
+ const c = m.marketCalculator();
1387
+ return {
1388
+ treasurySyTokenAccount: m.state.tokenFeeTreasurySy.toBase58(),
1389
+ address: m.selfAddress.toBase58(),
1390
+ addressLookupTable: m.addressLookupTable.toBase58(),
1391
+ tokenSyEscrow: m.tokenSyEscrow.toBase58(),
1392
+ tokenPtEscrow: m.tokenPtEscrow.toBase58(),
1393
+ tokenLpEscrow: m.tokenLpEscrow.toBase58(),
1394
+ lpSupply: m.state.lpSupply.toString(),
1395
+ syProgram: m.state.syProgram.toBase58(),
1396
+ mintPt: m.state.mintPt.toBase58(),
1397
+ mintSy: m.state.mintSy.toBase58(),
1398
+ mintLp: m.state.mintLp.toBase58(),
1399
+ feeTreasurySyBps: m.state.feeTreasurySyBps,
1400
+ ptBalance: m.state.ptBalance.toString(),
1401
+ syBalance: m.state.syBalance.toString(),
1402
+ currentSyRate: m.flavor.currentSyExchangeRate,
1403
+ expirationTs: m.state.expirationTs,
1404
+ expirationDate: new Date(m.state.expirationTs * 1000).toISOString(),
1405
+ lnFeeRateRoot: m.state.lnFeeRateRoot,
1406
+ rateScalarRoot: m.state.rateScalarRoot,
1407
+ lastLnImpliedRate: m.state.lastLnImpliedRate,
1408
+ currentPtPriceInSy: m.currentPtPriceInSy,
1409
+ currentPtPriceInAsset: m.currentPtPriceInAsset,
1410
+ secondsRemaining: m.secondsRemaining,
1411
+ proportionPtInAsset: c.proportionPtInAsset,
1412
+ proportionPtInSy: c.proportionPtInSy,
1413
+ currentFeeRate: c.feeRate,
1414
+ currentRateScalar: c.rateScalar,
1415
+ currentRateAnchor: c.findRateAnchor(),
1416
+ cpiAccounts: (0, exponent_ix_2.serializeCpiAccountsRaw)(m.cpiAccounts),
1417
+ emissions: {
1418
+ trackers: m.marketEmissions.trackers.map((e) => ({
1419
+ tokenEscrow: e.tokenEscrow.toBase58(),
1420
+ lpShareIndex: e.lpShareIndex,
1421
+ lastSeenStaged: e.lastSeenStaged,
1422
+ })),
1423
+ },
1424
+ ptApr: m.ptApr,
1425
+ lpEscrowAmount: m.state.lpEscrowAmount.toString(),
1426
+ maxLpSupply: m.state.maxLpSupply.toString(),
1427
+ liquidityNetBalanceLimits: {
1428
+ windowStartTimestamp: m.state.liquidityNetBalanceLimits.windowStartTimestamp,
1429
+ windowStartNetBalance: m.state.liquidityNetBalanceLimits.windowStartNetBalance.toString(),
1430
+ maxNetBalanceChangeNegativePercentage: m.state.liquidityNetBalanceLimits.maxNetBalanceChangeNegativePercentage,
1431
+ maxNetBalanceChangePositivePercentage: m.state.liquidityNetBalanceLimits.maxNetBalanceChangePositivePercentage,
1432
+ windowDurationSeconds: m.state.liquidityNetBalanceLimits.windowDurationSeconds,
1433
+ },
1434
+ lpFarm: {
1435
+ lastSeenTimestamp: m.state.lpFarm.lastSeenTimestamp,
1436
+ farmEmissions: m.state.lpFarm.farmEmissions.map((e) => ({
1437
+ mint: e.mint.toBase58(),
1438
+ tokenRate: e.tokenRate.toString(),
1439
+ expiryTimestamp: e.expiryTimestamp,
1440
+ index: precise_number_1.PreciseNumber.fromRaw(e.index[0]).valueString,
1441
+ })),
1442
+ },
1443
+ };
1444
+ }
1445
+ //# sourceMappingURL=market.js.map