@exponent-labs/exponent-sdk 0.0.9 → 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,
@@ -1227,7 +1235,7 @@ export class Market {
1227
1235
  const allRemainingAccounts = mintSyRemAccounts.concat(remainingAccounts)
1228
1236
 
1229
1237
  const ix1 = await this.coreProgram.methods
1230
- .wrapperBuyYt(new BN(ytOut.toString()), new BN(maxBaseIn.toString()), mintSyRemAccounts.length - 1)
1238
+ .wrapperBuyYt(new BN(ytOut.toString()), new BN(maxBaseIn.toString()), mintSyRemAccounts.length)
1231
1239
  .accountsStrict({
1232
1240
  buyer: owner,
1233
1241
  market: this.selfAddress,
@@ -1563,7 +1571,7 @@ export class Market {
1563
1571
  const lpPosition = this.xponPda.marketLpPosition({ market: this.selfAddress, owner: depositor })
1564
1572
 
1565
1573
  const ix = await this.coreProgram.methods
1566
- .wrapperProvideLiquidity(amountBaseBn, minLpOutBn, mintSyRemAccounts.length - 1)
1574
+ .wrapperProvideLiquidity(amountBaseBn, minLpOutBn, mintSyRemAccounts.length)
1567
1575
  .accountsStrict({
1568
1576
  depositor,
1569
1577
  authority: this.vault.authority,
@@ -1690,7 +1698,7 @@ export class Market {
1690
1698
  .wrapperProvideLiquidityBase(
1691
1699
  new BN(amountBase.toString()),
1692
1700
  new BN(minLpOut.toString()),
1693
- mintSyRemAccounts.length - 1,
1701
+ mintSyRemAccounts.length,
1694
1702
  new BN(externalPtToBuy.toString()),
1695
1703
  new BN(externalSyConstraint.toString()),
1696
1704
  )
@@ -1804,7 +1812,7 @@ export class Market {
1804
1812
  new BN(amountBase.toString()),
1805
1813
  new BN(amountPt.toString()),
1806
1814
  new BN(minLpOut.toString()),
1807
- mintSyRemAccounts.length - 1,
1815
+ mintSyRemAccounts.length,
1808
1816
  )
1809
1817
  .accountsStrict({
1810
1818
  depositor,
@@ -2244,6 +2252,8 @@ export type MarketJson = {
2244
2252
  /** Annualized yield for PT */
2245
2253
  ptApr: number
2246
2254
 
2255
+ ptApy: number
2256
+
2247
2257
  /** Emission tokens */
2248
2258
  emissions: {
2249
2259
  trackers: {
@@ -2314,6 +2324,7 @@ function toJson(m: Market): MarketJson {
2314
2324
  })),
2315
2325
  },
2316
2326
  ptApr: m.ptApr,
2327
+ ptApy: m.ptApy,
2317
2328
  lpEscrowAmount: m.state.lpEscrowAmount.toString(),
2318
2329
  maxLpSupply: m.state.maxLpSupply.toString(),
2319
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