@exponent-labs/exponent-sdk 0.1.6 → 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
package/src/flavors.ts CHANGED
@@ -20,9 +20,11 @@ import {
20
20
  FlavorPerena,
21
21
  FlavorPerenaState,
22
22
  FlavorPerenaStateJson,
23
+ fromAdditionalDataGenericJson,
24
+ fromInterfaceTypeGenericJson,
23
25
  MintSyArgs,
24
26
  RedeemSyArgs,
25
- fromInterfaceTypeGenericJson,
27
+ toAdditionalDataGenericJson,
26
28
  toInterfaceTypeGenericJson,
27
29
  } from "@exponent-labs/exponent-types"
28
30
  import { GenericSySdk } from "@exponent-labs/generic-sy-sdk"
@@ -90,7 +92,7 @@ export function deserializeFlavorMarginfi(flavor: FlavorMarginfiStateJson): Flav
90
92
  mintBase: new web3.PublicKey(flavor.mintBase),
91
93
  baseTokenProgram: new web3.PublicKey(flavor.baseTokenProgram),
92
94
  emissions: flavor.emissions.map((e) => ({
93
- exchangeRate: { 0: [new BN(PreciseNumber.fromRaw([new BN(e.exchangeRate)]).valueString)] },
95
+ exchangeRate: new PreciseNumber(e.exchangeRate.toString()).anchorify(),
94
96
  mint: new web3.PublicKey(e.mint),
95
97
  tokenProgram: new web3.PublicKey(e.tokenProgram),
96
98
  })),
@@ -121,8 +123,8 @@ export function deserializeFlavorMarginfi(flavor: FlavorMarginfiStateJson): Flav
121
123
  mint: new web3.PublicKey(emission.mint),
122
124
  tokenProgram: new web3.PublicKey(emission.tokenProgram),
123
125
  escrowAccount: new web3.PublicKey(emission.escrowAccount),
124
- index: { 0: [new BN(emission.index)] },
125
- lastSeenIndex: { 0: [new BN(emission.lastSeenIndex)] },
126
+ index: new PreciseNumber(emission.index.toString()).anchorify(),
127
+ lastSeenIndex: new PreciseNumber(emission.lastSeenIndex.toString()).anchorify(),
126
128
  lastSeenTotalAccruedEmissions: new BN(emission.lastSeenTotalAccruedEmissions),
127
129
  totalClaimedEmissions: new BN(emission.totalClaimedEmissions),
128
130
  treasuryEmission: new BN(emission.treasuryEmission),
@@ -151,6 +153,7 @@ export function serializeFlavorKamino(flavor: FlavorKaminoState): FlavorKaminoSt
151
153
  tokenProgramBase: flavor.kaminoSyState.tokenProgramBase.toString(),
152
154
  klendProgramId: flavor.kaminoSyState.klendProgramId.toString(),
153
155
  klendMarketId: flavor.kaminoSyState.klendMarketId.toString(),
156
+ scopePriceFeed: flavor.kaminoSyState.scopePriceFeed?.toString(),
154
157
  account: {
155
158
  kaminoReserve: flavor.kaminoSyState.account.kaminoReserve.toString(),
156
159
  kaminoObligation: flavor.kaminoSyState.account.kaminoObligation.toString(),
@@ -184,7 +187,7 @@ export function deserializeFlavorKamino(flavor: FlavorKaminoStateJson): FlavorKa
184
187
  mintBase: new web3.PublicKey(flavor.mintBase),
185
188
  baseTokenProgram: new web3.PublicKey(flavor.baseTokenProgram),
186
189
  emissions: flavor.emissions.map((e) => ({
187
- exchangeRate: { 0: [new BN(PreciseNumber.fromRaw([new BN(e.exchangeRate)]).valueString)] },
190
+ exchangeRate: new PreciseNumber(e.exchangeRate.toString()).anchorify(),
188
191
  mint: new web3.PublicKey(e.mint),
189
192
  tokenProgram: new web3.PublicKey(e.tokenProgram),
190
193
  })),
@@ -196,6 +199,9 @@ export function deserializeFlavorKamino(flavor: FlavorKaminoStateJson): FlavorKa
196
199
  tokenProgramBase: new web3.PublicKey(flavor.kaminoSyState.tokenProgramBase),
197
200
  klendProgramId: new web3.PublicKey(flavor.kaminoSyState.klendProgramId),
198
201
  klendMarketId: new web3.PublicKey(flavor.kaminoSyState.klendMarketId),
202
+ scopePriceFeed: flavor.kaminoSyState.scopePriceFeed
203
+ ? new web3.PublicKey(flavor.kaminoSyState.scopePriceFeed)
204
+ : undefined,
199
205
  account: {
200
206
  kaminoReserve: new web3.PublicKey(flavor.kaminoSyState.account.kaminoReserve),
201
207
  kaminoObligation: new web3.PublicKey(flavor.kaminoSyState.account.kaminoObligation),
@@ -211,8 +217,8 @@ export function deserializeFlavorKamino(flavor: FlavorKaminoStateJson): FlavorKa
211
217
  mint: new web3.PublicKey(emission.mint),
212
218
  tokenProgram: new web3.PublicKey(emission.tokenProgram),
213
219
  escrowAccount: new web3.PublicKey(emission.escrowAccount),
214
- index: { 0: [new BN(emission.index)] },
215
- lastSeenIndex: { 0: [new BN(emission.lastSeenIndex)] },
220
+ index: new PreciseNumber(emission.index.toString()).anchorify(),
221
+ lastSeenIndex: new PreciseNumber(emission.lastSeenIndex.toString()).anchorify(),
216
222
  lastSeenTotalAccruedEmissions: new BN(emission.lastSeenTotalAccruedEmissions),
217
223
  totalClaimedEmissions: new BN(emission.totalClaimedEmissions),
218
224
  treasuryEmission: new BN(emission.treasuryEmission),
@@ -270,7 +276,7 @@ export function deserializeFlavorJitoRestaking(flavor: FlavorJitoRestakingStateJ
270
276
  mintBase: new web3.PublicKey(flavor.mintBase),
271
277
  baseTokenProgram: new web3.PublicKey(flavor.baseTokenProgram),
272
278
  emissions: flavor.emissions.map((e) => ({
273
- exchangeRate: { 0: [new BN(PreciseNumber.fromRaw([new BN(e.exchangeRate)]).valueString)] },
279
+ exchangeRate: new PreciseNumber(e.exchangeRate.toString()).anchorify(),
274
280
  mint: new web3.PublicKey(e.mint),
275
281
  tokenProgram: new web3.PublicKey(e.tokenProgram),
276
282
  })),
@@ -293,8 +299,8 @@ export function deserializeFlavorJitoRestaking(flavor: FlavorJitoRestakingStateJ
293
299
  mint: new web3.PublicKey(emission.mint),
294
300
  tokenProgram: new web3.PublicKey(emission.tokenProgram),
295
301
  escrowAccount: new web3.PublicKey(emission.escrowAccount),
296
- index: { 0: [new BN(emission.index)] },
297
- lastSeenIndex: { 0: [new BN(emission.lastSeenIndex)] },
302
+ index: new PreciseNumber(emission.index.toString()).anchorify(),
303
+ lastSeenIndex: new PreciseNumber(emission.lastSeenIndex.toString()).anchorify(),
298
304
  lastSeenTotalAccruedEmissions: new BN(emission.lastSeenTotalAccruedEmissions),
299
305
  totalClaimedEmissions: new BN(emission.totalClaimedEmissions),
300
306
  treasuryEmission: new BN(emission.treasuryEmission),
@@ -359,6 +365,9 @@ export function serializeFlavorGeneric(flavor: FlavorGenericState): FlavorGeneri
359
365
  selfAddress: flavor.genericSyState.selfAddress.toString(),
360
366
  syRate: flavor.genericSyState.syRate,
361
367
  tokenProgramBase: flavor.genericSyState.tokenProgramBase.toString(),
368
+ additionalData: flavor.genericSyState.additionalData
369
+ ? toAdditionalDataGenericJson(flavor.genericSyState.additionalData)
370
+ : undefined,
362
371
  account: {
363
372
  yieldBearingMint: flavor.genericSyState.account.yieldBearingMint.toString(),
364
373
  mintSy: flavor.genericSyState.account.mintSy.toString(),
@@ -367,9 +376,11 @@ export function serializeFlavorGeneric(flavor: FlavorGenericState): FlavorGeneri
367
376
  minRedeemSize: flavor.genericSyState.account.minRedeemSize.toString(),
368
377
  maxSySupply: flavor.genericSyState.account.maxSySupply.toString(),
369
378
  hook: {
370
- ...flavor.genericSyState.account.hook,
371
- preMintHookDiscriminator: Buffer.from(flavor.genericSyState.account.hook.preMintHookDiscriminator),
372
- postRedeemHookDiscriminator: Buffer.from(flavor.genericSyState.account.hook.postRedeemHookDiscriminator),
379
+ enabled: flavor.genericSyState.account.hook.enabled,
380
+ interfaceEmissionsAccountsUntil: flavor.genericSyState.account.hook.interfaceEmissionsAccountsUntil,
381
+ programId: flavor.genericSyState.account.hook.programId.toString(),
382
+ preMintHookDiscriminator: flavor.genericSyState.account.hook.preMintHookDiscriminator,
383
+ postRedeemHookDiscriminator: flavor.genericSyState.account.hook.postRedeemHookDiscriminator,
373
384
  },
374
385
  emissions: flavor.genericSyState.account.emissions.map((e) => ({
375
386
  mint: e.mint.toString(),
@@ -409,8 +420,8 @@ export function deserializeFlavorPerena(flavor: FlavorPerenaStateJson): FlavorPe
409
420
  mint: new web3.PublicKey(emission.mint),
410
421
  tokenProgram: new web3.PublicKey(emission.tokenProgram),
411
422
  escrowAccount: new web3.PublicKey(emission.escrowAccount),
412
- index: { 0: [new BN(emission.index)] },
413
- lastSeenIndex: { 0: [new BN(emission.lastSeenIndex)] },
423
+ index: new PreciseNumber(emission.index.toString()).anchorify(),
424
+ lastSeenIndex: new PreciseNumber(emission.lastSeenIndex.toString()).anchorify(),
414
425
  lastSeenTotalAccruedEmissions: new BN(emission.lastSeenTotalAccruedEmissions),
415
426
  totalClaimedEmissions: new BN(emission.totalClaimedEmissions),
416
427
  treasuryEmission: new BN(emission.treasuryEmission),
@@ -421,7 +432,7 @@ export function deserializeFlavorPerena(flavor: FlavorPerenaStateJson): FlavorPe
421
432
  tokenProgramBase: new web3.PublicKey(flavor.perenaSyState.tokenProgramBase),
422
433
  },
423
434
  emissions: flavor.emissions.map((e) => ({
424
- exchangeRate: { 0: [new BN(PreciseNumber.fromRaw([new BN(e.exchangeRate)]).valueString)] },
435
+ exchangeRate: new PreciseNumber(e.exchangeRate.toString()).anchorify(),
425
436
  mint: new web3.PublicKey(e.mint),
426
437
  tokenProgram: new web3.PublicKey(e.tokenProgram),
427
438
  })),
@@ -435,7 +446,7 @@ export function deserializeFlavorGeneric(flavor: FlavorGenericStateJson): Flavor
435
446
  mintBase: new web3.PublicKey(flavor.mintBase),
436
447
  baseTokenProgram: new web3.PublicKey(flavor.baseTokenProgram),
437
448
  emissions: flavor.emissions.map((e) => ({
438
- exchangeRate: { 0: [new BN(PreciseNumber.fromRaw([new BN(e.exchangeRate)]).valueString)] },
449
+ exchangeRate: new PreciseNumber(e.exchangeRate.toString()).anchorify(),
439
450
  mint: new web3.PublicKey(e.mint),
440
451
  tokenProgram: new web3.PublicKey(e.tokenProgram),
441
452
  })),
@@ -443,6 +454,9 @@ export function deserializeFlavorGeneric(flavor: FlavorGenericStateJson): Flavor
443
454
  selfAddress: new web3.PublicKey(flavor.genericSyState.selfAddress),
444
455
  syRate: flavor.genericSyState.syRate,
445
456
  tokenProgramBase: new web3.PublicKey(flavor.genericSyState.tokenProgramBase),
457
+ additionalData: flavor.genericSyState.additionalData
458
+ ? fromAdditionalDataGenericJson(flavor.genericSyState.additionalData)
459
+ : undefined,
446
460
  account: {
447
461
  mintSy: new web3.PublicKey(flavor.genericSyState.account.mintSy),
448
462
  yieldBearingMint: new web3.PublicKey(flavor.genericSyState.account.yieldBearingMint),
@@ -463,13 +477,13 @@ export function deserializeFlavorGeneric(flavor: FlavorGenericStateJson): Flavor
463
477
  mint: new web3.PublicKey(e.mint),
464
478
  tokenProgram: new web3.PublicKey(e.tokenProgram),
465
479
  escrowAccount: new web3.PublicKey(e.escrowAccount),
466
- index: { 0: [new BN(e.index)] },
467
- lastSeenIndex: { 0: [new BN(e.lastSeenIndex)] },
480
+ index: new PreciseNumber(e.index.toString()).anchorify(),
481
+ lastSeenIndex: new PreciseNumber(e.lastSeenIndex.toString()).anchorify(),
468
482
  lastSeenTotalAccruedEmissions: new BN(e.lastSeenTotalAccruedEmissions),
469
483
  totalClaimedEmissions: new BN(e.totalClaimedEmissions),
470
484
  treasuryEmission: new BN(e.treasuryEmission),
471
485
  })),
472
- index: { 0: [new BN(flavor.genericSyState.account.index)] },
486
+ index: new PreciseNumber(flavor.genericSyState.account.index.toString()).anchorify(),
473
487
  },
474
488
  },
475
489
  }
@@ -539,15 +553,15 @@ export function makeFlavorGenericSync(data: FlavorGenericState, syConfig?: { ski
539
553
  }
540
554
 
541
555
  export function flavorFinder(env: Environment, syProgram: web3.PublicKey): FlavorDiscriminator {
542
- if (env.marginfiSyProgramId.equals(syProgram)) {
556
+ if (env.marginfiSyProgramId?.equals(syProgram)) {
543
557
  return "marginfi"
544
- } else if (env.kaminoSyProgramId.equals(syProgram)) {
558
+ } else if (env.kaminoSyProgramId?.equals(syProgram)) {
545
559
  return "kamino"
546
- } else if (env.jitoRestakingSyProgramId.equals(syProgram)) {
560
+ } else if (env.jitoRestakingSyProgramId?.equals(syProgram)) {
547
561
  return "jitoRestaking"
548
- } else if (env.perenaSyProgramId.equals(syProgram)) {
562
+ } else if (env.perenaSyProgramId?.equals(syProgram)) {
549
563
  return "perena"
550
- } else if (env.genericSyProgramId.equals(syProgram)) {
564
+ } else if (env.genericSyProgramId?.equals(syProgram)) {
551
565
  return "generic"
552
566
  } else {
553
567
  throw new Error("Unknown flavor")
@@ -637,6 +651,8 @@ async function makeKaminoFlavor(
637
651
  const mintBase = reserveAcct.baseMint
638
652
 
639
653
  // TODO - don't do this
654
+ // Type error: 'a' is possibly 'null'.
655
+ // @ts-ignore
640
656
  const baseTokenProgram = await fetcher.connection.getAccountInfo(mintBase).then((a) => a.owner)
641
657
 
642
658
  const pda = new KaminoSyPda(new web3.PublicKey(KAMINO_STANDARD_PROGRAM_ID))
@@ -750,6 +766,10 @@ async function makeGenericFlavor(
750
766
  syMetaAddress: genericSyMeta,
751
767
  config: syConfig,
752
768
  })
769
+ // @ts-ignore
770
+ const preIxs = []
771
+ // @ts-ignore
772
+ const postIxs = []
753
773
 
754
774
  return {
755
775
  flavor: "generic",
@@ -758,8 +778,10 @@ async function makeGenericFlavor(
758
778
  baseTokenProgram: sySdk.tokenProgramBase,
759
779
  ixMintSy: (args) => sySdk.ixMintSy(args),
760
780
  ixRedeemSy: (args) => sySdk.ixRedeemSy(args),
761
- preIxs: async () => [],
762
- postIxs: async () => [],
781
+ // @ts-ignore
782
+ preIxs: async () => preIxs,
783
+ // @ts-ignore
784
+ postIxs: async () => postIxs,
763
785
  genericSyState: sySdk.state,
764
786
  emissions: sySdk.emissions.map((e) => ({
765
787
  exchangeRate: e.index,
@@ -768,3 +790,51 @@ async function makeGenericFlavor(
768
790
  })),
769
791
  }
770
792
  }
793
+
794
+ export function serializeFlavor(
795
+ flavor: Flavor,
796
+ ):
797
+ | FlavorMarginfiStateJson
798
+ | FlavorKaminoStateJson
799
+ | FlavorJitoRestakingStateJson
800
+ | FlavorPerenaStateJson
801
+ | FlavorGenericStateJson {
802
+ switch (flavor.flavor) {
803
+ case "marginfi":
804
+ return serializeFlavorMarginfi(flavor)
805
+ case "kamino":
806
+ return serializeFlavorKamino(flavor)
807
+ case "jitoRestaking":
808
+ return serializeFlavorJitoRestaking(flavor)
809
+ case "perena":
810
+ return serializeFlavorPerena(flavor)
811
+ case "generic":
812
+ return serializeFlavorGeneric(flavor)
813
+ default:
814
+ throw new Error(`Unsupported flavor for serialization: ${(flavor as any).flavor}`)
815
+ }
816
+ }
817
+
818
+ export function deserializeFlavor(
819
+ flavor:
820
+ | FlavorMarginfiStateJson
821
+ | FlavorKaminoStateJson
822
+ | FlavorJitoRestakingStateJson
823
+ | FlavorPerenaStateJson
824
+ | FlavorGenericStateJson,
825
+ ): Flavor {
826
+ switch (flavor.flavor) {
827
+ case "marginfi":
828
+ return makeFlavorMarginfiSync(deserializeFlavorMarginfi(flavor))
829
+ case "kamino":
830
+ return makeFlavorKaminoSync(deserializeFlavorKamino(flavor))
831
+ case "jitoRestaking":
832
+ return makeFlavorJitoRestakingSync(deserializeFlavorJitoRestaking(flavor))
833
+ case "perena":
834
+ return makeFlavorPerenaSync(deserializeFlavorPerena(flavor))
835
+ case "generic":
836
+ return makeFlavorGenericSync(deserializeFlavorGeneric(flavor))
837
+ default:
838
+ throw new Error(`Unsupported flavor for deserialization: ${(flavor as any).flavor}`)
839
+ }
840
+ }
package/src/index.ts CHANGED
@@ -1,11 +1,17 @@
1
1
  export { Market, LiquidityAdd, MarketAdminAction } from "./market"
2
2
  export { Vault } from "./vault"
3
+ export { MarketThree, MarketSnapshotData } from "./marketThree"
4
+ export * from "./orderbook"
3
5
  export { LpPosition, LpPositionState } from "./lpPosition"
4
6
  export { YtPosition } from "./ytPosition"
5
7
  export { EventDecoder } from "./events"
8
+ export * as exponentEvents from "./eventsV2"
9
+ export * as clmmEvents from "./clmm/events"
10
+ export * from "./EventDecoderV2"
6
11
  export type { AdminAction } from "./vault"
7
12
  export type { CategorizedEvents } from "./events"
8
13
  export * as events from "./events"
9
14
  export * from "./environment"
10
15
  export * as flavors from "./flavors"
11
16
  export { makeSyPosition } from "./syPosition"
17
+ export { Router, RouterTradeSource, RouterQuoteDirection } from "./router"
package/src/lpPosition.ts CHANGED
@@ -31,7 +31,7 @@ export class LpPosition {
31
31
  public state: LpPositionState,
32
32
  ) {
33
33
  const mockWallet = new MyWallet(web3.Keypair.generate())
34
- this.coreProgram = new Program<ExponentCore>(IDL as ExponentCore, new AnchorProvider(connection, mockWallet))
34
+ this.coreProgram = new Program(IDL as ExponentCore, new AnchorProvider(connection, mockWallet))
35
35
  }
36
36
 
37
37
  static async load(env: Environment, connection: web3.Connection, address: web3.PublicKey, market?: Market) {
@@ -121,8 +121,11 @@ export class LpPosition {
121
121
  const positionFarm = this.state.farms[marketFarmIndex]
122
122
 
123
123
  const timeNow = new Date().getTime() / 1000
124
+ const expirationTs = this.state.market.state.expirationTs
124
125
 
125
- const deltaTimeFarm = timeNow - this.marketSdk.state.lpFarm.lastSeenTimestamp
126
+ // cap time at expiration - emissions stop accruing after market expires
127
+ const effectiveTime = Math.min(timeNow, expirationTs)
128
+ const deltaTimeFarm = effectiveTime - this.marketSdk.state.lpFarm.lastSeenTimestamp
126
129
  const lpStakedTotal = this.marketSdk.state.lpEscrowAmount
127
130
  const tokensEmitted = Number(marketFarm.tokenRate) * deltaTimeFarm
128
131
  const increaseAmount = Number(tokensEmitted) / Number(lpStakedTotal)
package/src/market.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { AnchorProvider, BN, Program, Wallet, web3 } from "@coral-xyz/anchor"
2
2
  import {
3
- TOKEN_PROGRAM_ID,
4
3
  createAssociatedTokenAccountIdempotentInstruction,
5
4
  getAssociatedTokenAddressSync,
5
+ TOKEN_PROGRAM_ID,
6
6
  } from "@solana/spl-token"
7
7
 
8
8
  import { ExponentFetcher, LiquidityNetBalanceLimits, LpFarm } from "@exponent-labs/exponent-fetcher"
@@ -13,28 +13,38 @@ import {
13
13
  CpiAccountsRaw,
14
14
  CpiAccountsRawJson,
15
15
  Flavor,
16
- SyPosition,
17
16
  serializeCpiAccountsRaw,
17
+ SyPosition,
18
18
  } from "@exponent-labs/exponent-types"
19
- import { LiquidityAdd, MarketCalculator, lpOutForTokensIn } from "@exponent-labs/market-math"
19
+ import { LiquidityAdd, lpOutForTokensIn, MarketCalculator } from "@exponent-labs/market-math"
20
20
  import { PreciseNumber } from "@exponent-labs/precise-number"
21
21
 
22
22
  import { fetchAddressLookupTable, makeCpiAccountMetaLists } from "./addressLookupTableUtil"
23
23
  import { Environment } from "./environment"
24
24
  import {
25
+ deserializeFlavor,
25
26
  makeFlavorGenericSync,
26
27
  makeFlavorJitoRestakingSync,
27
28
  makeFlavorKaminoSync,
28
29
  makeFlavorMarginfiSync,
29
30
  makeFlavorPerenaSync,
31
+ serializeFlavor,
30
32
  } from "./flavors"
33
+ import {
34
+ deserializeCpiAccountsRaw,
35
+ FlavorGenericStateJson,
36
+ SyPositionJson,
37
+ VaultJson,
38
+ } from "@exponent-labs/exponent-types"
39
+
40
+ import { deserializeSyPosition, serializeSyPosition } from "./syPosition"
31
41
  import { makeSyPosition } from "./syPosition"
32
42
  import { getMultipleMintSupply } from "./tokenUtil"
33
43
  import { emitEventAuthority, getExponentAdminStatePda, uniqueRemainingAccounts } from "./utils"
34
44
  import { extendAddressLookupTable } from "./utils/altUtil"
35
45
  import { Vault } from "./vault"
36
46
 
37
- export { LiquidityAdd }
47
+ export type { LiquidityAdd }
38
48
 
39
49
  const SECONDS_PER_YEAR = 365 * 24 * 60 * 60
40
50
 
@@ -61,6 +71,7 @@ interface Emission {
61
71
  export type MarketAdminAction =
62
72
  | { setStatus: [number] }
63
73
  | { setMaxLpSupply: [BN] }
74
+ | { changeTreasuryTradeSyBpsFee: [number] }
64
75
  | { changeLnFeeRateRoot: [number] }
65
76
  | { changeRateScalarRoot: [number] }
66
77
  | {
@@ -142,7 +153,7 @@ export class MyWallet implements Wallet {
142
153
  }
143
154
  }
144
155
 
145
- interface MarketLoadOptions {
156
+ export interface MarketLoadOptions {
146
157
  syConfig?: {
147
158
  skipWrap?: boolean
148
159
  }
@@ -160,7 +171,7 @@ export class Market {
160
171
  ) {
161
172
  this.xponPda = new ExponentPDA(env.coreProgramId)
162
173
  const mockWallet = new MyWallet(web3.Keypair.generate())
163
- this.coreProgram = new Program<ExponentCore>(IDL as ExponentCore, new AnchorProvider(connection, mockWallet))
174
+ this.coreProgram = new Program(IDL as ExponentCore, new AnchorProvider(connection, mockWallet))
164
175
  }
165
176
 
166
177
  static async load(
@@ -1000,6 +1011,7 @@ export class Market {
1000
1011
  tokenBaseClaimer,
1001
1012
  claimer,
1002
1013
  this.flavor.mintBase,
1014
+ this.flavor.baseTokenProgram,
1003
1015
  )
1004
1016
 
1005
1017
  const tokenSyClaimer = getAssociatedTokenAddressSync(this.mintSy, claimer, true)
@@ -1091,6 +1103,7 @@ export class Market {
1091
1103
  tokenBaseTrader,
1092
1104
  owner,
1093
1105
  this.flavor.mintBase,
1106
+ this.flavor.baseTokenProgram,
1094
1107
  )
1095
1108
 
1096
1109
  const mintSyIx = await this.flavor.ixMintSy({
@@ -1181,6 +1194,7 @@ export class Market {
1181
1194
  tokenBaseTrader,
1182
1195
  owner,
1183
1196
  this.flavor.mintBase,
1197
+ this.flavor.baseTokenProgram,
1184
1198
  )
1185
1199
 
1186
1200
  const redeemSyIx = await this.flavor.ixRedeemSy({
@@ -1314,32 +1328,8 @@ export class Market {
1314
1328
  .remainingAccounts(allRemainingAccounts)
1315
1329
  .instruction()
1316
1330
 
1317
- const ix2 = await this.coreProgram.methods
1318
- .depositYt(new BN(ytOut.toString()))
1319
- .accountsStrict({
1320
- depositor: owner,
1321
- vault: this.vault.selfAddress,
1322
- userYieldPosition: this.xponPda.yieldPosition({ vault: this.vault.selfAddress, owner }),
1323
- ytSrc: tokenYtTrader,
1324
- escrowYt: this.vault.escrowYt,
1325
- tokenProgram: TOKEN_PROGRAM_ID,
1326
- syProgram: this.syProgram,
1327
- addressLookupTable: this.vault.addressLookupTable,
1328
- systemProgram: web3.SystemProgram.programId,
1329
- eventAuthority: this.vault.eventAuthority,
1330
- program: this.coreProgram.programId,
1331
- yieldPosition: this.vault.state.yieldPositonAddress,
1332
- })
1333
- .remainingAccounts(remainingAccounts)
1334
- .instruction()
1335
-
1336
1331
  return {
1337
- ixs: [
1338
- ...(await this.flavor.preIxs({ signer: owner })),
1339
- ix1,
1340
- ...(await this.flavor.postIxs({ signer: owner })),
1341
- ix2,
1342
- ],
1332
+ ixs: [...(await this.flavor.preIxs({ signer: owner })), ix1, ...(await this.flavor.postIxs({ signer: owner }))],
1343
1333
  setupIxs: [tokenSyTraderAtaIx, tokenPtTraderAtaIx, tokenYtTraderAtaIx],
1344
1334
  }
1345
1335
  }
@@ -1394,6 +1384,7 @@ export class Market {
1394
1384
  tokenBaseTrader,
1395
1385
  owner,
1396
1386
  this.flavor.mintBase,
1387
+ this.flavor.baseTokenProgram,
1397
1388
  )
1398
1389
 
1399
1390
  const redeemSyIx = await this.flavor.ixRedeemSy({
@@ -2210,6 +2201,63 @@ export class Market {
2210
2201
  }
2211
2202
  }
2212
2203
 
2204
+ static fromJson(json: MarketJson, env: Environment, connection: web3.Connection): Market {
2205
+ const state: MarketArgs = {
2206
+ seedId: [json.seedId],
2207
+ ptBalance: BigInt(json.ptBalance),
2208
+ syBalance: BigInt(json.syBalance),
2209
+ lpSupply: BigInt(json.lpSupply),
2210
+ lpEscrowAmount: BigInt(json.lpEscrowAmount),
2211
+ maxLpSupply: BigInt(json.maxLpSupply),
2212
+ rateScalarRoot: json.rateScalarRoot,
2213
+ lnFeeRateRoot: json.lnFeeRateRoot,
2214
+ lastLnImpliedRate: json.lastLnImpliedRate,
2215
+ expirationTs: json.expirationTs,
2216
+ addressLookupTable: new web3.PublicKey(json.addressLookupTable),
2217
+ mintSy: new web3.PublicKey(json.mintSy),
2218
+ mintPt: new web3.PublicKey(json.mintPt),
2219
+ mintLp: new web3.PublicKey(json.mintLp),
2220
+ tokenPtEscrow: new web3.PublicKey(json.tokenPtEscrow),
2221
+ tokenSyEscrow: new web3.PublicKey(json.tokenSyEscrow),
2222
+ tokenLpEscrow: new web3.PublicKey(json.tokenLpEscrow),
2223
+ syProgram: new web3.PublicKey(json.syProgram),
2224
+ cpiAccounts: deserializeCpiAccountsRaw(json.cpiAccounts),
2225
+ feeTreasurySyBps: json.feeTreasurySyBps,
2226
+ tokenFeeTreasurySy: new web3.PublicKey(json.treasurySyTokenAccount),
2227
+ lpFarm: {
2228
+ farmEmissions: json.lpFarm.farmEmissions.map((e) => ({
2229
+ mint: new web3.PublicKey(e.mint),
2230
+ tokenRate: new BN(e.tokenRate),
2231
+ expiryTimestamp: e.expiryTimestamp,
2232
+ index: new PreciseNumber(e.index).anchorify(),
2233
+ })),
2234
+ lastSeenTimestamp: json.lpFarm.lastSeenTimestamp,
2235
+ },
2236
+ liquidityNetBalanceLimits: {
2237
+ windowStartTimestamp: json.liquidityNetBalanceLimits.windowStartTimestamp,
2238
+ windowStartNetBalance: new BN(json.liquidityNetBalanceLimits.windowStartNetBalance),
2239
+ maxNetBalanceChangeNegativePercentage: json.liquidityNetBalanceLimits.maxNetBalanceChangeNegativePercentage,
2240
+ maxNetBalanceChangePositivePercentage: json.liquidityNetBalanceLimits.maxNetBalanceChangePositivePercentage,
2241
+ windowDurationSeconds: json.liquidityNetBalanceLimits.windowDurationSeconds,
2242
+ },
2243
+ emissions: {
2244
+ trackers: json.emissions.trackers.map((e) => ({
2245
+ tokenEscrow: new web3.PublicKey(e.tokenEscrow),
2246
+ lpShareIndex: e.lpShareIndex,
2247
+ lastSeenStaged: e.lastSeenStaged,
2248
+ })),
2249
+ },
2250
+ vault: Vault.loadFromJson(json.vault, new web3.PublicKey(json.vault.selfAddress), env, connection),
2251
+ sySupply: BigInt(json.sySupply),
2252
+ statusFlags: json.statusFlags,
2253
+ isCurrentFlashSwap: json.isCurrentFlashSwap,
2254
+ flavor: deserializeFlavor(json.flavor),
2255
+ syPosition: deserializeSyPosition(json.syPosition),
2256
+ }
2257
+
2258
+ return new Market(state, new web3.PublicKey(json.address), env, connection)
2259
+ }
2260
+
2213
2261
  /** Calculate available liquidity for PT trades
2214
2262
  * @param isBuy - true if buying PT with SY, false if selling PT for SY
2215
2263
  * @param sizePt - amount of PT to trade (in PT decimals)
@@ -2269,6 +2317,8 @@ export class Market {
2269
2317
  export type MarketJson = {
2270
2318
  /** The market's public key */
2271
2319
  address: string
2320
+ /** The market's seed ID */
2321
+ seedId: number
2272
2322
  /** The market's address lookup table public key */
2273
2323
  addressLookupTable: string
2274
2324
  /** The market's SY escrow account public key - this is a pass-through account which moves SY between an end-user and the SY program where it is deposited and withdrawn from */
@@ -2349,6 +2399,18 @@ export type MarketJson = {
2349
2399
  /** Annualized yield for PT */
2350
2400
  ptApr: number
2351
2401
 
2402
+ vault: VaultJson
2403
+
2404
+ sySupply: string
2405
+
2406
+ statusFlags: number
2407
+
2408
+ isCurrentFlashSwap: boolean
2409
+
2410
+ flavor: FlavorGenericStateJson
2411
+
2412
+ syPosition: SyPositionJson
2413
+
2352
2414
  ptApy: number
2353
2415
 
2354
2416
  /** Emission tokens */
@@ -2442,5 +2504,12 @@ function toJson(market: Market): MarketJson {
2442
2504
  index: PreciseNumber.fromRaw(e.index[0]).valueString,
2443
2505
  })),
2444
2506
  },
2507
+ vault: market.vault.toJson(),
2508
+ sySupply: market.state.sySupply.toString(),
2509
+ statusFlags: market.state.statusFlags,
2510
+ isCurrentFlashSwap: market.state.isCurrentFlashSwap,
2511
+ // @ts-ignore
2512
+ flavor: serializeFlavor(market.state.flavor),
2513
+ syPosition: serializeSyPosition(market.state.syPosition),
2445
2514
  }
2446
2515
  }