@exponent-labs/exponent-fetcher 0.0.3
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/CHANGELOG.md +16 -0
- package/build/exponentFetcher.d.ts +242 -0
- package/build/exponentFetcher.js +492 -0
- package/build/exponentFetcher.js.map +1 -0
- package/build/index.d.ts +1 -0
- package/build/index.js +19 -0
- package/build/index.js.map +1 -0
- package/build/utils/meteora.d.ts +54 -0
- package/build/utils/meteora.js +116 -0
- package/build/utils/meteora.js.map +1 -0
- package/package.json +35 -0
- package/src/exponentFetcher.ts +895 -0
- package/src/index.ts +2 -0
- package/src/utils/meteora.ts +126 -0
- package/tsconfig.json +34 -0
|
@@ -0,0 +1,895 @@
|
|
|
1
|
+
import { AnchorProvider, BN, Idl, Program, Wallet, web3 } from "@coral-xyz/anchor"
|
|
2
|
+
import { ExponentCore, IDL, PROGRAM_ID } from "@exponent-labs/exponent-idl"
|
|
3
|
+
import { PROGRAM_ID as KAMINO_STANDARD_PROGRAM_ID } from "@exponent-labs/kamino-sy-idl"
|
|
4
|
+
import { KaminoLendStandard } from "@exponent-labs/kamino-sy-idl"
|
|
5
|
+
import {
|
|
6
|
+
PROGRAM_ID as MARGINFI_SY_PROGRAM_ID,
|
|
7
|
+
MarginfiStandard,
|
|
8
|
+
IDL as MarginfiSyIdl,
|
|
9
|
+
} from "@exponent-labs/marginfi-sy-idl"
|
|
10
|
+
import { PROGRAM_ID as PERENA_STANDARD_PROGRAM_ID } from "@exponent-labs/perena-sy-idl"
|
|
11
|
+
import { PROGRAM_ID as JITO_RESTAKING_SY_PROGRAM_ID } from "@exponent-labs/jito-restaking-sy-idl"
|
|
12
|
+
import { IDL as KaminoSyIdl } from "@exponent-labs/kamino-lend-standard"
|
|
13
|
+
import { PreciseNumber } from "@exponent-labs/precise-number"
|
|
14
|
+
import { Reserve } from "@exponent-labs/kamino-reserve-deserializer"
|
|
15
|
+
import { JitoRestakingStandard, IDL as JitoRestakingSyIdl } from "@exponent-labs/jito-restaking-sy-idl"
|
|
16
|
+
import { IDL as PerenaSyIdl } from "@exponent-labs/perena-sy-idl"
|
|
17
|
+
import { getStakePoolAccount } from "@solana/spl-stake-pool"
|
|
18
|
+
import { IDL as FragmetricIdl } from "@exponent-labs/fragmetric-idl"
|
|
19
|
+
import { decodePoolAccount, decodeVaultAccount } from "@exponent-labs/meteora-idl"
|
|
20
|
+
import { getMint, getAccount } from "@solana/spl-token"
|
|
21
|
+
import { BorshCoder } from "@coral-xyz/anchor"
|
|
22
|
+
import {
|
|
23
|
+
AnchorizedPNum,
|
|
24
|
+
AnchorizedPNumJson,
|
|
25
|
+
MarginfiSyMeta,
|
|
26
|
+
MarginfiSyMetaRaw,
|
|
27
|
+
VaultEmission,
|
|
28
|
+
VaultEmissionJson,
|
|
29
|
+
CpiAccountIndexes,
|
|
30
|
+
JitoRestakingSyMetaAccountRaw,
|
|
31
|
+
JitoRestakingSyMetaAccount,
|
|
32
|
+
deserializeJitoRestakingSyMetaAccountRaw,
|
|
33
|
+
InterfaceType,
|
|
34
|
+
SyEmissionRaw,
|
|
35
|
+
GenericSyMetaAccount,
|
|
36
|
+
deserializeGenericSyMetaAccountRaw,
|
|
37
|
+
GenericSyMetaAccountRaw,
|
|
38
|
+
deserializePerenaSyMetaAccountRaw,
|
|
39
|
+
PerenaSyMetaAccountRaw,
|
|
40
|
+
PerenaSyMetaAccount,
|
|
41
|
+
} from "@exponent-labs/exponent-types"
|
|
42
|
+
import Decimal from "decimal.js"
|
|
43
|
+
import { PerenaStandard } from "@exponent-labs/perena-sy-idl"
|
|
44
|
+
import { MintLayout } from "@solana/spl-token"
|
|
45
|
+
import { GenericStandard } from "@exponent-labs/generic-sy-idl"
|
|
46
|
+
import { PROGRAM_ID as GENERIC_STANDARD_PROGRAM_ID, IDL as GenericStandardIdl } from "@exponent-labs/generic-sy-idl"
|
|
47
|
+
import { computeD, getAmountByShare } from "./utils/meteora"
|
|
48
|
+
|
|
49
|
+
export function serializeAnchorizedPNumFromJson(pnum: AnchorizedPNum): AnchorizedPNumJson {
|
|
50
|
+
const serializedArray = pnum[0].map((bn) => bn.toString())
|
|
51
|
+
return { 0: serializedArray }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function deserializeAnchorizedPNumFromJson(serialized: AnchorizedPNumJson): AnchorizedPNum {
|
|
55
|
+
const bnArray = serialized[0].map((str) => new BN(str))
|
|
56
|
+
return { 0: bnArray }
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export class MyWallet implements Wallet {
|
|
60
|
+
constructor(readonly payer: web3.Keypair) {
|
|
61
|
+
this.payer = payer
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async signTransaction<T extends web3.Transaction | web3.VersionedTransaction>(tx: T): Promise<T> {
|
|
65
|
+
if (tx instanceof web3.Transaction) {
|
|
66
|
+
tx.partialSign(this.payer)
|
|
67
|
+
} else {
|
|
68
|
+
tx.sign([this.payer])
|
|
69
|
+
}
|
|
70
|
+
return tx
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async signAllTransactions<T extends web3.Transaction | web3.VersionedTransaction>(txs: T[]): Promise<T[]> {
|
|
74
|
+
return txs.map((t) => {
|
|
75
|
+
if (t instanceof web3.Transaction) {
|
|
76
|
+
t.partialSign(this.payer)
|
|
77
|
+
} else if (t instanceof web3.VersionedTransaction) {
|
|
78
|
+
t.sign([this.payer])
|
|
79
|
+
}
|
|
80
|
+
return t
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
get publicKey(): web3.PublicKey {
|
|
85
|
+
return this.payer.publicKey
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export class ExponentFetcher {
|
|
90
|
+
public program: Program<ExponentCore>
|
|
91
|
+
public marginfiSyProgram: Program<MarginfiStandard>
|
|
92
|
+
public kaminoSyProgram: Program<KaminoLendStandard>
|
|
93
|
+
public jitoRestakingSyProgram: Program<JitoRestakingStandard>
|
|
94
|
+
public perenaSyProgram: Program<PerenaStandard>
|
|
95
|
+
public genericStandardProgram: Program<GenericStandard>
|
|
96
|
+
public connection: web3.Connection
|
|
97
|
+
public coreProgramId: web3.PublicKey
|
|
98
|
+
public marginfiSyProgramId: web3.PublicKey
|
|
99
|
+
public kaminoSyProgramId: web3.PublicKey
|
|
100
|
+
public jitoRestakingSyProgramId: web3.PublicKey
|
|
101
|
+
public perenaSyProgramId: web3.PublicKey
|
|
102
|
+
public genericStandardProgramId: web3.PublicKey
|
|
103
|
+
|
|
104
|
+
constructor({
|
|
105
|
+
connection,
|
|
106
|
+
coreProgramId = new web3.PublicKey(PROGRAM_ID),
|
|
107
|
+
marginfiSyProgramId = new web3.PublicKey(MARGINFI_SY_PROGRAM_ID),
|
|
108
|
+
kaminoSyProgramId = new web3.PublicKey(KAMINO_STANDARD_PROGRAM_ID),
|
|
109
|
+
jitoRestakingSyProgramId = new web3.PublicKey(JITO_RESTAKING_SY_PROGRAM_ID),
|
|
110
|
+
perenaSyProgramId = new web3.PublicKey(PERENA_STANDARD_PROGRAM_ID),
|
|
111
|
+
genericStandardProgramId = new web3.PublicKey(GENERIC_STANDARD_PROGRAM_ID),
|
|
112
|
+
}: {
|
|
113
|
+
connection: web3.Connection
|
|
114
|
+
coreProgramId?: web3.PublicKey
|
|
115
|
+
marginfiSyProgramId?: web3.PublicKey
|
|
116
|
+
kaminoSyProgramId?: web3.PublicKey
|
|
117
|
+
jitoRestakingSyProgramId?: web3.PublicKey
|
|
118
|
+
perenaSyProgramId?: web3.PublicKey
|
|
119
|
+
genericStandardProgramId?: web3.PublicKey
|
|
120
|
+
}) {
|
|
121
|
+
this.connection = connection
|
|
122
|
+
this.coreProgramId = coreProgramId
|
|
123
|
+
this.marginfiSyProgramId = marginfiSyProgramId
|
|
124
|
+
this.kaminoSyProgramId = kaminoSyProgramId
|
|
125
|
+
this.jitoRestakingSyProgramId = jitoRestakingSyProgramId
|
|
126
|
+
this.perenaSyProgramId = perenaSyProgramId
|
|
127
|
+
this.genericStandardProgramId = genericStandardProgramId
|
|
128
|
+
// Note - keypair does not matter. this is purely read-only fetching
|
|
129
|
+
const mockWallet = new MyWallet(web3.Keypair.generate())
|
|
130
|
+
const provider = new AnchorProvider(connection, mockWallet)
|
|
131
|
+
|
|
132
|
+
this.program = new Program<ExponentCore>(IDL as ExponentCore, provider)
|
|
133
|
+
this.marginfiSyProgram = new Program<MarginfiStandard>(MarginfiSyIdl as MarginfiStandard, provider)
|
|
134
|
+
this.kaminoSyProgram = new Program<KaminoLendStandard>(KaminoSyIdl as KaminoLendStandard, provider)
|
|
135
|
+
this.jitoRestakingSyProgram = new Program<JitoRestakingStandard>(
|
|
136
|
+
JitoRestakingSyIdl as JitoRestakingStandard,
|
|
137
|
+
provider,
|
|
138
|
+
)
|
|
139
|
+
this.perenaSyProgram = new Program<PerenaStandard>(PerenaSyIdl as PerenaStandard, provider)
|
|
140
|
+
this.genericStandardProgram = new Program<GenericStandard>(GenericStandardIdl, provider)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async fetchVault(address: web3.PublicKey) {
|
|
144
|
+
try {
|
|
145
|
+
const v: VaultRaw = await this.program.account.vault.fetch(address)
|
|
146
|
+
return deserializeVault(v)
|
|
147
|
+
} catch (e) {
|
|
148
|
+
console.error(`Error fetching vault ${address.toBase58()}`)
|
|
149
|
+
console.error(e)
|
|
150
|
+
throw e
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async fetchMarket(address: web3.PublicKey): Promise<MarketTwo> {
|
|
155
|
+
try {
|
|
156
|
+
const m: MarketTwoRaw = await this.program.account.marketTwo.fetch(address)
|
|
157
|
+
return deserializeMarketTwo(m)
|
|
158
|
+
} catch (e) {
|
|
159
|
+
console.error(`Error fetching market ${address.toBase58()}`)
|
|
160
|
+
console.error(e)
|
|
161
|
+
throw e
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async fetchMarginfiSyMeta(address: web3.PublicKey): Promise<MarginfiSyMeta> {
|
|
166
|
+
const x: MarginfiSyMetaRaw = await this.marginfiSyProgram.account.syMeta.fetch(address)
|
|
167
|
+
return deserializeMarginfiSyMeta(x)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
async fetchMarginfiSyPosition(address: web3.PublicKey): Promise<SyPosition> {
|
|
171
|
+
const x = await this.marginfiSyProgram.account.position.fetch(address)
|
|
172
|
+
const emissions = x.rewardIndexes.map((r) => ({
|
|
173
|
+
mint: r.mint,
|
|
174
|
+
staged: BigInt(r.claimableRewardsAmount.toString()),
|
|
175
|
+
lastSeenIndex: parseFloat(PreciseNumber.fromRaw(r.lastSeenShareIndex[0]).valueString),
|
|
176
|
+
}))
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
owner: x.owner,
|
|
180
|
+
balanceSy: BigInt(x.amount.toString()),
|
|
181
|
+
emissions,
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async fetchKaminoSyPosition(address: web3.PublicKey): Promise<SyPosition> {
|
|
186
|
+
const x = await this.kaminoSyProgram.account.position.fetch(address)
|
|
187
|
+
const emissions = x.rewardIndexes.map((r) => ({
|
|
188
|
+
mint: r.mint,
|
|
189
|
+
staged: BigInt(r.claimableRewardsAmount.toString()),
|
|
190
|
+
lastSeenIndex: parseFloat(PreciseNumber.fromRaw(r.lastSeenShareIndex[0]).valueString),
|
|
191
|
+
}))
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
owner: x.owner,
|
|
195
|
+
balanceSy: BigInt(x.amount.toString()),
|
|
196
|
+
emissions,
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
async fetchJitoRestakingSyPosition(address: web3.PublicKey): Promise<SyPosition> {
|
|
201
|
+
const x = await this.jitoRestakingSyProgram.account.position.fetch(address)
|
|
202
|
+
const emissions = x.rewardIndexes.map((r) => ({
|
|
203
|
+
mint: r.mint,
|
|
204
|
+
staged: BigInt(r.claimableRewardsAmount.toString()),
|
|
205
|
+
lastSeenIndex: parseFloat(PreciseNumber.fromRaw(r.lastSeenShareIndex[0]).valueString),
|
|
206
|
+
}))
|
|
207
|
+
|
|
208
|
+
return {
|
|
209
|
+
owner: x.owner,
|
|
210
|
+
balanceSy: BigInt(x.amount.toString()),
|
|
211
|
+
emissions,
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
async fetchPerenaSyPosition(address: web3.PublicKey): Promise<SyPosition> {
|
|
216
|
+
const x = await this.perenaSyProgram.account.position.fetch(address)
|
|
217
|
+
const emissions = x.rewardIndexes.map((r) => ({
|
|
218
|
+
mint: r.mint,
|
|
219
|
+
staged: BigInt(r.claimableRewardsAmount.toString()),
|
|
220
|
+
lastSeenIndex: parseFloat(PreciseNumber.fromRaw(r.lastSeenShareIndex[0]).valueString),
|
|
221
|
+
}))
|
|
222
|
+
return { owner: x.owner, balanceSy: BigInt(x.amount.toString()), emissions }
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
async fetchGenericSyPosition(address: web3.PublicKey): Promise<SyPosition> {
|
|
226
|
+
const x = await this.genericStandardProgram.account.position.fetch(address)
|
|
227
|
+
const emissions = x.rewardIndexes.map((r) => ({
|
|
228
|
+
mint: r.mint,
|
|
229
|
+
staged: BigInt(r.claimableRewardsAmount.toString()),
|
|
230
|
+
lastSeenIndex: parseFloat(PreciseNumber.fromRaw(r.lastSeenShareIndex[0]).valueString),
|
|
231
|
+
}))
|
|
232
|
+
return { owner: x.owner, balanceSy: BigInt(x.amount.toString()), emissions }
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async fetchKaminoSyMeta(address: web3.PublicKey): Promise<KaminoSyMeta> {
|
|
236
|
+
const x: KaminoSyMetaRaw = await this.kaminoSyProgram.account.syMeta.fetch(address)
|
|
237
|
+
return {
|
|
238
|
+
...x,
|
|
239
|
+
emissions: x.emissions.map(deserializeSyEmissionRaw),
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
async fetchLpPosition(address: web3.PublicKey): Promise<LpPosition> {
|
|
244
|
+
const x: LpPositionRaw = await this.program.account.lpPosition.fetch(address)
|
|
245
|
+
console.log("FARMs SHOULD BE HERE", x.farms)
|
|
246
|
+
return deserializeLpPosition(x)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
async fetchYtPosition(address: web3.PublicKey): Promise<YtPosition> {
|
|
250
|
+
const x: YtPositionRaw = await this.program.account.yieldTokenPosition.fetch(address)
|
|
251
|
+
return deserializeYtPosition(x)
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
async fetchJitoRestakingSyMeta(address: web3.PublicKey): Promise<JitoRestakingSyMetaAccount> {
|
|
255
|
+
const x: JitoRestakingSyMetaAccountRaw = await this.jitoRestakingSyProgram.account.syMeta.fetch(address)
|
|
256
|
+
|
|
257
|
+
return deserializeJitoRestakingSyMetaAccountRaw(x)
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async fetchPerenaSyMeta(address: web3.PublicKey): Promise<PerenaSyMetaAccount> {
|
|
261
|
+
const x: PerenaSyMetaAccountRaw = await this.perenaSyProgram.account.syMeta.fetch(address)
|
|
262
|
+
return deserializePerenaSyMetaAccountRaw(x)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
async fetchGenericSyMeta(address: web3.PublicKey): Promise<GenericSyMetaAccount> {
|
|
266
|
+
const x: GenericSyMetaAccountRaw = await this.genericStandardProgram.account.syMeta.fetch(address)
|
|
267
|
+
|
|
268
|
+
return deserializeGenericSyMetaAccountRaw(x)
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function deserializeMarketTwo(m: MarketTwoRaw): MarketTwo {
|
|
273
|
+
return {
|
|
274
|
+
ptBalance: BigInt(m.financials.ptBalance.toString()),
|
|
275
|
+
syBalance: BigInt(m.financials.syBalance.toString()),
|
|
276
|
+
lpEscrowAmount: BigInt(m.lpEscrowAmount.toString()),
|
|
277
|
+
maxLpSupply: BigInt(m.maxLpSupply.toString()),
|
|
278
|
+
rateScalarRoot: m.financials.rateScalarRoot,
|
|
279
|
+
lnFeeRateRoot: m.financials.lnFeeRateRoot,
|
|
280
|
+
lastLnImpliedRate: m.financials.lastLnImpliedRate,
|
|
281
|
+
expirationTs: m.financials.expirationTs.toNumber(),
|
|
282
|
+
addressLookupTable: m.addressLookupTable,
|
|
283
|
+
mintSy: m.mintSy,
|
|
284
|
+
mintPt: m.mintPt,
|
|
285
|
+
mintLp: m.mintLp,
|
|
286
|
+
vault: m.vault,
|
|
287
|
+
tokenLpEscrow: m.tokenLpEscrow,
|
|
288
|
+
tokenSyEscrow: m.tokenSyEscrow,
|
|
289
|
+
tokenPtEscrow: m.tokenPtEscrow,
|
|
290
|
+
tokenFeeTreasurySy: m.tokenFeeTreasurySy,
|
|
291
|
+
selfAddress: m.selfAddress,
|
|
292
|
+
syProgram: m.syProgram,
|
|
293
|
+
statusFlags: m.statusFlags,
|
|
294
|
+
cpiAccounts: m.cpiAccounts,
|
|
295
|
+
feeTreasurySyBps: m.feeTreasurySyBps,
|
|
296
|
+
isCurrentFlashSwap: m.isCurrentFlashSwap,
|
|
297
|
+
lpFarm: m.lpFarm,
|
|
298
|
+
emissions: {
|
|
299
|
+
trackers: m.emissions.trackers.map((t) => ({
|
|
300
|
+
tokenEscrow: t.tokenEscrow,
|
|
301
|
+
lpShareIndex: deserializeAnchorizedPNum(t.lpShareIndex),
|
|
302
|
+
lastSeenStaged: Number(t.lastSeenStaged),
|
|
303
|
+
})),
|
|
304
|
+
},
|
|
305
|
+
liquidityNetBalanceLimits: m.liquidityNetBalanceLimits,
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function deserializeVault(x: VaultRaw): Vault {
|
|
310
|
+
return {
|
|
311
|
+
syProgram: x.syProgram,
|
|
312
|
+
mintSy: x.mintSy,
|
|
313
|
+
mintYt: x.mintYt,
|
|
314
|
+
mintPt: x.mintPt,
|
|
315
|
+
escrowSy: x.escrowSy,
|
|
316
|
+
escrowYt: x.escrowYt,
|
|
317
|
+
startTs: x.startTs,
|
|
318
|
+
duration: x.duration,
|
|
319
|
+
authority: x.authority,
|
|
320
|
+
lastSeenSyExchangeRate: deserializeAnchorizedPNum(x.lastSeenSyExchangeRate),
|
|
321
|
+
allTimeHighSyExchangeRate: deserializeAnchorizedPNum(x.allTimeHighSyExchangeRate),
|
|
322
|
+
finalSyExchangeRate: deserializeAnchorizedPNum(x.finalSyExchangeRate),
|
|
323
|
+
addressLookupTable: x.addressLookupTable,
|
|
324
|
+
ptSupply: BigInt(x.ptSupply.toString()),
|
|
325
|
+
syForPt: BigInt(x.syForPt.toString()),
|
|
326
|
+
yieldPosition: x.yieldPosition,
|
|
327
|
+
emissions: x.emissions,
|
|
328
|
+
cpiAccounts: x.cpiAccounts,
|
|
329
|
+
treasurySy: x.treasurySy,
|
|
330
|
+
totalSyInEscrow: BigInt(x.totalSyInEscrow.toString()),
|
|
331
|
+
interestBpsFee: x.interestBpsFee,
|
|
332
|
+
status: x.status,
|
|
333
|
+
treasurySyTokenAccount: x.treasurySyTokenAccount,
|
|
334
|
+
minOpSizeStrip: BigInt(x.minOpSizeStrip.toString()),
|
|
335
|
+
minOpSizeMerge: BigInt(x.minOpSizeMerge.toString()),
|
|
336
|
+
maxPySupply: BigInt(x.maxPySupply.toString()),
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function deserializeMarginfiSyMeta(x: MarginfiSyMetaRaw): MarginfiSyMeta {
|
|
341
|
+
return {
|
|
342
|
+
...x,
|
|
343
|
+
maxSySupply: BigInt(x.maxSySupply.toString()),
|
|
344
|
+
minMintSize: BigInt(x.minMintSize.toString()),
|
|
345
|
+
minRedeemSize: BigInt(x.minRedeemSize.toString()),
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function deserializeSyEmissionRaw(x: {
|
|
350
|
+
mint: web3.PublicKey
|
|
351
|
+
index: AnchorizedPNum
|
|
352
|
+
lastSeenTotalAccruedEmissions: BN
|
|
353
|
+
totalClaimedEmissions: BN
|
|
354
|
+
tokenProgram: web3.PublicKey
|
|
355
|
+
escrowAccount: web3.PublicKey
|
|
356
|
+
treasuryEmission: BN
|
|
357
|
+
lastSeenIndex: AnchorizedPNum
|
|
358
|
+
}): SyEmissionRaw {
|
|
359
|
+
return {
|
|
360
|
+
mint: x.mint,
|
|
361
|
+
index: x.index,
|
|
362
|
+
lastSeenTotalAccruedEmissions: new BN(x.lastSeenTotalAccruedEmissions.toString()),
|
|
363
|
+
totalClaimedEmissions: new BN(x.totalClaimedEmissions.toString()),
|
|
364
|
+
tokenProgram: x.tokenProgram,
|
|
365
|
+
escrowAccount: x.escrowAccount,
|
|
366
|
+
treasuryEmission: new BN(x.treasuryEmission.toString()),
|
|
367
|
+
lastSeenIndex: x.lastSeenIndex,
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function deserializeLpPosition(x: LpPositionRaw): LpPosition {
|
|
372
|
+
return {
|
|
373
|
+
owner: x.owner,
|
|
374
|
+
market: x.market,
|
|
375
|
+
lpBalance: BigInt(x.lpBalance.toString()),
|
|
376
|
+
emissions: x.emissions.trackers.map((t) => ({
|
|
377
|
+
staged: BigInt(t.staged.toString()),
|
|
378
|
+
lastSeenIndex: parseFloat(PreciseNumber.fromRaw(t.lastSeenIndex[0]).valueString),
|
|
379
|
+
})),
|
|
380
|
+
farms: x.farms.trackers.map((t) => ({
|
|
381
|
+
staged: BigInt(t.staged.toString()),
|
|
382
|
+
lastSeenIndex: parseFloat(PreciseNumber.fromRaw(t.lastSeenIndex[0]).valueString),
|
|
383
|
+
})),
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function deserializeYtPosition(x: YtPositionRaw): YtPosition {
|
|
388
|
+
return {
|
|
389
|
+
owner: x.owner,
|
|
390
|
+
vault: x.vault,
|
|
391
|
+
ytBalance: BigInt(x.ytBalance.toString()),
|
|
392
|
+
interest: deserializeYieldTokenTracker(x.interest),
|
|
393
|
+
emissions: x.emissions.map(deserializeYieldTokenTracker),
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
function deserializeYieldTokenTracker(x: YieldTokenTrackerRaw): YieldTokenTracker {
|
|
398
|
+
return {
|
|
399
|
+
staged: BigInt(x.staged.toString()),
|
|
400
|
+
lastSeenIndex: parseFloat(PreciseNumber.fromRaw(x.lastSeenIndex[0]).valueString),
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
export async function fetchKaminoReserve(address: web3.PublicKey, connection: web3.Connection) {
|
|
405
|
+
const reserve = await Reserve.fetch(connection, address)
|
|
406
|
+
if (!reserve) {
|
|
407
|
+
throw new Error("Reserve not found")
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
return {
|
|
411
|
+
lendingMarket: reserve.lendingMarket,
|
|
412
|
+
baseMint: reserve.liquidity.mintPubkey,
|
|
413
|
+
assetShareValue: reserve.getCollateralExchangeRate(),
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
export function serializeEmission(emission: VaultEmission): VaultEmissionJson {
|
|
418
|
+
return {
|
|
419
|
+
tokenAccount: emission.tokenAccount.toString(),
|
|
420
|
+
initialIndex: serializeAnchorizedPNumFromJson(emission.initialIndex),
|
|
421
|
+
lastSeenIndex: serializeAnchorizedPNumFromJson(emission.lastSeenIndex),
|
|
422
|
+
treasuryTokenAccount: emission.treasuryTokenAccount.toString(),
|
|
423
|
+
feeBps: emission.feeBps,
|
|
424
|
+
treasuryEmission: emission.treasuryEmission.toString(),
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
export function deserializeEmission(emission: VaultEmissionJson): VaultEmission {
|
|
429
|
+
return {
|
|
430
|
+
tokenAccount: new web3.PublicKey(emission.tokenAccount),
|
|
431
|
+
initialIndex: deserializeAnchorizedPNumFromJson(emission.initialIndex),
|
|
432
|
+
lastSeenIndex: deserializeAnchorizedPNumFromJson(emission.lastSeenIndex),
|
|
433
|
+
treasuryTokenAccount: new web3.PublicKey(emission.treasuryTokenAccount),
|
|
434
|
+
feeBps: emission.feeBps,
|
|
435
|
+
treasuryEmission: new BN(emission.treasuryEmission),
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
export interface MarketTwo {
|
|
440
|
+
ptBalance: bigint
|
|
441
|
+
syBalance: bigint
|
|
442
|
+
rateScalarRoot: number
|
|
443
|
+
lnFeeRateRoot: number
|
|
444
|
+
lastLnImpliedRate: number
|
|
445
|
+
expirationTs: number
|
|
446
|
+
addressLookupTable: web3.PublicKey
|
|
447
|
+
mintSy: web3.PublicKey
|
|
448
|
+
mintPt: web3.PublicKey
|
|
449
|
+
mintLp: web3.PublicKey
|
|
450
|
+
vault: web3.PublicKey
|
|
451
|
+
tokenPtEscrow: web3.PublicKey
|
|
452
|
+
tokenSyEscrow: web3.PublicKey
|
|
453
|
+
tokenLpEscrow: web3.PublicKey
|
|
454
|
+
tokenFeeTreasurySy: web3.PublicKey
|
|
455
|
+
syProgram: web3.PublicKey
|
|
456
|
+
selfAddress: web3.PublicKey
|
|
457
|
+
statusFlags: number
|
|
458
|
+
lpEscrowAmount: bigint
|
|
459
|
+
maxLpSupply: bigint
|
|
460
|
+
cpiAccounts: CpiAccountIndexes
|
|
461
|
+
feeTreasurySyBps: number
|
|
462
|
+
isCurrentFlashSwap: boolean
|
|
463
|
+
lpFarm: LpFarm
|
|
464
|
+
emissions: {
|
|
465
|
+
trackers: {
|
|
466
|
+
tokenEscrow: web3.PublicKey
|
|
467
|
+
lpShareIndex: number
|
|
468
|
+
lastSeenStaged: number
|
|
469
|
+
}[]
|
|
470
|
+
}
|
|
471
|
+
liquidityNetBalanceLimits: LiquidityNetBalanceLimits
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
export interface Vault {
|
|
475
|
+
syProgram: web3.PublicKey
|
|
476
|
+
mintSy: web3.PublicKey
|
|
477
|
+
mintYt: web3.PublicKey
|
|
478
|
+
mintPt: web3.PublicKey
|
|
479
|
+
escrowSy: web3.PublicKey
|
|
480
|
+
startTs: number
|
|
481
|
+
duration: number
|
|
482
|
+
authority: web3.PublicKey
|
|
483
|
+
lastSeenSyExchangeRate: number
|
|
484
|
+
allTimeHighSyExchangeRate: number
|
|
485
|
+
finalSyExchangeRate: number
|
|
486
|
+
addressLookupTable: web3.PublicKey
|
|
487
|
+
totalSyInEscrow: bigint
|
|
488
|
+
ptSupply: bigint
|
|
489
|
+
syForPt: bigint
|
|
490
|
+
yieldPosition: web3.PublicKey
|
|
491
|
+
escrowYt: web3.PublicKey
|
|
492
|
+
treasurySy: BN
|
|
493
|
+
treasurySyTokenAccount: web3.PublicKey
|
|
494
|
+
interestBpsFee: number
|
|
495
|
+
emissions: VaultEmission[]
|
|
496
|
+
status: number
|
|
497
|
+
minOpSizeStrip: bigint
|
|
498
|
+
minOpSizeMerge: bigint
|
|
499
|
+
cpiAccounts: CpiAccountIndexes
|
|
500
|
+
maxPySupply: bigint
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
export interface KaminoSyMeta {
|
|
504
|
+
kaminoReserve: web3.PublicKey
|
|
505
|
+
kaminoObligation: web3.PublicKey
|
|
506
|
+
kaminoFarm: web3.PublicKey
|
|
507
|
+
kaminoUserMetadata: web3.PublicKey
|
|
508
|
+
mintSy: web3.PublicKey
|
|
509
|
+
/** Where the SY tokens get deposited */
|
|
510
|
+
tokenSyEscrow: web3.PublicKey
|
|
511
|
+
minMintSize: BN
|
|
512
|
+
minRedeemSize: BN
|
|
513
|
+
emissions: SyEmissionRaw[]
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
export interface SyPosition {
|
|
517
|
+
balanceSy: bigint
|
|
518
|
+
owner: web3.PublicKey
|
|
519
|
+
emissions: {
|
|
520
|
+
/** Last seen index for SY-to-emission exchange rate */
|
|
521
|
+
lastSeenIndex: number
|
|
522
|
+
/** mint of emission token */
|
|
523
|
+
mint: web3.PublicKey
|
|
524
|
+
/** How many emissions are staged to claim */
|
|
525
|
+
staged: bigint
|
|
526
|
+
}[]
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
export interface LpPosition {
|
|
530
|
+
owner: web3.PublicKey
|
|
531
|
+
market: web3.PublicKey
|
|
532
|
+
lpBalance: bigint
|
|
533
|
+
emissions: { staged: bigint; lastSeenIndex: number }[]
|
|
534
|
+
farms: { staged: bigint; lastSeenIndex: number }[]
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
export interface YtPosition {
|
|
538
|
+
owner: web3.PublicKey
|
|
539
|
+
vault: web3.PublicKey
|
|
540
|
+
ytBalance: bigint
|
|
541
|
+
interest: YieldTokenTracker
|
|
542
|
+
emissions: YieldTokenTracker[]
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
export interface YieldTokenTracker {
|
|
546
|
+
staged: bigint
|
|
547
|
+
lastSeenIndex: number
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
interface LpPositionRaw {
|
|
551
|
+
owner: web3.PublicKey
|
|
552
|
+
market: web3.PublicKey
|
|
553
|
+
lpBalance: BN
|
|
554
|
+
emissions: { trackers: { staged: BN; lastSeenIndex: AnchorizedPNum }[] }
|
|
555
|
+
farms: { trackers: { staged: BN; lastSeenIndex: AnchorizedPNum }[] }
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
export interface LpFarm {
|
|
559
|
+
lastSeenTimestamp: number
|
|
560
|
+
farmEmissions: FarmEmissionRaw[]
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
interface FarmEmissionRaw {
|
|
564
|
+
mint: web3.PublicKey
|
|
565
|
+
tokenRate: BN
|
|
566
|
+
expiryTimestamp: number
|
|
567
|
+
index: AnchorizedPNum
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
export interface LiquidityNetBalanceLimits {
|
|
571
|
+
windowStartTimestamp: number
|
|
572
|
+
windowStartNetBalance: BN
|
|
573
|
+
maxNetBalanceChangeNegativePercentage: number
|
|
574
|
+
maxNetBalanceChangePositivePercentage: number
|
|
575
|
+
windowDurationSeconds: number
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
export interface MarketEmissions {
|
|
579
|
+
trackers: MarketEmission[]
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
interface MarketEmission {
|
|
583
|
+
tokenEscrow: web3.PublicKey
|
|
584
|
+
lpShareIndex: AnchorizedPNum
|
|
585
|
+
lastSeenStaged: BN
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
interface MarketTwoRaw {
|
|
589
|
+
financials: MarketFinancialsRaw
|
|
590
|
+
addressLookupTable: web3.PublicKey
|
|
591
|
+
vault: web3.PublicKey
|
|
592
|
+
mintSy: web3.PublicKey
|
|
593
|
+
mintLp: web3.PublicKey
|
|
594
|
+
mintPt: web3.PublicKey
|
|
595
|
+
tokenPtEscrow: web3.PublicKey
|
|
596
|
+
tokenSyEscrow: web3.PublicKey
|
|
597
|
+
tokenLpEscrow: web3.PublicKey
|
|
598
|
+
tokenFeeTreasurySy: web3.PublicKey
|
|
599
|
+
syProgram: web3.PublicKey
|
|
600
|
+
selfAddress: web3.PublicKey
|
|
601
|
+
statusFlags: number
|
|
602
|
+
lpEscrowAmount: BN
|
|
603
|
+
maxLpSupply: BN
|
|
604
|
+
cpiAccounts: CpiAccountIndexes
|
|
605
|
+
/** Fee rate taken off of trade fees (typically around 20%) */
|
|
606
|
+
feeTreasurySyBps: number
|
|
607
|
+
isCurrentFlashSwap: boolean
|
|
608
|
+
lpFarm: LpFarm
|
|
609
|
+
liquidityNetBalanceLimits: LiquidityNetBalanceLimits
|
|
610
|
+
emissions: MarketEmissions
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
interface MarketFinancialsRaw {
|
|
614
|
+
ptBalance: BN
|
|
615
|
+
syBalance: BN
|
|
616
|
+
rateScalarRoot: number
|
|
617
|
+
lnFeeRateRoot: number
|
|
618
|
+
lastLnImpliedRate: number
|
|
619
|
+
expirationTs: BN
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
interface VaultRaw {
|
|
623
|
+
syProgram: web3.PublicKey
|
|
624
|
+
mintSy: web3.PublicKey
|
|
625
|
+
mintYt: web3.PublicKey
|
|
626
|
+
mintPt: web3.PublicKey
|
|
627
|
+
escrowSy: web3.PublicKey
|
|
628
|
+
startTs: number
|
|
629
|
+
duration: number
|
|
630
|
+
authority: web3.PublicKey
|
|
631
|
+
lastSeenSyExchangeRate: AnchorizedPNum
|
|
632
|
+
allTimeHighSyExchangeRate: AnchorizedPNum
|
|
633
|
+
finalSyExchangeRate: AnchorizedPNum
|
|
634
|
+
addressLookupTable: web3.PublicKey
|
|
635
|
+
ptSupply: BN
|
|
636
|
+
syForPt: BN
|
|
637
|
+
escrowYt: web3.PublicKey
|
|
638
|
+
totalSyInEscrow: BN
|
|
639
|
+
yieldPosition: web3.PublicKey
|
|
640
|
+
treasurySy: BN
|
|
641
|
+
treasurySyTokenAccount: web3.PublicKey
|
|
642
|
+
interestBpsFee: number
|
|
643
|
+
emissions: VaultEmission[]
|
|
644
|
+
status: number
|
|
645
|
+
minOpSizeStrip: BN
|
|
646
|
+
minOpSizeMerge: BN
|
|
647
|
+
cpiAccounts: CpiAccountIndexes
|
|
648
|
+
maxPySupply: BN
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
interface KaminoSyMetaRaw {
|
|
652
|
+
kaminoReserve: web3.PublicKey
|
|
653
|
+
kaminoObligation: web3.PublicKey
|
|
654
|
+
kaminoFarm: web3.PublicKey
|
|
655
|
+
kaminoUserMetadata: web3.PublicKey
|
|
656
|
+
mintSy: web3.PublicKey
|
|
657
|
+
minMintSize: BN
|
|
658
|
+
minRedeemSize: BN
|
|
659
|
+
/** Where the SY tokens get deposited */
|
|
660
|
+
tokenSyEscrow: web3.PublicKey
|
|
661
|
+
emissions: SyEmissionRaw[]
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
interface YtPositionRaw {
|
|
665
|
+
owner: web3.PublicKey
|
|
666
|
+
vault: web3.PublicKey
|
|
667
|
+
ytBalance: BN
|
|
668
|
+
interest: YieldTokenTrackerRaw
|
|
669
|
+
emissions: YieldTokenTrackerRaw[]
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
interface YieldTokenTrackerRaw {
|
|
673
|
+
staged: BN
|
|
674
|
+
lastSeenIndex: AnchorizedPNum
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
function deserializeAnchorizedPNum(x: AnchorizedPNum): number {
|
|
678
|
+
return parseFloat(PreciseNumber.fromRaw(x[0]).valueString)
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
/** Fetch the exchange rate of a JitoRestaking vault's VRT to JitoSOL */
|
|
682
|
+
async function fetchJitoVaultData({
|
|
683
|
+
connection,
|
|
684
|
+
vaultAddress,
|
|
685
|
+
}: {
|
|
686
|
+
connection: web3.Connection
|
|
687
|
+
vaultAddress: web3.PublicKey
|
|
688
|
+
}) {
|
|
689
|
+
const vaultAccountInfo = await connection.getAccountInfo(vaultAddress)
|
|
690
|
+
const d = vaultAccountInfo.data
|
|
691
|
+
|
|
692
|
+
// the vault has an 8 byte discriminator at the beginning
|
|
693
|
+
const discriminatorOffset = 8
|
|
694
|
+
const vrtMintOffset = 32 + discriminatorOffset
|
|
695
|
+
const vrtSupplyOffset = 96 + discriminatorOffset
|
|
696
|
+
const jitoVaultTotalDepositsOffset = 104 + discriminatorOffset
|
|
697
|
+
const mintBase = new web3.PublicKey(d.slice(vrtMintOffset, vrtMintOffset + 32))
|
|
698
|
+
|
|
699
|
+
// For Borsh, numbers are serialized in little-endian format
|
|
700
|
+
const jitoVaultTotalSharesBuffer = d.slice(vrtSupplyOffset, vrtSupplyOffset + 8)
|
|
701
|
+
const jitoVaultTotalShares = new BN(jitoVaultTotalSharesBuffer, "le")
|
|
702
|
+
|
|
703
|
+
const jitoVaultTotalDepositsBuffer = d.slice(jitoVaultTotalDepositsOffset, jitoVaultTotalDepositsOffset + 8)
|
|
704
|
+
const jitoVaultTotalDeposits = new BN(jitoVaultTotalDepositsBuffer, "le")
|
|
705
|
+
|
|
706
|
+
const jitoVaultTotalSharesD = new Decimal(jitoVaultTotalShares.toString())
|
|
707
|
+
const jitoVaultTotalDepositsD = new Decimal(jitoVaultTotalDeposits.toString())
|
|
708
|
+
|
|
709
|
+
const exchangeRate = jitoVaultTotalDepositsD.isZero()
|
|
710
|
+
? "1.0"
|
|
711
|
+
: jitoVaultTotalDepositsD.div(jitoVaultTotalSharesD).toString()
|
|
712
|
+
|
|
713
|
+
return { exchangeRate: parseFloat(exchangeRate), mintBase }
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
async function fetchJitoSolToSolExchangeRate({
|
|
717
|
+
connection,
|
|
718
|
+
interfaceType,
|
|
719
|
+
accounts,
|
|
720
|
+
}: {
|
|
721
|
+
connection: web3.Connection
|
|
722
|
+
/** Interface type of the JitoRestaking interface program that Exponent manages */
|
|
723
|
+
interfaceType: InterfaceType
|
|
724
|
+
/** "remaining accounts" */
|
|
725
|
+
accounts: web3.PublicKey[]
|
|
726
|
+
}) {
|
|
727
|
+
if (interfaceType.splStakePool) {
|
|
728
|
+
const stakePool = await getStakePoolAccount(connection, accounts[0])
|
|
729
|
+
|
|
730
|
+
return Number(stakePool.account.data.totalLamports) / Number(stakePool.account.data.poolTokenSupply)
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
throw new Error("Unsupported interface type")
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
export async function fetchPerenaStablePoolData({
|
|
737
|
+
connection,
|
|
738
|
+
perenaStablePool,
|
|
739
|
+
}: {
|
|
740
|
+
connection: web3.Connection
|
|
741
|
+
perenaStablePool: web3.PublicKey
|
|
742
|
+
}) {
|
|
743
|
+
const [lpMint, _] = web3.PublicKey.findProgramAddressSync(
|
|
744
|
+
[perenaStablePool.toBuffer(), Buffer.from("liquidity")],
|
|
745
|
+
new web3.PublicKey("NUMERUNsFCP3kuNmWZuXtm1AaQCPj9uw6Guv2Ekoi5P"),
|
|
746
|
+
)
|
|
747
|
+
|
|
748
|
+
const [accountInfo, lpMintInfo] = await connection.getMultipleAccountsInfo([perenaStablePool, lpMint])
|
|
749
|
+
const lpMintDeserialized = MintLayout.decode(lpMintInfo.data)
|
|
750
|
+
const d = accountInfo.data
|
|
751
|
+
|
|
752
|
+
const discriminatorOffset = 8
|
|
753
|
+
const invTOffset = discriminatorOffset + 32 + 32 + 32 + 32 // 4 Pubkeys before invT
|
|
754
|
+
const invTBuffer = d.slice(invTOffset, invTOffset + 8)
|
|
755
|
+
const invT = Buffer.from(invTBuffer).readBigUInt64LE(0)
|
|
756
|
+
|
|
757
|
+
const exchangeRate = new Decimal(invT.toString()).div(new Decimal(lpMintDeserialized.supply.toString())).toString()
|
|
758
|
+
|
|
759
|
+
return { lpSupply: lpMintDeserialized.supply, invT, exchangeRate, lpMint }
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
/**
|
|
763
|
+
* Fetch the exchange rate of a JitoRestaking vault
|
|
764
|
+
* @param connection
|
|
765
|
+
* @param accounts "remaining accounts"
|
|
766
|
+
* @param vaultAddress "address of the Jito Restaking vault"
|
|
767
|
+
* @param interfaceType "interface type of the Jito Restaking interface program that Exponent manages"
|
|
768
|
+
* @returns
|
|
769
|
+
*/
|
|
770
|
+
export async function fetchJitoRestaking(
|
|
771
|
+
connection: web3.Connection,
|
|
772
|
+
accounts: web3.PublicKey[],
|
|
773
|
+
interfaceType: InterfaceType,
|
|
774
|
+
vaultAddress: web3.PublicKey,
|
|
775
|
+
): Promise<{ mintBase: web3.PublicKey; exchangeRateUnderlying: number; exchangeRate: string }> {
|
|
776
|
+
const vaultDataP = fetchJitoVaultData({ connection, vaultAddress })
|
|
777
|
+
|
|
778
|
+
const solToSolExchangeRateP = fetchJitoSolToSolExchangeRate({ connection, interfaceType, accounts })
|
|
779
|
+
|
|
780
|
+
const [{ exchangeRate: e1, mintBase }, e2] = await Promise.all([vaultDataP, solToSolExchangeRateP])
|
|
781
|
+
|
|
782
|
+
// exchange rate of VRT to SOL is the product of the two exchange rates
|
|
783
|
+
const exr = e1 * e2
|
|
784
|
+
|
|
785
|
+
return {
|
|
786
|
+
mintBase,
|
|
787
|
+
exchangeRateUnderlying: e2,
|
|
788
|
+
exchangeRate: exr.toString(),
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
export async function fetchPyth(connection: web3.Connection): Promise<string> {
|
|
793
|
+
return ""
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
export async function fetchGenericSyMetaIndex({
|
|
797
|
+
connection,
|
|
798
|
+
genericSyMeta,
|
|
799
|
+
}: {
|
|
800
|
+
connection: web3.Connection
|
|
801
|
+
genericSyMeta: web3.PublicKey
|
|
802
|
+
}) {
|
|
803
|
+
const [accountInfo] = await connection.getMultipleAccountsInfo([genericSyMeta])
|
|
804
|
+
const d = accountInfo.data
|
|
805
|
+
|
|
806
|
+
// Calculate offset:
|
|
807
|
+
// 8 (discriminator) +
|
|
808
|
+
// 32 (mint_sy) +
|
|
809
|
+
// 32 (token_sy_escrow) +
|
|
810
|
+
// 8 (max_sy_supply) +
|
|
811
|
+
// 8 (min_mint_size) +
|
|
812
|
+
// 8 (min_redeem_size) +
|
|
813
|
+
// 1 (self_address_bump)
|
|
814
|
+
const indexOffset = 8 + 32 + 32 + 8 + 8 + 8 + 1
|
|
815
|
+
const indexBuffer = d.slice(indexOffset, indexOffset + 32)
|
|
816
|
+
|
|
817
|
+
// Split the 32 byte buffer into 4 u64 (8 bytes each)
|
|
818
|
+
const nums = []
|
|
819
|
+
for (let i = 0; i < 4; i++) {
|
|
820
|
+
const slice = indexBuffer.slice(i * 8, (i + 1) * 8)
|
|
821
|
+
nums.push(new BN(slice, undefined, "le")) // Added 'le' for little-endian
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
// Convert the buffer to AnchorizedPNum format with 4 BNs
|
|
825
|
+
const indexRaw = { 0: nums }
|
|
826
|
+
const index = parseFloat(PreciseNumber.fromRaw(indexRaw[0]).valueString)
|
|
827
|
+
|
|
828
|
+
return { index }
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
export async function fetchFragmetricIndex({
|
|
832
|
+
connection,
|
|
833
|
+
fragmetricFund,
|
|
834
|
+
}: {
|
|
835
|
+
connection: web3.Connection
|
|
836
|
+
fragmetricFund: web3.PublicKey
|
|
837
|
+
}) {
|
|
838
|
+
const account = await connection.getAccountInfo(fragmetricFund)
|
|
839
|
+
const coder = new BorshCoder(FragmetricIdl as Idl)
|
|
840
|
+
const data = coder.accounts.decode("FundAccount", account.data)
|
|
841
|
+
const index = Number(data.one_receipt_token_as_sol) / Number(10 ** data.receipt_token_decimals)
|
|
842
|
+
|
|
843
|
+
const receiptTokenMint = new web3.PublicKey(data.receipt_token_mint)
|
|
844
|
+
const wrappedTokenMint = new web3.PublicKey(data.wrapped_token.mint)
|
|
845
|
+
|
|
846
|
+
return { index, receiptTokenMint, wrappedTokenMint }
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
export async function fetchMeteoraUsdcUsdtIndex({
|
|
850
|
+
connection,
|
|
851
|
+
accounts,
|
|
852
|
+
onChainTime,
|
|
853
|
+
}: {
|
|
854
|
+
connection: web3.Connection
|
|
855
|
+
accounts: any
|
|
856
|
+
onChainTime: number
|
|
857
|
+
}): Promise<number> {
|
|
858
|
+
try {
|
|
859
|
+
const VIRTUAL_PRICE_PRECISION = new BN(100_000_000)
|
|
860
|
+
|
|
861
|
+
const pool = await decodePoolAccount(connection, accounts.pool)
|
|
862
|
+
|
|
863
|
+
const poolLpSupply = new BN((await getMint(connection, pool.lpMint)).supply.toString())
|
|
864
|
+
|
|
865
|
+
const vaultA = await decodeVaultAccount(connection, accounts.vaultA)
|
|
866
|
+
const vaultB = await decodeVaultAccount(connection, accounts.vaultB)
|
|
867
|
+
|
|
868
|
+
const vaultALpSupply = (await getMint(connection, vaultA.lpMint)).supply
|
|
869
|
+
const vaultBLpSupply = (await getMint(connection, vaultB.lpMint)).supply
|
|
870
|
+
|
|
871
|
+
const poolVaultALpTokenAmount = (await getAccount(connection, pool.aVaultLp)).amount
|
|
872
|
+
const poolVaultBLpTokenAmount = (await getAccount(connection, pool.bVaultLp)).amount
|
|
873
|
+
|
|
874
|
+
const tokenAAmount = getAmountByShare(
|
|
875
|
+
new BN(poolVaultALpTokenAmount.toString()),
|
|
876
|
+
new BN(vaultALpSupply.toString()),
|
|
877
|
+
vaultA,
|
|
878
|
+
onChainTime,
|
|
879
|
+
)
|
|
880
|
+
const tokenBAmount = getAmountByShare(
|
|
881
|
+
new BN(poolVaultBLpTokenAmount.toString()),
|
|
882
|
+
new BN(vaultBLpSupply.toString()),
|
|
883
|
+
vaultB,
|
|
884
|
+
onChainTime,
|
|
885
|
+
)
|
|
886
|
+
|
|
887
|
+
const d = computeD(pool.curveType, tokenAAmount, tokenBAmount)
|
|
888
|
+
const virtualPriceBigNum = poolLpSupply.isZero() ? new BN(0) : d.mul(VIRTUAL_PRICE_PRECISION).div(poolLpSupply)
|
|
889
|
+
const virtualPrice = new Decimal(virtualPriceBigNum.toString()).div(VIRTUAL_PRICE_PRECISION.toString()).toNumber()
|
|
890
|
+
|
|
891
|
+
return virtualPrice
|
|
892
|
+
} catch (error) {
|
|
893
|
+
throw error
|
|
894
|
+
}
|
|
895
|
+
}
|