@exponent-labs/generic-sy-sdk 0.9.20 → 0.9.22
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/build/index.d.ts +16 -3
- package/build/index.js +164 -211
- package/build/index.js.map +1 -1
- package/build/interfaces/exponentTranching.d.ts +12 -0
- package/build/interfaces/exponentTranching.js +75 -0
- package/build/interfaces/exponentTranching.js.map +1 -0
- package/build/interfaces/glowVault.d.ts +7 -0
- package/build/interfaces/glowVault.js +46 -0
- package/build/interfaces/glowVault.js.map +1 -0
- package/build/types.d.ts +0 -1
- package/package.json +9 -8
- package/src/index.ts +287 -165
- package/src/interfaces/exponentTranching.ts +125 -0
- package/src/interfaces/glowVault.ts +55 -0
- package/tsconfig.json +3 -0
package/src/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
5
5
|
TOKEN_2022_PROGRAM_ID,
|
|
6
6
|
TOKEN_PROGRAM_ID,
|
|
7
|
+
createAssociatedTokenAccountIdempotentInstruction,
|
|
7
8
|
getAssociatedTokenAddressSync,
|
|
8
9
|
} from "@solana/spl-token"
|
|
9
10
|
|
|
@@ -30,15 +31,83 @@ import {
|
|
|
30
31
|
GenericSyState,
|
|
31
32
|
Hook,
|
|
32
33
|
InterfaceTypeGeneric,
|
|
34
|
+
getGenericSyMetaInitInterfaceType,
|
|
35
|
+
getGenericSyMetaInterfaceType,
|
|
33
36
|
} from "@exponent-labs/exponent-types"
|
|
34
37
|
import { FRAGMETRIC_PROGRAM_ID, FragmetricPda } from "@exponent-labs/fragmetric-pda"
|
|
35
38
|
import { PROGRAM_ID as GENERIC_STANDARD_PROGRAM_ID, GenericStandard, IDL } from "@exponent-labs/generic-sy-idl"
|
|
36
39
|
import { GenericSyPda } from "@exponent-labs/generic-sy-pda"
|
|
37
40
|
import { PreciseNumber } from "@exponent-labs/precise-number"
|
|
38
41
|
|
|
42
|
+
import {
|
|
43
|
+
buildExponentTranchingUpdateMarketInstruction,
|
|
44
|
+
fetchExponentTranchingRate,
|
|
45
|
+
} from "./interfaces/exponentTranching"
|
|
46
|
+
import { fetchGlowVaultRate } from "./interfaces/glowVault"
|
|
39
47
|
import { SyInitializeConfig, SyTokenMetadata } from "./types"
|
|
40
48
|
import { MyWallet } from "./utils"
|
|
41
49
|
|
|
50
|
+
const GET_STATE_DISCRIMINATOR = Buffer.from([7])
|
|
51
|
+
|
|
52
|
+
async function fetchOnChainSyRate({
|
|
53
|
+
connection,
|
|
54
|
+
programId,
|
|
55
|
+
meta,
|
|
56
|
+
mintSy,
|
|
57
|
+
tokenSyEscrow,
|
|
58
|
+
remainingAccounts,
|
|
59
|
+
}: {
|
|
60
|
+
connection: web3.Connection
|
|
61
|
+
programId: web3.PublicKey
|
|
62
|
+
meta: web3.PublicKey
|
|
63
|
+
mintSy: web3.PublicKey
|
|
64
|
+
tokenSyEscrow: web3.PublicKey
|
|
65
|
+
remainingAccounts: web3.AccountMeta[]
|
|
66
|
+
}): Promise<number> {
|
|
67
|
+
const instruction = new web3.TransactionInstruction({
|
|
68
|
+
programId,
|
|
69
|
+
keys: [
|
|
70
|
+
{ pubkey: meta, isSigner: false, isWritable: true },
|
|
71
|
+
{ pubkey: mintSy, isSigner: false, isWritable: false },
|
|
72
|
+
{ pubkey: tokenSyEscrow, isSigner: false, isWritable: false },
|
|
73
|
+
...remainingAccounts,
|
|
74
|
+
],
|
|
75
|
+
data: GET_STATE_DISCRIMINATOR,
|
|
76
|
+
})
|
|
77
|
+
const [feePayer, { blockhash }] = await Promise.all([
|
|
78
|
+
connection.getSlotLeader("confirmed"),
|
|
79
|
+
connection.getLatestBlockhash("confirmed"),
|
|
80
|
+
])
|
|
81
|
+
const message = new web3.TransactionMessage({
|
|
82
|
+
payerKey: new web3.PublicKey(feePayer),
|
|
83
|
+
recentBlockhash: blockhash,
|
|
84
|
+
instructions: [instruction],
|
|
85
|
+
}).compileToV0Message()
|
|
86
|
+
const simulation = await connection.simulateTransaction(new web3.VersionedTransaction(message), {
|
|
87
|
+
commitment: "confirmed",
|
|
88
|
+
replaceRecentBlockhash: true,
|
|
89
|
+
sigVerify: false,
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
if (simulation.value.err) {
|
|
93
|
+
const logs = simulation.value.logs?.join("\n") ?? "No simulation logs"
|
|
94
|
+
throw new Error(`Generic Standard get_state simulation failed: ${JSON.stringify(simulation.value.err)}\n${logs}`)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const returnData = simulation.value.returnData
|
|
98
|
+
if (!returnData || returnData.programId !== programId.toBase58()) {
|
|
99
|
+
throw new Error("Generic Standard get_state returned invalid program data")
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const data = Buffer.from(returnData.data[0], "base64")
|
|
103
|
+
if (data.length < 32) {
|
|
104
|
+
throw new Error("Generic Standard get_state return data is too short")
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const exchangeRate = Array.from({ length: 4 }, (_, index) => new BN(data.subarray(index * 8, (index + 1) * 8), "le"))
|
|
108
|
+
return Number(PreciseNumber.fromRaw(exchangeRate).valueString)
|
|
109
|
+
}
|
|
110
|
+
|
|
42
111
|
/**
|
|
43
112
|
* Create a custom updateStakePoolBalance instruction using dynamic program ID
|
|
44
113
|
*/
|
|
@@ -86,48 +155,7 @@ async function loadAccountState(
|
|
|
86
155
|
genericStandardProgramId: web3.PublicKey,
|
|
87
156
|
interfaceType: InterfaceTypeGeneric,
|
|
88
157
|
) {
|
|
89
|
-
|
|
90
|
-
if ("pyth" in interfaceType) {
|
|
91
|
-
interfaceIndex = InterfaceType.Pyth
|
|
92
|
-
} else if ("splStakePool" in interfaceType) {
|
|
93
|
-
interfaceIndex = InterfaceType.SplStakePool
|
|
94
|
-
} else if ("one" in interfaceType) {
|
|
95
|
-
interfaceIndex = InterfaceType.One
|
|
96
|
-
} else if ("fragmetric" in interfaceType) {
|
|
97
|
-
interfaceIndex = InterfaceType.Fragmetric
|
|
98
|
-
} else if ("meteora" in interfaceType) {
|
|
99
|
-
interfaceIndex = InterfaceType.Meteora
|
|
100
|
-
} else if ("sanctum" in interfaceType) {
|
|
101
|
-
interfaceIndex = InterfaceType.Sanctum
|
|
102
|
-
} else if ("fragmetricSupportedAsset" in interfaceType) {
|
|
103
|
-
interfaceIndex = InterfaceType.FragmetricSupportedAsset
|
|
104
|
-
} else if ("jupiterPerps" in interfaceType) {
|
|
105
|
-
interfaceIndex = InterfaceType.JupiterPerps
|
|
106
|
-
} else if ("adrena" in interfaceType) {
|
|
107
|
-
interfaceIndex = InterfaceType.Adrena
|
|
108
|
-
} else if ("hyloLpToken" in interfaceType) {
|
|
109
|
-
interfaceIndex = InterfaceType.HyloLpToken
|
|
110
|
-
} else if ("jupiterLend" in interfaceType) {
|
|
111
|
-
interfaceIndex = InterfaceType.JupiterLend
|
|
112
|
-
} else if ("kaminoVault" in interfaceType) {
|
|
113
|
-
interfaceIndex = InterfaceType.KaminoVault
|
|
114
|
-
} else if ("solstice" in interfaceType) {
|
|
115
|
-
interfaceIndex = InterfaceType.Solstice
|
|
116
|
-
} else if ("reflect" in interfaceType) {
|
|
117
|
-
interfaceIndex = InterfaceType.Reflect
|
|
118
|
-
} else if ("ore" in interfaceType) {
|
|
119
|
-
interfaceIndex = InterfaceType.Ore
|
|
120
|
-
} else if ("chainlink" in interfaceType) {
|
|
121
|
-
interfaceIndex = InterfaceType.Chainlink
|
|
122
|
-
} else if ("chainlinkDataStream" in interfaceType) {
|
|
123
|
-
interfaceIndex = InterfaceType.ChainlinkDataStream
|
|
124
|
-
} else if ("scope" in interfaceType) {
|
|
125
|
-
interfaceIndex = InterfaceType.Scope
|
|
126
|
-
} else if ("solsticeGlamVault" in interfaceType) {
|
|
127
|
-
interfaceIndex = InterfaceType.SolsticeGlamVault
|
|
128
|
-
} else {
|
|
129
|
-
throw new Error("Unsupported interface type")
|
|
130
|
-
}
|
|
158
|
+
const interfaceIndex = getInterfaceTypeIndex(interfaceType)
|
|
131
159
|
const pda = new GenericSyPda(genericStandardProgramId, interfaceIndex)
|
|
132
160
|
const fetcher = new ExponentFetcher({ connection: cnx, genericStandardProgramId })
|
|
133
161
|
const syMetaAddress = pda.syMeta({ yieldBearingMint })
|
|
@@ -157,6 +185,36 @@ export enum InterfaceType {
|
|
|
157
185
|
ChainlinkDataStream = 16,
|
|
158
186
|
Scope = 17,
|
|
159
187
|
SolsticeGlamVault = 18,
|
|
188
|
+
ExponentTranching = 19,
|
|
189
|
+
GlowVault = 20,
|
|
190
|
+
LoopscaleVaultLp = 21,
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export function getInterfaceTypeIndex(interfaceType: InterfaceTypeGeneric): InterfaceType {
|
|
194
|
+
if ("pyth" in interfaceType) return InterfaceType.Pyth
|
|
195
|
+
if ("splStakePool" in interfaceType) return InterfaceType.SplStakePool
|
|
196
|
+
if ("one" in interfaceType) return InterfaceType.One
|
|
197
|
+
if ("fragmetricSupportedAsset" in interfaceType) return InterfaceType.FragmetricSupportedAsset
|
|
198
|
+
if ("fragmetric" in interfaceType) return InterfaceType.Fragmetric
|
|
199
|
+
if ("meteora" in interfaceType) return InterfaceType.Meteora
|
|
200
|
+
if ("sanctum" in interfaceType) return InterfaceType.Sanctum
|
|
201
|
+
if ("jupiterPerps" in interfaceType) return InterfaceType.JupiterPerps
|
|
202
|
+
if ("adrena" in interfaceType) return InterfaceType.Adrena
|
|
203
|
+
if ("hyloLpToken" in interfaceType) return InterfaceType.HyloLpToken
|
|
204
|
+
if ("jupiterLend" in interfaceType) return InterfaceType.JupiterLend
|
|
205
|
+
if ("kaminoVault" in interfaceType) return InterfaceType.KaminoVault
|
|
206
|
+
if ("solstice" in interfaceType) return InterfaceType.Solstice
|
|
207
|
+
if ("reflect" in interfaceType) return InterfaceType.Reflect
|
|
208
|
+
if ("ore" in interfaceType) return InterfaceType.Ore
|
|
209
|
+
if ("chainlinkDataStream" in interfaceType) return InterfaceType.ChainlinkDataStream
|
|
210
|
+
if ("chainlink" in interfaceType) return InterfaceType.Chainlink
|
|
211
|
+
if ("scope" in interfaceType) return InterfaceType.Scope
|
|
212
|
+
if ("solsticeGlamVault" in interfaceType) return InterfaceType.SolsticeGlamVault
|
|
213
|
+
if ("exponentTranching" in interfaceType) return InterfaceType.ExponentTranching
|
|
214
|
+
if ("glowVault" in interfaceType) return InterfaceType.GlowVault
|
|
215
|
+
if ("loopscaleVaultLp" in interfaceType) return InterfaceType.LoopscaleVaultLp
|
|
216
|
+
|
|
217
|
+
throw new Error("Unsupported interface type")
|
|
160
218
|
}
|
|
161
219
|
|
|
162
220
|
export function getInterfaceTypeObj(
|
|
@@ -219,6 +277,12 @@ export function getInterfaceTypeObj(
|
|
|
219
277
|
return { scope: { priceChain: scopePriceChain, maximumAgeSeconds: new BN(scopeMaximumAgeSeconds) } }
|
|
220
278
|
case InterfaceType.SolsticeGlamVault:
|
|
221
279
|
return { solsticeGlamVault: { padding: [] } }
|
|
280
|
+
case InterfaceType.ExponentTranching:
|
|
281
|
+
return { exponentTranching: {} }
|
|
282
|
+
case InterfaceType.GlowVault:
|
|
283
|
+
return { glowVault: { padding: [] } }
|
|
284
|
+
case InterfaceType.LoopscaleVaultLp:
|
|
285
|
+
return { loopscaleVaultLp: { padding: [] } }
|
|
222
286
|
default:
|
|
223
287
|
throw new Error(`Unsupported interface type: ${interfaceType}`)
|
|
224
288
|
}
|
|
@@ -278,6 +342,13 @@ export function getInterfaceTypeFromString(interfaceType: string): InterfaceType
|
|
|
278
342
|
return { scope: { priceChain: [0, 512, 512, 512], maximumAgeSeconds: new BN(3600) } }
|
|
279
343
|
case "solstice-glam-vault":
|
|
280
344
|
return { solsticeGlamVault: { padding: [] } }
|
|
345
|
+
case "exponent-tranching":
|
|
346
|
+
return { exponentTranching: {} }
|
|
347
|
+
case "glow-vault":
|
|
348
|
+
return { glowVault: { padding: [] } }
|
|
349
|
+
case "loopscale-vault":
|
|
350
|
+
case "loopscale-vault-lp":
|
|
351
|
+
return { loopscaleVaultLp: { padding: [] } }
|
|
281
352
|
default:
|
|
282
353
|
throw new Error(`Unsupported interface type: ${interfaceType}`)
|
|
283
354
|
}
|
|
@@ -306,61 +377,26 @@ export class GenericSySdk {
|
|
|
306
377
|
new AnchorProvider(new web3.Connection("https://api.devnet.solana.com"), new MyWallet(web3.Keypair.generate())),
|
|
307
378
|
)
|
|
308
379
|
|
|
309
|
-
|
|
310
|
-
let interfaceIndex: number
|
|
311
|
-
if ("pyth" in this.state.account.interfaceType) {
|
|
312
|
-
interfaceIndex = InterfaceType.Pyth
|
|
313
|
-
} else if ("splStakePool" in this.state.account.interfaceType) {
|
|
314
|
-
interfaceIndex = InterfaceType.SplStakePool
|
|
315
|
-
} else if ("one" in this.state.account.interfaceType) {
|
|
316
|
-
interfaceIndex = InterfaceType.One
|
|
317
|
-
} else if ("fragmetricSupportedAsset" in this.state.account.interfaceType) {
|
|
318
|
-
interfaceIndex = InterfaceType.FragmetricSupportedAsset
|
|
319
|
-
} else if ("fragmetric" in this.state.account.interfaceType) {
|
|
320
|
-
interfaceIndex = InterfaceType.Fragmetric
|
|
321
|
-
} else if ("meteora" in this.state.account.interfaceType) {
|
|
322
|
-
interfaceIndex = InterfaceType.Meteora
|
|
323
|
-
} else if ("sanctum" in this.state.account.interfaceType) {
|
|
324
|
-
interfaceIndex = InterfaceType.Sanctum
|
|
325
|
-
} else if ("jupiterPerps" in this.state.account.interfaceType) {
|
|
326
|
-
interfaceIndex = InterfaceType.JupiterPerps
|
|
327
|
-
} else if ("adrena" in this.state.account.interfaceType) {
|
|
328
|
-
interfaceIndex = InterfaceType.Adrena
|
|
329
|
-
} else if ("hyloLpToken" in this.state.account.interfaceType) {
|
|
330
|
-
interfaceIndex = InterfaceType.HyloLpToken
|
|
331
|
-
} else if ("jupiterLend" in this.state.account.interfaceType) {
|
|
332
|
-
interfaceIndex = InterfaceType.JupiterLend
|
|
333
|
-
} else if ("kaminoVault" in this.state.account.interfaceType) {
|
|
334
|
-
interfaceIndex = InterfaceType.KaminoVault
|
|
335
|
-
} else if ("solstice" in this.state.account.interfaceType) {
|
|
336
|
-
interfaceIndex = InterfaceType.Solstice
|
|
337
|
-
} else if ("reflect" in this.state.account.interfaceType) {
|
|
338
|
-
interfaceIndex = InterfaceType.Reflect
|
|
339
|
-
} else if ("ore" in this.state.account.interfaceType) {
|
|
340
|
-
interfaceIndex = InterfaceType.Ore
|
|
341
|
-
} else if ("chainlink" in this.state.account.interfaceType) {
|
|
342
|
-
interfaceIndex = InterfaceType.Chainlink
|
|
343
|
-
} else if ("chainlinkDataStream" in this.state.account.interfaceType) {
|
|
344
|
-
interfaceIndex = InterfaceType.ChainlinkDataStream
|
|
345
|
-
} else if ("scope" in this.state.account.interfaceType) {
|
|
346
|
-
interfaceIndex = InterfaceType.Scope
|
|
347
|
-
} else if ("solsticeGlamVault" in this.state.account.interfaceType) {
|
|
348
|
-
interfaceIndex = InterfaceType.SolsticeGlamVault
|
|
349
|
-
} else {
|
|
350
|
-
throw new Error("Unsupported interface type")
|
|
351
|
-
}
|
|
352
|
-
|
|
380
|
+
const interfaceIndex = getInterfaceTypeIndex(getGenericSyMetaInitInterfaceType(this.state.account))
|
|
353
381
|
this.syPda = new GenericSyPda(programId, interfaceIndex)
|
|
354
382
|
}
|
|
355
383
|
|
|
356
|
-
private static async calculateSyRate(
|
|
357
|
-
account
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
384
|
+
private static async calculateSyRate({
|
|
385
|
+
account,
|
|
386
|
+
cnx,
|
|
387
|
+
syMetaAddress,
|
|
388
|
+
genericStandardProgramId,
|
|
389
|
+
}: {
|
|
390
|
+
account: GenericSyMetaAccount
|
|
391
|
+
cnx: web3.Connection
|
|
392
|
+
syMetaAddress: web3.PublicKey
|
|
393
|
+
genericStandardProgramId: web3.PublicKey
|
|
394
|
+
}): Promise<{
|
|
361
395
|
syRate: number
|
|
362
396
|
additionalData?: AdditionalDataGeneric
|
|
363
397
|
}> {
|
|
398
|
+
const interfaceType = getGenericSyMetaInterfaceType(account)
|
|
399
|
+
|
|
364
400
|
if ("pyth" in interfaceType) {
|
|
365
401
|
const syRate = Number(PreciseNumber.fromRaw(account.index[0]).valueString)
|
|
366
402
|
return { syRate: syRate }
|
|
@@ -414,7 +450,7 @@ export class GenericSySdk {
|
|
|
414
450
|
} else if ("meteora" in interfaceType) {
|
|
415
451
|
const currentTs = Math.floor(Date.now() / 1000)
|
|
416
452
|
|
|
417
|
-
|
|
453
|
+
let accounts = {
|
|
418
454
|
pool: account.interfaceAccounts[0],
|
|
419
455
|
vaultA: account.interfaceAccounts[4],
|
|
420
456
|
vaultB: account.interfaceAccounts[5],
|
|
@@ -434,11 +470,10 @@ export class GenericSySdk {
|
|
|
434
470
|
|
|
435
471
|
return { syRate: exchangeRate }
|
|
436
472
|
} else if ("adrena" in interfaceType) {
|
|
437
|
-
|
|
438
|
-
const previousTotalFees = account.interfaceType.adrena.previousTotalFees
|
|
473
|
+
const previousTotalFees = interfaceType.adrena.previousTotalFees
|
|
439
474
|
const currentIndex = account.index
|
|
440
475
|
|
|
441
|
-
|
|
476
|
+
const accounts = {
|
|
442
477
|
pool: account.interfaceAccounts[0],
|
|
443
478
|
custody1: account.interfaceAccounts[1],
|
|
444
479
|
custody2: account.interfaceAccounts[2],
|
|
@@ -450,8 +485,7 @@ export class GenericSySdk {
|
|
|
450
485
|
|
|
451
486
|
return { syRate: syRate.index }
|
|
452
487
|
} else if ("jupiterPerps" in interfaceType) {
|
|
453
|
-
|
|
454
|
-
const j = account.interfaceType.jupiterPerps
|
|
488
|
+
const j = interfaceType.jupiterPerps
|
|
455
489
|
const { index } = await fetchJupiterPerpsIndex({
|
|
456
490
|
connection: cnx,
|
|
457
491
|
pool: account.interfaceAccounts[0],
|
|
@@ -574,6 +608,50 @@ export class GenericSySdk {
|
|
|
574
608
|
stslxMint,
|
|
575
609
|
})
|
|
576
610
|
return { syRate }
|
|
611
|
+
} else if ("exponentTranching" in interfaceType) {
|
|
612
|
+
const marketAddress = account.interfaceAccounts[0]
|
|
613
|
+
if (account.interfaceAccounts.length !== 1 || !marketAddress) {
|
|
614
|
+
throw new Error("Exponent Tranching interface requires exactly one market account")
|
|
615
|
+
}
|
|
616
|
+
const syRate = await fetchExponentTranchingRate({
|
|
617
|
+
connection: cnx,
|
|
618
|
+
marketAddress,
|
|
619
|
+
yieldBearingMint: account.yieldBearingMint,
|
|
620
|
+
})
|
|
621
|
+
return { syRate }
|
|
622
|
+
} else if ("glowVault" in interfaceType) {
|
|
623
|
+
const vaultAddress = account.interfaceAccounts[0]
|
|
624
|
+
if (account.interfaceAccounts.length !== 1 || !vaultAddress) {
|
|
625
|
+
throw new Error("Glow Vault interface requires exactly one vault account")
|
|
626
|
+
}
|
|
627
|
+
const syRate = await fetchGlowVaultRate({
|
|
628
|
+
connection: cnx,
|
|
629
|
+
vaultAddress,
|
|
630
|
+
expectedShareMint: account.yieldBearingMint,
|
|
631
|
+
})
|
|
632
|
+
return { syRate }
|
|
633
|
+
} else if ("loopscaleVaultLp" in interfaceType) {
|
|
634
|
+
if (account.interfaceAccounts.length !== 3) {
|
|
635
|
+
throw new Error("Loopscale Vault LP interface requires exactly three accounts")
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
const syRate = await fetchOnChainSyRate({
|
|
639
|
+
connection: cnx,
|
|
640
|
+
programId: genericStandardProgramId,
|
|
641
|
+
meta: syMetaAddress,
|
|
642
|
+
mintSy: account.mintSy,
|
|
643
|
+
tokenSyEscrow: account.tokenSyEscrow,
|
|
644
|
+
remainingAccounts: account.interfaceAccounts
|
|
645
|
+
.map((pubkey) => ({ pubkey, isSigner: false, isWritable: false }))
|
|
646
|
+
.concat(
|
|
647
|
+
account.emissions.map((emission) => ({
|
|
648
|
+
pubkey: emission.escrowAccount,
|
|
649
|
+
isSigner: false,
|
|
650
|
+
isWritable: false,
|
|
651
|
+
})),
|
|
652
|
+
),
|
|
653
|
+
})
|
|
654
|
+
return { syRate }
|
|
577
655
|
} else {
|
|
578
656
|
return { syRate: 1 }
|
|
579
657
|
}
|
|
@@ -596,53 +674,17 @@ export class GenericSySdk {
|
|
|
596
674
|
const account = await loadAccountState(cnx, yieldBearingMint, genericStandardProgramId, interfaceType)
|
|
597
675
|
const tokenProgramBase = (await cnx.getAccountInfo(yieldBearingMint))?.owner
|
|
598
676
|
|
|
599
|
-
|
|
600
|
-
if ("pyth" in interfaceType) {
|
|
601
|
-
interfaceIndex = InterfaceType.Pyth
|
|
602
|
-
} else if ("splStakePool" in interfaceType) {
|
|
603
|
-
interfaceIndex = InterfaceType.SplStakePool
|
|
604
|
-
} else if ("one" in interfaceType) {
|
|
605
|
-
interfaceIndex = InterfaceType.One
|
|
606
|
-
} else if ("fragmetricSupportedAsset" in interfaceType) {
|
|
607
|
-
interfaceIndex = InterfaceType.FragmetricSupportedAsset
|
|
608
|
-
} else if ("fragmetric" in interfaceType) {
|
|
609
|
-
interfaceIndex = InterfaceType.Fragmetric
|
|
610
|
-
} else if ("meteora" in interfaceType) {
|
|
611
|
-
interfaceIndex = InterfaceType.Meteora
|
|
612
|
-
} else if ("sanctum" in interfaceType) {
|
|
613
|
-
interfaceIndex = InterfaceType.Sanctum
|
|
614
|
-
} else if ("jupiterPerps" in interfaceType) {
|
|
615
|
-
interfaceIndex = InterfaceType.JupiterPerps
|
|
616
|
-
} else if ("adrena" in interfaceType) {
|
|
617
|
-
interfaceIndex = InterfaceType.Adrena
|
|
618
|
-
} else if ("hyloLpToken" in interfaceType) {
|
|
619
|
-
interfaceIndex = InterfaceType.HyloLpToken
|
|
620
|
-
} else if ("jupiterLend" in interfaceType) {
|
|
621
|
-
interfaceIndex = InterfaceType.JupiterLend
|
|
622
|
-
} else if ("kaminoVault" in interfaceType) {
|
|
623
|
-
interfaceIndex = InterfaceType.KaminoVault
|
|
624
|
-
} else if ("solstice" in interfaceType) {
|
|
625
|
-
interfaceIndex = InterfaceType.Solstice
|
|
626
|
-
} else if ("reflect" in interfaceType) {
|
|
627
|
-
interfaceIndex = InterfaceType.Reflect
|
|
628
|
-
} else if ("ore" in interfaceType) {
|
|
629
|
-
interfaceIndex = InterfaceType.Ore
|
|
630
|
-
} else if ("chainlink" in interfaceType) {
|
|
631
|
-
interfaceIndex = InterfaceType.Chainlink
|
|
632
|
-
} else if ("chainlinkDataStream" in interfaceType) {
|
|
633
|
-
interfaceIndex = InterfaceType.ChainlinkDataStream
|
|
634
|
-
} else if ("scope" in interfaceType) {
|
|
635
|
-
interfaceIndex = InterfaceType.Scope
|
|
636
|
-
} else if ("solsticeGlamVault" in interfaceType) {
|
|
637
|
-
interfaceIndex = InterfaceType.SolsticeGlamVault
|
|
638
|
-
} else {
|
|
639
|
-
throw new Error("Unsupported interface type")
|
|
640
|
-
}
|
|
677
|
+
const interfaceIndex = getInterfaceTypeIndex(getGenericSyMetaInitInterfaceType(account))
|
|
641
678
|
const selfAddress = new GenericSyPda(genericStandardProgramId, interfaceIndex).syMeta({
|
|
642
679
|
yieldBearingMint,
|
|
643
680
|
})
|
|
644
681
|
|
|
645
|
-
const { syRate, additionalData } = await GenericSySdk.calculateSyRate(
|
|
682
|
+
const { syRate, additionalData } = await GenericSySdk.calculateSyRate({
|
|
683
|
+
account,
|
|
684
|
+
cnx,
|
|
685
|
+
syMetaAddress: selfAddress,
|
|
686
|
+
genericStandardProgramId,
|
|
687
|
+
})
|
|
646
688
|
|
|
647
689
|
const state: GenericSyState = {
|
|
648
690
|
selfAddress,
|
|
@@ -671,7 +713,12 @@ export class GenericSySdk {
|
|
|
671
713
|
const account = await fetcher.fetchGenericSyMeta(syMetaAddress)
|
|
672
714
|
const tokenProgramBase = (await cnx.getAccountInfo(account.yieldBearingMint))?.owner
|
|
673
715
|
|
|
674
|
-
const { syRate, additionalData } = await GenericSySdk.calculateSyRate(
|
|
716
|
+
const { syRate, additionalData } = await GenericSySdk.calculateSyRate({
|
|
717
|
+
account,
|
|
718
|
+
cnx,
|
|
719
|
+
syMetaAddress,
|
|
720
|
+
genericStandardProgramId,
|
|
721
|
+
})
|
|
675
722
|
|
|
676
723
|
const state: GenericSyState = {
|
|
677
724
|
selfAddress: syMetaAddress,
|
|
@@ -686,14 +733,16 @@ export class GenericSySdk {
|
|
|
686
733
|
|
|
687
734
|
/** Reload the state of the account */
|
|
688
735
|
async reload(cnx: web3.Connection) {
|
|
689
|
-
const
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
this.program.programId,
|
|
693
|
-
this.state.account.interfaceType,
|
|
694
|
-
)
|
|
736
|
+
const genericStandardProgramId = this.syPda.programId
|
|
737
|
+
const fetcher = new ExponentFetcher({ connection: cnx, genericStandardProgramId })
|
|
738
|
+
const account = await fetcher.fetchGenericSyMeta(this.state.selfAddress)
|
|
695
739
|
this.state.account = account
|
|
696
|
-
const { syRate, additionalData } = await GenericSySdk.calculateSyRate(
|
|
740
|
+
const { syRate, additionalData } = await GenericSySdk.calculateSyRate({
|
|
741
|
+
account,
|
|
742
|
+
cnx,
|
|
743
|
+
syMetaAddress: this.state.selfAddress,
|
|
744
|
+
genericStandardProgramId,
|
|
745
|
+
})
|
|
697
746
|
this.state.syRate = syRate
|
|
698
747
|
this.state.additionalData = additionalData
|
|
699
748
|
}
|
|
@@ -702,6 +751,14 @@ export class GenericSySdk {
|
|
|
702
751
|
return this.state.account
|
|
703
752
|
}
|
|
704
753
|
|
|
754
|
+
get interfaceType() {
|
|
755
|
+
return getGenericSyMetaInterfaceType(this.account)
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
get initInterfaceType() {
|
|
759
|
+
return getGenericSyMetaInitInterfaceType(this.account)
|
|
760
|
+
}
|
|
761
|
+
|
|
705
762
|
get mintSy() {
|
|
706
763
|
return this.account.mintSy
|
|
707
764
|
}
|
|
@@ -751,10 +808,7 @@ export class GenericSySdk {
|
|
|
751
808
|
}
|
|
752
809
|
|
|
753
810
|
get fragmetricData() {
|
|
754
|
-
if (
|
|
755
|
-
!("fragmetric" in this.state.account.interfaceType) &&
|
|
756
|
-
!("fragmetricSupportedAsset" in this.state.account.interfaceType)
|
|
757
|
-
) {
|
|
811
|
+
if (!("fragmetric" in this.interfaceType) && !("fragmetricSupportedAsset" in this.interfaceType)) {
|
|
758
812
|
throw new Error("Not a fragmetric interface")
|
|
759
813
|
}
|
|
760
814
|
if (!this.state.additionalData?.fragmetricData) {
|
|
@@ -764,7 +818,7 @@ export class GenericSySdk {
|
|
|
764
818
|
}
|
|
765
819
|
|
|
766
820
|
get jupiterLendData() {
|
|
767
|
-
if (!("jupiterLend" in this.
|
|
821
|
+
if (!("jupiterLend" in this.interfaceType)) {
|
|
768
822
|
throw new Error("Not a Jupiter Lend interface")
|
|
769
823
|
}
|
|
770
824
|
if (!this.state.additionalData?.jupiterLendData) {
|
|
@@ -774,7 +828,7 @@ export class GenericSySdk {
|
|
|
774
828
|
}
|
|
775
829
|
|
|
776
830
|
get kaminoVaultData() {
|
|
777
|
-
if (!("kaminoVault" in this.
|
|
831
|
+
if (!("kaminoVault" in this.interfaceType)) {
|
|
778
832
|
throw new Error("Not a Kamino Vault interface")
|
|
779
833
|
}
|
|
780
834
|
if (!this.state.additionalData?.kaminoVaultData) {
|
|
@@ -804,11 +858,7 @@ export class GenericSySdk {
|
|
|
804
858
|
}))
|
|
805
859
|
.concat(this.emissions.map((e) => ({ pubkey: e.escrowAccount, isSigner: false, isWritable: false })))
|
|
806
860
|
|
|
807
|
-
if (
|
|
808
|
-
("fragmetric" in this.state.account.interfaceType ||
|
|
809
|
-
"fragmetricSupportedAsset" in this.state.account.interfaceType) &&
|
|
810
|
-
signer
|
|
811
|
-
) {
|
|
861
|
+
if (("fragmetric" in this.interfaceType || "fragmetricSupportedAsset" in this.interfaceType) && signer) {
|
|
812
862
|
// If skipWrap is true, return minimal accounts (skip additional interface-specific accounts)
|
|
813
863
|
if (this.config.skipWrap) {
|
|
814
864
|
return accounts
|
|
@@ -881,7 +931,7 @@ export class GenericSySdk {
|
|
|
881
931
|
)
|
|
882
932
|
}
|
|
883
933
|
|
|
884
|
-
if ("jupiterLend" in this.
|
|
934
|
+
if ("jupiterLend" in this.interfaceType) {
|
|
885
935
|
// If skipWrap is true, return minimal accounts (skip additional interface-specific accounts)
|
|
886
936
|
if (this.config.skipWrap) {
|
|
887
937
|
return accounts
|
|
@@ -1024,7 +1074,7 @@ export class GenericSySdk {
|
|
|
1024
1074
|
}
|
|
1025
1075
|
}
|
|
1026
1076
|
|
|
1027
|
-
if ("kaminoVault" in this.
|
|
1077
|
+
if ("kaminoVault" in this.interfaceType) {
|
|
1028
1078
|
// If skipWrap is true, return minimal accounts (skip additional interface-specific accounts)
|
|
1029
1079
|
if (this.config.skipWrap) {
|
|
1030
1080
|
return accounts
|
|
@@ -1155,9 +1205,33 @@ export class GenericSySdk {
|
|
|
1155
1205
|
.instruction()
|
|
1156
1206
|
}
|
|
1157
1207
|
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
if (
|
|
1208
|
+
private getFragmetricReceiptTokenAccountSetupInstruction(signer?: web3.PublicKey) {
|
|
1209
|
+
const isFragmetric = "fragmetric" in this.interfaceType || "fragmetricSupportedAsset" in this.interfaceType
|
|
1210
|
+
if (!signer || !isFragmetric || this.config.skipWrap) {
|
|
1211
|
+
return null
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
const { receiptTokenMint } = this.fragmetricData
|
|
1215
|
+
const userReceiptTokenAccount = getAssociatedTokenAddressSync(receiptTokenMint, signer, true, TOKEN_2022_PROGRAM_ID)
|
|
1216
|
+
|
|
1217
|
+
return createAssociatedTokenAccountIdempotentInstruction(
|
|
1218
|
+
signer,
|
|
1219
|
+
userReceiptTokenAccount,
|
|
1220
|
+
signer,
|
|
1221
|
+
receiptTokenMint,
|
|
1222
|
+
TOKEN_2022_PROGRAM_ID,
|
|
1223
|
+
)
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
/** Returns interface-specific setup instructions for the signer. */
|
|
1227
|
+
preInstructions(signer?: web3.PublicKey) {
|
|
1228
|
+
const ixs: web3.TransactionInstruction[] = []
|
|
1229
|
+
const receiptTokenAccountSetupIx = this.getFragmetricReceiptTokenAccountSetupInstruction(signer)
|
|
1230
|
+
if (receiptTokenAccountSetupIx) {
|
|
1231
|
+
ixs.push(receiptTokenAccountSetupIx)
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
if ("jupiterLend" in this.interfaceType) {
|
|
1161
1235
|
const jupiterLendData = this.state.additionalData?.jupiterLendData
|
|
1162
1236
|
if (!jupiterLendData) {
|
|
1163
1237
|
throw new Error("Jupiter lend data not loaded")
|
|
@@ -1197,7 +1271,7 @@ export class GenericSySdk {
|
|
|
1197
1271
|
ixs.push(refreshInstruction)
|
|
1198
1272
|
}
|
|
1199
1273
|
|
|
1200
|
-
if ("splStakePool" in this.
|
|
1274
|
+
if ("splStakePool" in this.interfaceType) {
|
|
1201
1275
|
const splStakePoolData = this.state.additionalData?.splStakePoolData
|
|
1202
1276
|
if (!splStakePoolData) {
|
|
1203
1277
|
throw new Error("SPL stake pool data not loaded")
|
|
@@ -1226,6 +1300,23 @@ export class GenericSySdk {
|
|
|
1226
1300
|
return ixs
|
|
1227
1301
|
}
|
|
1228
1302
|
|
|
1303
|
+
/** Returns signer setup and refresh instructions, including those that require live interface state. */
|
|
1304
|
+
async getPreInstructions(cnx: web3.Connection, signer?: web3.PublicKey): Promise<web3.TransactionInstruction[]> {
|
|
1305
|
+
const instructions = this.preInstructions(signer)
|
|
1306
|
+
if (!("exponentTranching" in this.interfaceType)) return instructions
|
|
1307
|
+
|
|
1308
|
+
const marketAddress = this.account.interfaceAccounts[0]
|
|
1309
|
+
if (this.account.interfaceAccounts.length !== 1 || !marketAddress) {
|
|
1310
|
+
throw new Error("Exponent Tranching interface requires exactly one market account")
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
const updateMarket = await buildExponentTranchingUpdateMarketInstruction({
|
|
1314
|
+
connection: cnx,
|
|
1315
|
+
marketAddress,
|
|
1316
|
+
})
|
|
1317
|
+
return [updateMarket, ...instructions]
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1229
1320
|
getSyState() {
|
|
1230
1321
|
return this.program.methods
|
|
1231
1322
|
.getState()
|
|
@@ -1304,6 +1395,37 @@ export class GenericSySdk {
|
|
|
1304
1395
|
})
|
|
1305
1396
|
.instruction()
|
|
1306
1397
|
}
|
|
1398
|
+
|
|
1399
|
+
ixChangeInterfaceType({
|
|
1400
|
+
signer,
|
|
1401
|
+
interfaceAccounts,
|
|
1402
|
+
interfaceType,
|
|
1403
|
+
}: {
|
|
1404
|
+
signer: web3.PublicKey
|
|
1405
|
+
interfaceAccounts: web3.PublicKey[]
|
|
1406
|
+
interfaceType: InterfaceTypeGeneric
|
|
1407
|
+
}) {
|
|
1408
|
+
return this.program.methods
|
|
1409
|
+
.changeInterfaceType(interfaceAccounts, interfaceType)
|
|
1410
|
+
.accountsStrict({
|
|
1411
|
+
adminState: this.adminState,
|
|
1412
|
+
feePayer: signer,
|
|
1413
|
+
meta: this.selfAddress,
|
|
1414
|
+
mintSy: this.mintSy,
|
|
1415
|
+
signer,
|
|
1416
|
+
systemProgram: web3.SystemProgram.programId,
|
|
1417
|
+
tokenSyEscrow: this.tokenSyEscrow,
|
|
1418
|
+
yieldBearingMint: this.vrtMint,
|
|
1419
|
+
})
|
|
1420
|
+
.remainingAccounts(
|
|
1421
|
+
interfaceAccounts.map((pubkey) => ({
|
|
1422
|
+
pubkey,
|
|
1423
|
+
isSigner: false,
|
|
1424
|
+
isWritable: true,
|
|
1425
|
+
})),
|
|
1426
|
+
)
|
|
1427
|
+
.instruction()
|
|
1428
|
+
}
|
|
1307
1429
|
}
|
|
1308
1430
|
|
|
1309
1431
|
export function initSy(
|