@exponent-labs/generic-sy-sdk 0.1.3 → 0.1.6

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/index.ts CHANGED
@@ -1,21 +1,39 @@
1
1
  import { AnchorProvider, BN, Program, web3 } from "@coral-xyz/anchor"
2
- import { IDL, GenericStandard } from "@exponent-labs/generic-sy-idl"
3
- import { getAssociatedTokenAddressSync, TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from "@solana/spl-token"
4
- import { GenericSyPda } from "@exponent-labs/generic-sy-pda"
5
- import { GenericSyState, GenericSyMetaAccount, InterfaceTypeGeneric, Hook } from "@exponent-labs/exponent-types"
2
+ import {
3
+ ASSOCIATED_TOKEN_PROGRAM_ID,
4
+ TOKEN_2022_PROGRAM_ID,
5
+ TOKEN_PROGRAM_ID,
6
+ getAssociatedTokenAddressSync,
7
+ } from "@solana/spl-token"
8
+
9
+ import { EXPONENT_ADMIN_PROGRAM_ID, ExponentAdminPda } from "@exponent-labs/exponent-admin-pda"
6
10
  import {
7
11
  ExponentFetcher,
12
+ fetchAdrenaIndex,
8
13
  fetchFragmetricIndex,
9
14
  fetchFragmetricSupportedTokenIndex,
15
+ fetchJupiterLendIndex,
16
+ fetchKaminoVaultIndex,
10
17
  fetchMeteoraIndex,
18
+ fetchSanctumIndex,
11
19
  fetchSplStakePoolIndex,
20
+ fetchJupiterPerpsIndex,
21
+ fetchSolsticeRedemptionRate,
12
22
  } from "@exponent-labs/exponent-fetcher"
13
- import { EXPONENT_ADMIN_PROGRAM_ID, ExponentAdminPda } from "@exponent-labs/exponent-admin-pda"
14
- import { MyWallet } from "./utils"
15
- import { FragmetricPda, FRAGMETRIC_PROGRAM_ID } from "@exponent-labs/fragmetric-pda"
16
- import { PROGRAM_ID as GENERIC_STANDARD_PROGRAM_ID } from "@exponent-labs/generic-sy-idl"
23
+ import {
24
+ GenericSyMetaAccount,
25
+ GenericSyState,
26
+ Hook,
27
+ InterfaceTypeGeneric,
28
+ AdditionalDataGeneric,
29
+ } from "@exponent-labs/exponent-types"
30
+ import { FRAGMETRIC_PROGRAM_ID, FragmetricPda } from "@exponent-labs/fragmetric-pda"
31
+ import { PROGRAM_ID as GENERIC_STANDARD_PROGRAM_ID, GenericStandard, IDL } from "@exponent-labs/generic-sy-idl"
32
+ import { GenericSyPda } from "@exponent-labs/generic-sy-pda"
17
33
  import { PreciseNumber } from "@exponent-labs/precise-number"
34
+
18
35
  import { SyInitializeConfig, SyTokenMetadata } from "./types"
36
+ import { MyWallet } from "./utils"
19
37
 
20
38
  async function loadAccountState(
21
39
  cnx: web3.Connection,
@@ -34,8 +52,22 @@ async function loadAccountState(
34
52
  interfaceIndex = InterfaceType.Fragmetric
35
53
  } else if ("meteora" in interfaceType) {
36
54
  interfaceIndex = InterfaceType.Meteora
55
+ } else if ("sanctum" in interfaceType) {
56
+ interfaceIndex = InterfaceType.Sanctum
37
57
  } else if ("fragmetricSupportedAsset" in interfaceType) {
38
58
  interfaceIndex = InterfaceType.FragmetricSupportedAsset
59
+ } else if ("jupiterPerps" in interfaceType) {
60
+ interfaceIndex = InterfaceType.JupiterPerps
61
+ } else if ("adrena" in interfaceType) {
62
+ interfaceIndex = InterfaceType.Adrena
63
+ } else if ("hyloLpToken" in interfaceType) {
64
+ interfaceIndex = InterfaceType.HyloLpToken
65
+ } else if ("jupiterLend" in interfaceType) {
66
+ interfaceIndex = InterfaceType.JupiterLend
67
+ } else if ("kaminoVault" in interfaceType) {
68
+ interfaceIndex = InterfaceType.KaminoVault
69
+ } else if ("solstice" in interfaceType) {
70
+ interfaceIndex = InterfaceType.Solstice
39
71
  } else {
40
72
  throw new Error("Unsupported interface type")
41
73
  }
@@ -55,6 +87,13 @@ export enum InterfaceType {
55
87
  Fragmetric = 3,
56
88
  Meteora = 4,
57
89
  FragmetricSupportedAsset = 5,
90
+ Sanctum = 6,
91
+ JupiterPerps = 7,
92
+ Adrena = 8,
93
+ HyloLpToken = 9,
94
+ JupiterLend = 10,
95
+ KaminoVault = 11,
96
+ Solstice = 12,
58
97
  }
59
98
 
60
99
  export function getInterfaceTypeObj(interfaceType: number): InterfaceTypeGeneric {
@@ -71,7 +110,27 @@ export function getInterfaceTypeObj(interfaceType: number): InterfaceTypeGeneric
71
110
  return { fragmetricSupportedAsset: {} }
72
111
  case InterfaceType.Meteora:
73
112
  return { meteora: {} }
74
-
113
+ case InterfaceType.Sanctum:
114
+ return { sanctum: {} }
115
+ case InterfaceType.JupiterPerps:
116
+ return {
117
+ jupiterPerps: {
118
+ lastFeeUsdResetUnixTimestamp: 0,
119
+ lastRealizedFeeUsd: new BN(0),
120
+ lastAumUsd: new BN(0),
121
+ lastRealizedFeeUsdUpdateUnixTimestamp: 0,
122
+ },
123
+ }
124
+ case InterfaceType.Adrena:
125
+ return { adrena: { previousTotalFees: new BN(0) } }
126
+ case InterfaceType.HyloLpToken:
127
+ return { hyloLpToken: {} }
128
+ case InterfaceType.JupiterLend:
129
+ return { jupiterLend: { padding: [] } }
130
+ case InterfaceType.KaminoVault:
131
+ return { kaminoVault: { padding: [] } }
132
+ case InterfaceType.Solstice:
133
+ return { solstice: { padding: [] } }
75
134
  default:
76
135
  throw new Error(`Unsupported interface type: ${interfaceType}`)
77
136
  }
@@ -91,13 +150,34 @@ export function getInterfaceTypeFromString(interfaceType: string): InterfaceType
91
150
  return { fragmetricSupportedAsset: {} }
92
151
  case "meteora":
93
152
  return { meteora: {} }
153
+ case "sanctum":
154
+ return { sanctum: {} }
155
+ case "jupiter-perps":
156
+ return {
157
+ jupiterPerps: {
158
+ lastFeeUsdResetUnixTimestamp: 0,
159
+ lastRealizedFeeUsd: new BN(0),
160
+ lastAumUsd: new BN(0),
161
+ lastRealizedFeeUsdUpdateUnixTimestamp: 0,
162
+ },
163
+ }
164
+ case "adrena":
165
+ return { adrena: { previousTotalFees: new BN(0) } }
166
+ case "hylo-lp-token":
167
+ return { hyloLpToken: {} }
168
+ case "jupiter-lend":
169
+ return { jupiterLend: { padding: [] } }
170
+ case "kamino-vault":
171
+ return { kaminoVault: { padding: [] } }
172
+ case "solstice":
173
+ return { solstice: { padding: [] } }
94
174
  default:
95
175
  throw new Error(`Unsupported interface type: ${interfaceType}`)
96
176
  }
97
177
  }
98
178
 
99
179
  interface GenericSyConfig {
100
- skipFragmetricWrap?: boolean
180
+ skipWrap?: boolean
101
181
  }
102
182
 
103
183
  export class GenericSySdk {
@@ -118,6 +198,7 @@ export class GenericSySdk {
118
198
  IDL,
119
199
  new AnchorProvider(new web3.Connection("https://api.devnet.solana.com"), new MyWallet(web3.Keypair.generate())),
120
200
  )
201
+
121
202
  // Determine interface index based on the interface type from state
122
203
  let interfaceIndex: number
123
204
  if ("pyth" in this.state.account.interfaceType) {
@@ -132,9 +213,24 @@ export class GenericSySdk {
132
213
  interfaceIndex = InterfaceType.Fragmetric
133
214
  } else if ("meteora" in this.state.account.interfaceType) {
134
215
  interfaceIndex = InterfaceType.Meteora
216
+ } else if ("sanctum" in this.state.account.interfaceType) {
217
+ interfaceIndex = InterfaceType.Sanctum
218
+ } else if ("jupiterPerps" in this.state.account.interfaceType) {
219
+ interfaceIndex = InterfaceType.JupiterPerps
220
+ } else if ("adrena" in this.state.account.interfaceType) {
221
+ interfaceIndex = InterfaceType.Adrena
222
+ } else if ("hyloLpToken" in this.state.account.interfaceType) {
223
+ interfaceIndex = InterfaceType.HyloLpToken
224
+ } else if ("jupiterLend" in this.state.account.interfaceType) {
225
+ interfaceIndex = InterfaceType.JupiterLend
226
+ } else if ("kaminoVault" in this.state.account.interfaceType) {
227
+ interfaceIndex = InterfaceType.KaminoVault
228
+ } else if ("solstice" in this.state.account.interfaceType) {
229
+ interfaceIndex = InterfaceType.Solstice
135
230
  } else {
136
231
  throw new Error("Unsupported interface type")
137
232
  }
233
+
138
234
  this.syPda = new GenericSyPda(programId, interfaceIndex)
139
235
  }
140
236
 
@@ -144,7 +240,7 @@ export class GenericSySdk {
144
240
  cnx: web3.Connection,
145
241
  ): Promise<{
146
242
  syRate: number
147
- fragmetricData?: { receiptTokenMint: web3.PublicKey; wrappedTokenMint: web3.PublicKey }
243
+ additionalData?: AdditionalDataGeneric
148
244
  }> {
149
245
  if ("pyth" in interfaceType) {
150
246
  const syRate = Number(PreciseNumber.fromRaw(account.index[0]).valueString)
@@ -158,13 +254,23 @@ export class GenericSySdk {
158
254
  fragmetricFund: account.interfaceAccounts[0],
159
255
  index: 0,
160
256
  })
161
- return { syRate: index, fragmetricData: { receiptTokenMint, wrappedTokenMint } }
257
+ return {
258
+ syRate: index,
259
+ additionalData: {
260
+ fragmetricData: { receiptTokenMint, wrappedTokenMint },
261
+ },
262
+ }
162
263
  } else if ("fragmetric" in interfaceType) {
163
264
  const { index, receiptTokenMint, wrappedTokenMint } = await fetchFragmetricIndex({
164
265
  connection: cnx,
165
266
  fragmetricFund: account.interfaceAccounts[0],
166
267
  })
167
- return { syRate: index, fragmetricData: { receiptTokenMint, wrappedTokenMint } }
268
+ return {
269
+ syRate: index,
270
+ additionalData: {
271
+ fragmetricData: { receiptTokenMint, wrappedTokenMint },
272
+ },
273
+ }
168
274
  } else if ("meteora" in interfaceType) {
169
275
  const currentTs = Math.floor(Date.now() / 1000)
170
276
 
@@ -177,6 +283,98 @@ export class GenericSySdk {
177
283
  const virtualPrice = await fetchMeteoraIndex({ connection: cnx, accounts, onChainTime: currentTs })
178
284
 
179
285
  return { syRate: virtualPrice.virtualPrice }
286
+ } else if ("sanctum" in interfaceType) {
287
+ const accounts = {
288
+ lpMint: account.interfaceAccounts[0],
289
+ poolState: account.interfaceAccounts[1],
290
+ }
291
+
292
+ const exchangeRate = await fetchSanctumIndex({ connection: cnx, accounts })
293
+
294
+ return { syRate: exchangeRate }
295
+ } else if ("adrena" in interfaceType) {
296
+ // @ts-ignore
297
+ const previousTotalFees = account.interfaceType.adrena.previousTotalFees
298
+ const currentIndex = account.index
299
+
300
+ let accounts = {
301
+ pool: account.interfaceAccounts[0],
302
+ custody1: account.interfaceAccounts[1],
303
+ custody2: account.interfaceAccounts[2],
304
+ custody3: account.interfaceAccounts[3],
305
+ custody4: account.interfaceAccounts[4],
306
+ }
307
+
308
+ const syRate = await fetchAdrenaIndex({ connection: cnx, accounts, currentIndex, previousTotalFees })
309
+
310
+ return { syRate: syRate.index }
311
+ } else if ("jupiterPerps" in interfaceType) {
312
+ // @ts-ignore
313
+ const j = account.interfaceType.jupiterPerps
314
+ const { index } = await fetchJupiterPerpsIndex({
315
+ connection: cnx,
316
+ pool: account.interfaceAccounts[0],
317
+ lastFeeUsdResetUnixTimestamp: j.lastFeeUsdResetUnixTimestamp,
318
+ lastRealizedFeeUsd: new BN(j.lastRealizedFeeUsd),
319
+ lastAumUsd: new BN(j.lastAumUsd),
320
+ currentIndex: account.index,
321
+ lastRealizedFeeUsdUpdateUnixTimestamp: j.lastRealizedFeeUsdUpdateUnixTimestamp,
322
+ })
323
+ return { syRate: index }
324
+ } else if ("hyloLpToken" in interfaceType) {
325
+ // For HyloLpToken, the exchange rate is calculated by the Rust program using hylo_cpi
326
+ // and will be available in the index field
327
+ const syRate = Number(PreciseNumber.fromRaw(account.index[0]).valueString)
328
+ return { syRate }
329
+ } else if ("jupiterLend" in interfaceType) {
330
+ const { index, baseTokenMint, tokenReservesLiquidity, lendingSupplyPosition, rewardsRateModel, rateModel } =
331
+ await fetchJupiterLendIndex({
332
+ connection: cnx,
333
+ jupiterLendAccount: account.interfaceAccounts[0],
334
+ })
335
+
336
+ return {
337
+ syRate: index,
338
+ additionalData: {
339
+ jupiterLendData: {
340
+ baseTokenMint,
341
+ tokenReservesLiquidity,
342
+ lendingSupplyPosition,
343
+ rewardsRateModel,
344
+ rateModel,
345
+ },
346
+ },
347
+ }
348
+ } else if ("kaminoVault" in interfaceType) {
349
+ const { index, tokenVault, tokenMint, baseVaultAuthority, sharesMint, reserves } = await fetchKaminoVaultIndex({
350
+ connection: cnx,
351
+ kaminoVaultAccount: account.interfaceAccounts[0],
352
+ })
353
+ return {
354
+ syRate: index,
355
+ additionalData: {
356
+ kaminoVaultData: {
357
+ vault: account.interfaceAccounts[0],
358
+ reserves: reserves.map((r) => {
359
+ return {
360
+ reserveAddress: r.reserveAddress,
361
+ marketAddress: r.reserve,
362
+ }
363
+ }),
364
+ tokenVault,
365
+ tokenMint,
366
+ baseVaultAuthority,
367
+ sharesMint,
368
+ },
369
+ },
370
+ }
371
+ } else if ("solstice" in interfaceType) {
372
+ const { redemptionRate } = await fetchSolsticeRedemptionRate({
373
+ connection: cnx,
374
+ yieldPool: account.interfaceAccounts[0],
375
+ vestingSchedule: account.interfaceAccounts[1],
376
+ })
377
+ return { syRate: redemptionRate }
180
378
  } else {
181
379
  return { syRate: 1 }
182
380
  }
@@ -197,7 +395,7 @@ export class GenericSySdk {
197
395
  config?: GenericSyConfig
198
396
  }) {
199
397
  const account = await loadAccountState(cnx, yieldBearingMint, genericStandardProgramId, interfaceType)
200
- const tokenProgramBase = TOKEN_PROGRAM_ID
398
+ const tokenProgramBase = (await cnx.getAccountInfo(yieldBearingMint))?.owner
201
399
 
202
400
  let interfaceIndex: number
203
401
  if ("pyth" in interfaceType) {
@@ -212,6 +410,20 @@ export class GenericSySdk {
212
410
  interfaceIndex = InterfaceType.Fragmetric
213
411
  } else if ("meteora" in interfaceType) {
214
412
  interfaceIndex = InterfaceType.Meteora
413
+ } else if ("sanctum" in interfaceType) {
414
+ interfaceIndex = InterfaceType.Sanctum
415
+ } else if ("jupiterPerps" in interfaceType) {
416
+ interfaceIndex = InterfaceType.JupiterPerps
417
+ } else if ("adrena" in interfaceType) {
418
+ interfaceIndex = InterfaceType.Adrena
419
+ } else if ("hyloLpToken" in interfaceType) {
420
+ interfaceIndex = InterfaceType.HyloLpToken
421
+ } else if ("jupiterLend" in interfaceType) {
422
+ interfaceIndex = InterfaceType.JupiterLend
423
+ } else if ("kaminoVault" in interfaceType) {
424
+ interfaceIndex = InterfaceType.KaminoVault
425
+ } else if ("solstice" in interfaceType) {
426
+ interfaceIndex = InterfaceType.Solstice
215
427
  } else {
216
428
  throw new Error("Unsupported interface type")
217
429
  }
@@ -219,14 +431,14 @@ export class GenericSySdk {
219
431
  yieldBearingMint,
220
432
  })
221
433
 
222
- const { syRate, fragmetricData } = await GenericSySdk.calculateSyRate(account, interfaceType, cnx)
434
+ const { syRate, additionalData } = await GenericSySdk.calculateSyRate(account, interfaceType, cnx)
223
435
 
224
436
  const state: GenericSyState = {
225
437
  selfAddress,
226
438
  account,
227
439
  tokenProgramBase,
228
440
  syRate,
229
- fragmetricData,
441
+ additionalData,
230
442
  }
231
443
 
232
444
  return new GenericSySdk(state, genericStandardProgramId, config)
@@ -248,14 +460,14 @@ export class GenericSySdk {
248
460
  const account = await fetcher.fetchGenericSyMeta(syMetaAddress)
249
461
  const tokenProgramBase = TOKEN_PROGRAM_ID
250
462
 
251
- const { syRate, fragmetricData } = await GenericSySdk.calculateSyRate(account, account.interfaceType, cnx)
463
+ const { syRate, additionalData } = await GenericSySdk.calculateSyRate(account, account.interfaceType, cnx)
252
464
 
253
465
  const state: GenericSyState = {
254
466
  selfAddress: syMetaAddress,
255
467
  account,
256
468
  tokenProgramBase,
257
469
  syRate,
258
- fragmetricData,
470
+ additionalData,
259
471
  }
260
472
 
261
473
  return new GenericSySdk(state, genericStandardProgramId, config)
@@ -270,9 +482,9 @@ export class GenericSySdk {
270
482
  this.state.account.interfaceType,
271
483
  )
272
484
  this.state.account = account
273
- const { syRate, fragmetricData } = await GenericSySdk.calculateSyRate(account, account.interfaceType, cnx)
485
+ const { syRate, additionalData } = await GenericSySdk.calculateSyRate(account, account.interfaceType, cnx)
274
486
  this.state.syRate = syRate
275
- this.state.fragmetricData = fragmetricData
487
+ this.state.additionalData = additionalData
276
488
  }
277
489
 
278
490
  get account() {
@@ -316,7 +528,7 @@ export class GenericSySdk {
316
528
  }
317
529
 
318
530
  get tokenVrtEscrow() {
319
- return getAssociatedTokenAddressSync(this.vrtMint, this.selfAddress, true, TOKEN_PROGRAM_ID)
531
+ return getAssociatedTokenAddressSync(this.vrtMint, this.selfAddress, true, this.tokenProgramBase)
320
532
  }
321
533
 
322
534
  get tokenSyEscrow() {
@@ -334,10 +546,30 @@ export class GenericSySdk {
334
546
  ) {
335
547
  throw new Error("Not a fragmetric interface")
336
548
  }
337
- if (!this.state.fragmetricData) {
549
+ if (!this.state.additionalData?.fragmetricData) {
338
550
  throw new Error("Fragmetric data not loaded")
339
551
  }
340
- return this.state.fragmetricData
552
+ return this.state.additionalData.fragmetricData
553
+ }
554
+
555
+ get jupiterLendData() {
556
+ if (!("jupiterLend" in this.state.account.interfaceType)) {
557
+ throw new Error("Not a Jupiter Lend interface")
558
+ }
559
+ if (!this.state.additionalData?.jupiterLendData) {
560
+ throw new Error("Jupiter Lend data not loaded")
561
+ }
562
+ return this.state.additionalData.jupiterLendData
563
+ }
564
+
565
+ get kaminoVaultData() {
566
+ if (!("kaminoVault" in this.state.account.interfaceType)) {
567
+ throw new Error("Not a Kamino Vault interface")
568
+ }
569
+ if (!this.state.additionalData?.kaminoVaultData) {
570
+ throw new Error("Kamino Vault data not loaded")
571
+ }
572
+ return this.state.additionalData.kaminoVaultData
341
573
  }
342
574
 
343
575
  get remainingAccounts() {
@@ -352,7 +584,7 @@ export class GenericSySdk {
352
584
  return accounts
353
585
  }
354
586
 
355
- getAccountsWithSigner(signer?: web3.PublicKey) {
587
+ getAccountsWithSigner(signer?: web3.PublicKey, type: "mint" | "redeem" = "mint") {
356
588
  const accounts = this.account.interfaceAccounts
357
589
  .map((a) => ({
358
590
  pubkey: a,
@@ -361,15 +593,22 @@ export class GenericSySdk {
361
593
  }))
362
594
  .concat(this.emissions.map((e) => ({ pubkey: e.escrowAccount, isSigner: false, isWritable: false })))
363
595
 
364
- if ("fragmetric" in this.state.account.interfaceType && signer) {
365
- // If skipFragmetricWrap is true, return minimal accounts
366
- if (this.config.skipFragmetricWrap) {
596
+ if (
597
+ ("fragmetric" in this.state.account.interfaceType ||
598
+ "fragmetricSupportedAsset" in this.state.account.interfaceType) &&
599
+ signer
600
+ ) {
601
+ // If skipWrap is true, return minimal accounts (skip additional interface-specific accounts)
602
+ if (this.config.skipWrap) {
367
603
  return accounts
368
604
  }
369
605
 
370
- // Existing fragmetric account logic
371
- const fragmetricReceiptTokenMint = this.state.fragmetricData.receiptTokenMint
372
- const fragmetricWrappedTokenMint = this.state.fragmetricData.wrappedTokenMint
606
+ // Fragmetric interface account logic
607
+ if (!this.state.additionalData?.fragmetricData) {
608
+ throw new Error("Fragmetric data not loaded for fragmetric interface")
609
+ }
610
+ const fragmetricReceiptTokenMint = this.state.additionalData.fragmetricData.receiptTokenMint
611
+ const fragmetricWrappedTokenMint = this.state.additionalData.fragmetricData.wrappedTokenMint
373
612
  const fragmetricPda = new FragmetricPda()
374
613
  const fragmetricFundAccount = fragmetricPda.fundAccount(fragmetricReceiptTokenMint)
375
614
  const fragmetricRewardAccount = fragmetricPda.rewardAccount(fragmetricReceiptTokenMint)
@@ -431,6 +670,215 @@ export class GenericSySdk {
431
670
  )
432
671
  }
433
672
 
673
+ if ("jupiterLend" in this.state.account.interfaceType) {
674
+ // If skipWrap is true, return minimal accounts (skip additional interface-specific accounts)
675
+ if (this.config.skipWrap) {
676
+ return accounts
677
+ }
678
+
679
+ const jupiterLendData = this.state.additionalData?.jupiterLendData
680
+ if (!jupiterLendData) {
681
+ throw new Error("Jupiter lend data not loaded")
682
+ }
683
+
684
+ console.log("accounts before push", accounts)
685
+
686
+ const vaultAuthority = new web3.PublicKey("7s1da8DduuBFqGra5bJBjpnvL5E9mGzCuMk1Qkh4or2Z")
687
+ const vaultAta = getAssociatedTokenAddressSync(
688
+ jupiterLendData.baseTokenMint,
689
+ vaultAuthority,
690
+ true,
691
+ this.tokenProgramBase,
692
+ )
693
+
694
+ if (type === "mint") {
695
+ const depositorTokenAccount = getAssociatedTokenAddressSync(
696
+ jupiterLendData.baseTokenMint,
697
+ signer,
698
+ true,
699
+ this.tokenProgramBase,
700
+ )
701
+ const recipientTokenAccount = getAssociatedTokenAddressSync(this.vrtMint, signer, true, this.tokenProgramBase)
702
+ console.log("jupiter lend rate model: ", jupiterLendData.rateModel.toBase58())
703
+ accounts.push(
704
+ { pubkey: signer, isSigner: true, isWritable: true },
705
+ { pubkey: depositorTokenAccount, isSigner: false, isWritable: true },
706
+ { pubkey: recipientTokenAccount, isSigner: false, isWritable: true },
707
+ { pubkey: jupiterLendData.baseTokenMint, isSigner: false, isWritable: true },
708
+ // lending admin
709
+ {
710
+ pubkey: new web3.PublicKey("5nmGjA4s7ATzpBQXC5RNceRpaJ7pYw2wKsNBWyuSAZV6"),
711
+ isSigner: false,
712
+ isWritable: false,
713
+ },
714
+ { pubkey: this.account.interfaceAccounts[0], isSigner: false, isWritable: true },
715
+ { pubkey: this.vrtMint, isSigner: false, isWritable: true },
716
+ { pubkey: jupiterLendData.tokenReservesLiquidity, isSigner: false, isWritable: true },
717
+ { pubkey: jupiterLendData.lendingSupplyPosition, isSigner: false, isWritable: true },
718
+ { pubkey: jupiterLendData.rateModel, isSigner: false, isWritable: true },
719
+ // vault
720
+ {
721
+ pubkey: vaultAta,
722
+ isSigner: false,
723
+ isWritable: true,
724
+ },
725
+ // supply vault owner - can be hardcoded
726
+ {
727
+ pubkey: vaultAuthority,
728
+ isSigner: false,
729
+ isWritable: true,
730
+ },
731
+ // liquidity program - can be hardcoded
732
+ {
733
+ pubkey: new web3.PublicKey("jupeiUmn818Jg1ekPURTpr4mFo29p46vygyykFJ3wZC"),
734
+ isSigner: false,
735
+ isWritable: true,
736
+ },
737
+ { pubkey: jupiterLendData.rewardsRateModel, isSigner: false, isWritable: true },
738
+ // token program
739
+ { pubkey: this.tokenProgramBase, isSigner: false, isWritable: false },
740
+ // associated token program
741
+ { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
742
+ { pubkey: web3.SystemProgram.programId, isSigner: false, isWritable: false },
743
+ {
744
+ pubkey: new web3.PublicKey("jup3YeL8QhtSx1e253b2FDvsMNC87fDrgQZivbrndc9"),
745
+ isSigner: false,
746
+ isWritable: false,
747
+ },
748
+ )
749
+ } else if (type === "redeem") {
750
+ const recipientTokenAccount = getAssociatedTokenAddressSync(
751
+ jupiterLendData.baseTokenMint,
752
+ signer,
753
+ true,
754
+ this.tokenProgramBase,
755
+ )
756
+
757
+ const depositorTokenAccount = getAssociatedTokenAddressSync(this.vrtMint, signer, true, this.tokenProgramBase)
758
+
759
+ accounts.push(
760
+ { pubkey: signer, isSigner: true, isWritable: true },
761
+ { pubkey: depositorTokenAccount, isSigner: false, isWritable: true },
762
+ { pubkey: recipientTokenAccount, isSigner: false, isWritable: true },
763
+ {
764
+ // lending admin
765
+ pubkey: new web3.PublicKey("5nmGjA4s7ATzpBQXC5RNceRpaJ7pYw2wKsNBWyuSAZV6"),
766
+ isSigner: false,
767
+ isWritable: false,
768
+ },
769
+ // lending
770
+ { pubkey: this.account.interfaceAccounts[0], isSigner: false, isWritable: true },
771
+ { pubkey: jupiterLendData.baseTokenMint, isSigner: false, isWritable: true },
772
+
773
+ { pubkey: this.vrtMint, isSigner: false, isWritable: true },
774
+ { pubkey: jupiterLendData.tokenReservesLiquidity, isSigner: false, isWritable: true },
775
+ { pubkey: jupiterLendData.lendingSupplyPosition, isSigner: false, isWritable: true },
776
+ { pubkey: jupiterLendData.rateModel, isSigner: false, isWritable: true },
777
+ // vault
778
+ {
779
+ pubkey: vaultAta,
780
+ isSigner: false,
781
+ isWritable: true,
782
+ },
783
+ // claim account
784
+ {
785
+ pubkey: new web3.PublicKey("HN1r4VfkDn53xQQfeGDYrNuDKFdemAhZsHYRwBrFhsW"),
786
+ isSigner: false,
787
+ isWritable: true,
788
+ },
789
+ // liquidity
790
+ {
791
+ pubkey: new web3.PublicKey("7s1da8DduuBFqGra5bJBjpnvL5E9mGzCuMk1Qkh4or2Z"),
792
+ isSigner: false,
793
+ isWritable: true,
794
+ },
795
+ // liquidity program
796
+ {
797
+ pubkey: new web3.PublicKey("jupeiUmn818Jg1ekPURTpr4mFo29p46vygyykFJ3wZC"),
798
+ isSigner: false,
799
+ isWritable: true,
800
+ },
801
+ { pubkey: jupiterLendData.rewardsRateModel, isSigner: false, isWritable: true },
802
+ // token program
803
+ { pubkey: this.tokenProgramBase, isSigner: false, isWritable: false },
804
+ // associated token program
805
+ { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
806
+ { pubkey: web3.SystemProgram.programId, isSigner: false, isWritable: false },
807
+ {
808
+ pubkey: new web3.PublicKey("jup3YeL8QhtSx1e253b2FDvsMNC87fDrgQZivbrndc9"),
809
+ isSigner: false,
810
+ isWritable: false,
811
+ },
812
+ )
813
+ }
814
+ }
815
+
816
+ if ("kaminoVault" in this.state.account.interfaceType) {
817
+ // If skipWrap is true, return minimal accounts (skip additional interface-specific accounts)
818
+ if (this.config.skipWrap) {
819
+ return accounts
820
+ }
821
+
822
+ const kaminoVaultData = this.state.additionalData?.kaminoVaultData
823
+ if (!kaminoVaultData) {
824
+ throw new Error("Kamino vault data not loaded")
825
+ }
826
+
827
+ const userTokenAta = getAssociatedTokenAddressSync(kaminoVaultData.tokenMint, signer, true, TOKEN_PROGRAM_ID)
828
+ const userSharesAta = getAssociatedTokenAddressSync(this.vrtMint, signer, true, TOKEN_PROGRAM_ID)
829
+
830
+ accounts.push(
831
+ // user
832
+ { pubkey: signer, isSigner: true, isWritable: true },
833
+ // vault_state
834
+ { pubkey: kaminoVaultData.vault, isSigner: false, isWritable: true },
835
+ // token_vault
836
+ { pubkey: kaminoVaultData.tokenVault, isSigner: false, isWritable: true },
837
+ // token_mint
838
+ { pubkey: kaminoVaultData.tokenMint, isSigner: false, isWritable: true },
839
+ // base_vault_authority
840
+ { pubkey: kaminoVaultData.baseVaultAuthority, isSigner: false, isWritable: true },
841
+ // shares_mint
842
+ { pubkey: kaminoVaultData.sharesMint, isSigner: false, isWritable: true },
843
+ // user_token_ata
844
+ { pubkey: userTokenAta, isSigner: false, isWritable: true },
845
+ // user_shares_ata
846
+ { pubkey: userSharesAta, isSigner: false, isWritable: true },
847
+ // klend_program
848
+ {
849
+ pubkey: new web3.PublicKey("KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD"),
850
+ isSigner: false,
851
+ isWritable: false,
852
+ },
853
+ // token_program
854
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
855
+ // shares_token_program
856
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
857
+ // event_authority
858
+ {
859
+ pubkey: new web3.PublicKey("24tHwQyJJ9akVXxnvkekGfAoeUJXXS7mE6kQNioNySsK"),
860
+ isSigner: false,
861
+ isWritable: true,
862
+ },
863
+ // kamino vault program
864
+ {
865
+ pubkey: new web3.PublicKey("KvauGMspG5k6rtzrqqn7WNn3oZdyKqLKwK2XWQ8FLjd"),
866
+ isSigner: false,
867
+ isWritable: false,
868
+ },
869
+ ...kaminoVaultData.reserves.map((reserve) => ({
870
+ pubkey: reserve.reserveAddress,
871
+ isSigner: false,
872
+ isWritable: true,
873
+ })),
874
+ ...kaminoVaultData.reserves.map((reserve) => ({
875
+ pubkey: reserve.marketAddress,
876
+ isSigner: false,
877
+ isWritable: true,
878
+ })),
879
+ )
880
+ }
881
+
434
882
  return accounts
435
883
  }
436
884
 
@@ -446,16 +894,13 @@ export class GenericSySdk {
446
894
  syDst?: web3.PublicKey
447
895
  }) {
448
896
  baseSrc = baseSrc || getAssociatedTokenAddressSync(this.vrtMint, depositor, true, this.state.tokenProgramBase)
449
- console.log("baseSrc", baseSrc.toBase58())
450
- console.log("depositor", depositor.toBase58())
451
897
  syDst = syDst || getAssociatedTokenAddressSync(this.mintSy, depositor, true, TOKEN_PROGRAM_ID)
452
898
 
453
- console.log("this.selfAddress", this.selfAddress.toBase58())
454
899
  return this.program.methods
455
900
  .mint(new BN(amountBase))
456
901
  .accountsStrict({
457
902
  meta: this.selfAddress,
458
- baseTokenProgram: this.tokenProgramBase,
903
+ baseTokenProgram: this.state.tokenProgramBase,
459
904
  depositor,
460
905
  mintSy: this.mintSy,
461
906
  tokenBaseDepositor: baseSrc,
@@ -493,10 +938,55 @@ export class GenericSySdk {
493
938
  baseTokenProgram: this.tokenProgramBase,
494
939
  tokenYieldBearingEscrow: this.tokenVrtEscrow,
495
940
  })
496
- .remainingAccounts(this.getAccountsWithSigner(redeemer))
941
+ .remainingAccounts(this.getAccountsWithSigner(redeemer, "redeem"))
497
942
  .instruction()
498
943
  }
499
944
 
945
+ preInstructions() {
946
+ let ixs = []
947
+ if ("jupiterLend" in this.state.account.interfaceType) {
948
+ const jupiterLendData = this.state.additionalData?.jupiterLendData
949
+ if (!jupiterLendData) {
950
+ throw new Error("Jupiter lend data not loaded")
951
+ }
952
+
953
+ const refreshInstruction = new web3.TransactionInstruction({
954
+ keys: [
955
+ {
956
+ pubkey: this.account.interfaceAccounts[0],
957
+ isSigner: false,
958
+ isWritable: true,
959
+ },
960
+ {
961
+ pubkey: jupiterLendData.baseTokenMint,
962
+ isSigner: false,
963
+ isWritable: true,
964
+ },
965
+ {
966
+ pubkey: this.vrtMint,
967
+ isSigner: false,
968
+ isWritable: true,
969
+ },
970
+ {
971
+ pubkey: jupiterLendData.tokenReservesLiquidity,
972
+ isSigner: false,
973
+ isWritable: true,
974
+ },
975
+ {
976
+ pubkey: jupiterLendData.rewardsRateModel,
977
+ isSigner: false,
978
+ isWritable: true,
979
+ },
980
+ ],
981
+ programId: new web3.PublicKey("jup3YeL8QhtSx1e253b2FDvsMNC87fDrgQZivbrndc9"),
982
+ data: Buffer.from([24, 225, 53, 189, 72, 212, 225, 178]),
983
+ })
984
+ ixs.push(refreshInstruction)
985
+ }
986
+
987
+ return ixs
988
+ }
989
+
500
990
  getSyState() {
501
991
  return this.program.methods
502
992
  .getState()
@@ -540,13 +1030,16 @@ export class GenericSySdk {
540
1030
  postRedeemHookDiscriminator: Buffer.from(hook.postRedeemHookDiscriminator),
541
1031
  }
542
1032
 
543
- return this.program.methods.modifyHook(modifiedHook).accountsStrict({
544
- adminState: this.adminState,
545
- signer,
546
- feePayer: signer,
547
- meta: this.selfAddress,
548
- systemProgram: web3.SystemProgram.programId,
549
- })
1033
+ return this.program.methods
1034
+ .modifyHook(modifiedHook)
1035
+ .accountsStrict({
1036
+ adminState: this.adminState,
1037
+ signer,
1038
+ feePayer: signer,
1039
+ meta: this.selfAddress,
1040
+ systemProgram: web3.SystemProgram.programId,
1041
+ })
1042
+ .instruction()
550
1043
  }
551
1044
  }
552
1045
 
@@ -557,18 +1050,18 @@ export function initSy(
557
1050
  interfaceIndex: number,
558
1051
  syToken?: SyTokenMetadata,
559
1052
  initConfig?: SyInitializeConfig,
1053
+ yieldBearingMintTokenProgram: web3.PublicKey = TOKEN_PROGRAM_ID,
560
1054
  ) {
561
1055
  const program = new Program<GenericStandard>(
562
1056
  IDL,
563
1057
  new AnchorProvider(new web3.Connection("https://api.devnet.solana.com"), new MyWallet(web3.Keypair.generate())),
564
1058
  )
565
1059
 
566
- console.log("interfaceIndex", interfaceIndex)
567
1060
  const pda = new GenericSyPda(program.programId, interfaceIndex)
568
1061
  const syMetaAddress = pda.syMeta({ yieldBearingMint })
569
- console.log("this.selfAddress in sdk", syMetaAddress.toBase58())
1062
+
570
1063
  const mintSy = pda.mintSy({ yieldBearingMint })
571
- console.log("mintSy in sdk", mintSy.toBase58())
1064
+
572
1065
  const exponentAdminPda = new ExponentAdminPda(EXPONENT_ADMIN_PROGRAM_ID)
573
1066
 
574
1067
  const metaplexMetadataProgram = new web3.PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s")
@@ -577,14 +1070,19 @@ export function initSy(
577
1070
  metaplexMetadataProgram,
578
1071
  )[0]
579
1072
 
580
- const tokenVrtEscrow = getAssociatedTokenAddressSync(yieldBearingMint, syMetaAddress, true, TOKEN_PROGRAM_ID)
1073
+ const tokenVrtEscrow = getAssociatedTokenAddressSync(
1074
+ yieldBearingMint,
1075
+ syMetaAddress,
1076
+ true,
1077
+ yieldBearingMintTokenProgram,
1078
+ )
581
1079
 
582
1080
  const { minMintSize, minRedeemSize } = initConfig ? initConfig : { minMintSize: new BN(0), minRedeemSize: new BN(0) }
583
1081
  const {
584
1082
  name: tokenName,
585
1083
  uri: tokenUri,
586
1084
  symbol: tokenSymbol,
587
- } = syToken ? syToken : { symbol: "ewfragBTC", name: "Exponent Wrapped wfragBTC", uri: "" }
1085
+ } = syToken ? syToken : { symbol: "wjlSOL", name: "Exponent Wrapped jlSOL", uri: "" }
588
1086
 
589
1087
  const interfaceType = getInterfaceTypeObj(interfaceIndex)
590
1088
  const ix = program.methods
@@ -596,7 +1094,7 @@ export function initSy(
596
1094
  admin: signer,
597
1095
  yieldBearingMint,
598
1096
  syTokenProgram: TOKEN_PROGRAM_ID,
599
- yieldBearingTokenProgram: TOKEN_PROGRAM_ID,
1097
+ yieldBearingTokenProgram: yieldBearingMintTokenProgram,
600
1098
  tokenSyEscrow: pda.syEscrow({ yieldBearingMint }),
601
1099
  systemProgram: web3.SystemProgram.programId,
602
1100
  metadata: mintSyMetaplexMetadataPda,