@exponent-labs/exponent-sdk 0.0.8 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/events.ts CHANGED
@@ -50,15 +50,30 @@ export class EventDecoder {
50
50
  }
51
51
  }
52
52
 
53
- parseCpiEvents(transactionResponse: web3.VersionedTransactionResponse | web3.TransactionResponse): CategorizedEvents {
53
+ async parseCpiEvents(
54
+ transactionResponse: web3.VersionedTransactionResponse | web3.TransactionResponse,
55
+ connection: web3.Connection,
56
+ ): Promise<CategorizedEvents> {
54
57
  const events: GenericEvent[] = []
55
58
  const inner: web3.CompiledInnerInstruction[] = transactionResponse?.meta?.innerInstructions ?? []
56
59
 
60
+ const addressTableLookups = transactionResponse?.transaction.message.addressTableLookups
61
+
62
+ const lookupTables = await Promise.all(
63
+ addressTableLookups.map(async (lookup) => {
64
+ const lookupTable = await connection.getAddressLookupTable(lookup.accountKey)
65
+ return lookupTable
66
+ }),
67
+ )
68
+
57
69
  for (let i = 0; i < inner.length; i++) {
58
70
  for (let j = 0; j < inner[i].instructions.length; j++) {
59
71
  const ix = inner[i].instructions[j]
60
72
 
61
- const programPubkey = transactionResponse?.transaction.message.staticAccountKeys[ix.programIdIndex]
73
+ const accountKeys = transactionResponse?.transaction.message.getAccountKeys({
74
+ addressLookupTableAccounts: lookupTables.map((lookup) => lookup.value),
75
+ })
76
+ const programPubkey = accountKeys.get(ix.programIdIndex)
62
77
 
63
78
  if (programPubkey === undefined || !programPubkey.equals(this.programId)) {
64
79
  continue
package/src/lpPosition.ts CHANGED
@@ -5,6 +5,7 @@ import { ExponentCore, IDL } from "@exponent-labs/exponent-idl"
5
5
  import { ExponentFetcher } from "@exponent-labs/exponent-fetcher"
6
6
  import { PreciseNumber } from "@exponent-labs/precise-number"
7
7
  import { makeSyPosition } from "./syPosition"
8
+ import { ExponentPDA } from "@exponent-labs/exponent-pda"
8
9
 
9
10
  export interface EmissionTracker {
10
11
  lastSeenIndex: number
@@ -32,14 +33,14 @@ export class LpPosition {
32
33
  this.coreProgram = new Program(IDL as ExponentCore, new AnchorProvider(connection, mockWallet))
33
34
  }
34
35
 
35
- static async load(env: Environment, connection: web3.Connection, address: web3.PublicKey) {
36
+ static async load(env: Environment, connection: web3.Connection, address: web3.PublicKey, market?: Market) {
36
37
  const fetcher = new ExponentFetcher({ connection })
37
38
  const x = await fetcher.fetchLpPosition(address)
38
- const market = await Market.load(env, connection, x.market)
39
+ const loadedMarket = market ?? (await Market.load(env, connection, x.market))
39
40
  const state: LpPositionState = {
40
41
  owner: x.owner,
41
42
  balanceLp: x.lpBalance,
42
- market,
43
+ market: loadedMarket,
43
44
  emissionTrackers: x.emissions,
44
45
  farms: x.farms,
45
46
  fetcher: fetcher,
@@ -47,6 +48,32 @@ export class LpPosition {
47
48
  return new LpPosition(env, connection, address, state)
48
49
  }
49
50
 
51
+ static async loadAllByOwner(
52
+ env: Environment,
53
+ connection: web3.Connection,
54
+ owner: web3.PublicKey,
55
+ markets: (Market | web3.PublicKey)[],
56
+ ) {
57
+ const pda = new ExponentPDA(env.coreProgramId)
58
+ const addresses = markets.map((m) =>
59
+ pda.marketLpPosition({
60
+ market: m instanceof web3.PublicKey ? m : m.selfAddress,
61
+ owner,
62
+ }),
63
+ )
64
+
65
+ const positionPromises = addresses.map((addr) => {
66
+ try {
67
+ return LpPosition.load(env, connection, addr)
68
+ } catch (e) {
69
+ return Promise.resolve(null)
70
+ }
71
+ })
72
+
73
+ const positions = await Promise.all(positionPromises)
74
+ return positions.filter((p): p is LpPosition => p !== null)
75
+ }
76
+
50
77
  async reload(conn = this.connection) {
51
78
  const x = await LpPosition.load(this.env, conn, this.selfAddress)
52
79
  this.state = x.state
package/src/market.ts CHANGED
@@ -392,11 +392,19 @@ export class Market {
392
392
  return (r * SECONDS_PER_YEAR) / secondsRemaining
393
393
  }
394
394
 
395
+ static annualizeApy(r: number, secondsRemaining: number) {
396
+ return (1 + r) ** (SECONDS_PER_YEAR / secondsRemaining) - 1
397
+ }
398
+
395
399
  /** Annualized PT fixed rate */
396
400
  get ptApr(): number {
397
401
  return Market.annualize(this.absolutePtYield, this.secondsRemaining)
398
402
  }
399
403
 
404
+ get ptApy(): number {
405
+ return Market.annualizeApy(this.absolutePtYield, this.secondsRemaining)
406
+ }
407
+
400
408
  /** The fee rate taken off of trade fees (typically around 20%) expressed as a BPS number */
401
409
  get feeTreasuryBps(): number {
402
410
  return this.state.feeTreasurySyBps
@@ -1066,7 +1074,7 @@ export class Market {
1066
1074
  ])
1067
1075
 
1068
1076
  const ix = await this.coreProgram.methods
1069
- .wrapperBuyPt(new BN(ptOut.toString()), new BN(maxBaseIn.toString()), mintSyRemAccounts.length - 1)
1077
+ .wrapperBuyPt(new BN(ptOut.toString()), new BN(maxBaseIn.toString()), mintSyRemAccounts.length)
1070
1078
  .accountsStrict({
1071
1079
  addressLookupTable: this.addressLookupTable,
1072
1080
  buyer: owner,
@@ -1137,16 +1145,11 @@ export class Market {
1137
1145
  })
1138
1146
 
1139
1147
  const redeemSyRemAccounts = redeemSyIx.keys
1140
- redeemSyRemAccounts.push({
1141
- pubkey: this.coreProgram.programId,
1142
- isWritable: false,
1143
- isSigner: false,
1144
- })
1145
1148
 
1146
1149
  const remainingAccounts = uniqueRemainingAccounts([...this.cpiAccounts.getSyState, ...this.cpiAccounts.withdrawSy])
1147
1150
 
1148
1151
  const ix = await this.coreProgram.methods
1149
- .wrapperSellPt(new BN(amount.toString()), new BN(minBaseOut.toString()), redeemSyRemAccounts.length - 1)
1152
+ .wrapperSellPt(new BN(amount.toString()), new BN(minBaseOut.toString()), redeemSyRemAccounts.length)
1150
1153
  .accountsStrict({
1151
1154
  seller: owner,
1152
1155
  market: this.selfAddress,
@@ -1232,7 +1235,7 @@ export class Market {
1232
1235
  const allRemainingAccounts = mintSyRemAccounts.concat(remainingAccounts)
1233
1236
 
1234
1237
  const ix1 = await this.coreProgram.methods
1235
- .wrapperBuyYt(new BN(ytOut.toString()), new BN(maxBaseIn.toString()), mintSyRemAccounts.length - 1)
1238
+ .wrapperBuyYt(new BN(ytOut.toString()), new BN(maxBaseIn.toString()), mintSyRemAccounts.length)
1236
1239
  .accountsStrict({
1237
1240
  buyer: owner,
1238
1241
  market: this.selfAddress,
@@ -1383,7 +1386,7 @@ export class Market {
1383
1386
  .instruction()
1384
1387
 
1385
1388
  const ix2 = await this.coreProgram.methods
1386
- .wrapperSellYt(new BN(amount.toString()), new BN(minBaseOut.toString()), redeemSyRemAccounts.length - 1)
1389
+ .wrapperSellYt(new BN(amount.toString()), new BN(minBaseOut.toString()), redeemSyRemAccounts.length)
1387
1390
  .accountsStrict({
1388
1391
  seller: owner,
1389
1392
  market: this.selfAddress,
@@ -1568,7 +1571,7 @@ export class Market {
1568
1571
  const lpPosition = this.xponPda.marketLpPosition({ market: this.selfAddress, owner: depositor })
1569
1572
 
1570
1573
  const ix = await this.coreProgram.methods
1571
- .wrapperProvideLiquidity(amountBaseBn, minLpOutBn, mintSyRemAccounts.length - 1)
1574
+ .wrapperProvideLiquidity(amountBaseBn, minLpOutBn, mintSyRemAccounts.length)
1572
1575
  .accountsStrict({
1573
1576
  depositor,
1574
1577
  authority: this.vault.authority,
@@ -1695,7 +1698,7 @@ export class Market {
1695
1698
  .wrapperProvideLiquidityBase(
1696
1699
  new BN(amountBase.toString()),
1697
1700
  new BN(minLpOut.toString()),
1698
- mintSyRemAccounts.length - 1,
1701
+ mintSyRemAccounts.length,
1699
1702
  new BN(externalPtToBuy.toString()),
1700
1703
  new BN(externalSyConstraint.toString()),
1701
1704
  )
@@ -1809,7 +1812,7 @@ export class Market {
1809
1812
  new BN(amountBase.toString()),
1810
1813
  new BN(amountPt.toString()),
1811
1814
  new BN(minLpOut.toString()),
1812
- mintSyRemAccounts.length - 1,
1815
+ mintSyRemAccounts.length,
1813
1816
  )
1814
1817
  .accountsStrict({
1815
1818
  depositor,
@@ -1903,7 +1906,7 @@ export class Market {
1903
1906
  .wrapperWithdrawLiquidity(
1904
1907
  new BN(amountLp.toString()),
1905
1908
  new BN(minSyOut.toFixed(0).toString()),
1906
- redeemSyRemAccounts.length - 1,
1909
+ redeemSyRemAccounts.length,
1907
1910
  )
1908
1911
  .accountsStrict({
1909
1912
  market: this.selfAddress,
@@ -1989,7 +1992,7 @@ export class Market {
1989
1992
  const redeemSyRemAccounts = redeemSyIx.keys
1990
1993
 
1991
1994
  const ixn = await this.coreProgram.methods
1992
- .wrapperWithdrawLiquidityClassic(new BN(amountLp.toString()), redeemSyRemAccounts.length - 1)
1995
+ .wrapperWithdrawLiquidityClassic(new BN(amountLp.toString()), redeemSyRemAccounts.length)
1993
1996
  .accountsStrict({
1994
1997
  market: this.selfAddress,
1995
1998
  tokenPtEscrow: this.tokenPtEscrow,
@@ -2249,6 +2252,8 @@ export type MarketJson = {
2249
2252
  /** Annualized yield for PT */
2250
2253
  ptApr: number
2251
2254
 
2255
+ ptApy: number
2256
+
2252
2257
  /** Emission tokens */
2253
2258
  emissions: {
2254
2259
  trackers: {
@@ -2319,6 +2324,7 @@ function toJson(m: Market): MarketJson {
2319
2324
  })),
2320
2325
  },
2321
2326
  ptApr: m.ptApr,
2327
+ ptApy: m.ptApy,
2322
2328
  lpEscrowAmount: m.state.lpEscrowAmount.toString(),
2323
2329
  maxLpSupply: m.state.maxLpSupply.toString(),
2324
2330
  liquidityNetBalanceLimits: {
package/src/ytPosition.ts CHANGED
@@ -27,11 +27,11 @@ export class YtPosition {
27
27
  /** Loads the YT position by address, and loads Vault, too
28
28
  * DEPRECATED - use loadByOwner instead - loading the vault is expensive
29
29
  */
30
- static async load(env: Environment, connection: web3.Connection, address: web3.PublicKey) {
30
+ static async load(env: Environment, connection: web3.Connection, address: web3.PublicKey, vault?: Vault) {
31
31
  const fetcher = new ExponentFetcher({ connection })
32
32
  const x = await fetcher.fetchYtPosition(address)
33
- const vault = await Vault.load(env, connection, x.vault)
34
- return new YtPosition(env, connection, address, x, vault)
33
+ const loadedVault = vault ?? (await Vault.load(env, connection, x.vault))
34
+ return new YtPosition(env, connection, address, x, loadedVault)
35
35
  }
36
36
 
37
37
  /** Loads the YT position by owner, but require a loaded Vault */
@@ -43,6 +43,22 @@ export class YtPosition {
43
43
  return new YtPosition(env, connection, address, x, vault)
44
44
  }
45
45
 
46
+ static async loadAllByOwner(
47
+ env: Environment,
48
+ connection: web3.Connection,
49
+ owner: web3.PublicKey,
50
+ vaults: (Vault | web3.PublicKey)[],
51
+ ) {
52
+ const pda = new ExponentPDA(env.coreProgramId)
53
+ const addresses = vaults.map((v) =>
54
+ pda.yieldPosition({
55
+ vault: v instanceof web3.PublicKey ? v : v.selfAddress,
56
+ owner,
57
+ }),
58
+ )
59
+ return Promise.all(addresses.map((addr) => YtPosition.load(env, connection, addr)))
60
+ }
61
+
46
62
  async reload(conn = this.connection) {
47
63
  const x = await YtPosition.load(this.env, conn, this.selfAddress)
48
64
  this.state = x.state