@glamsystems/glam-sdk 0.1.29 → 0.1.30
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/index.cjs.js +174 -140
- package/index.esm.js +174 -140
- package/package.json +1 -1
- package/src/client/base.d.ts +1 -1
- package/src/client/price.d.ts +13 -12
- package/target/idl/glam_protocol.json +22 -23
- package/target/types/glam_protocol.d.ts +22 -23
- package/target/types/glam_protocol.ts +22 -23
package/index.cjs.js
CHANGED
|
@@ -34,7 +34,7 @@ var borsh__namespace = /*#__PURE__*/_interopNamespaceDefault(borsh);
|
|
|
34
34
|
var address = "GLAMbTqav9N9witRjswJ8enwp9vv5G8bsSJ2kPJ4rcyc";
|
|
35
35
|
var metadata = {
|
|
36
36
|
name: "glam_protocol",
|
|
37
|
-
version: "0.4.
|
|
37
|
+
version: "0.4.35",
|
|
38
38
|
spec: "0.1.0",
|
|
39
39
|
description: "Glam Protocol"
|
|
40
40
|
};
|
|
@@ -6900,7 +6900,9 @@ var instructions = [
|
|
|
6900
6900
|
docs: [
|
|
6901
6901
|
"Extra accounts for pricing N vault depositors:",
|
|
6902
6902
|
"- (vault_depositor, drift_vault, drift_user) x N",
|
|
6903
|
-
"-
|
|
6903
|
+
"- spot_market used by drift users of vaults (no specific order)",
|
|
6904
|
+
"- perp markets used by drift users of vaults (no specific order)",
|
|
6905
|
+
"- oracles of spot markets and perp markets (no specific order)"
|
|
6904
6906
|
],
|
|
6905
6907
|
discriminator: [
|
|
6906
6908
|
234,
|
|
@@ -7021,6 +7023,14 @@ var instructions = [
|
|
|
7021
7023
|
{
|
|
7022
7024
|
name: "num_vault_depositors",
|
|
7023
7025
|
type: "u8"
|
|
7026
|
+
},
|
|
7027
|
+
{
|
|
7028
|
+
name: "num_spot_markets",
|
|
7029
|
+
type: "u8"
|
|
7030
|
+
},
|
|
7031
|
+
{
|
|
7032
|
+
name: "num_perp_markets",
|
|
7033
|
+
type: "u8"
|
|
7024
7034
|
}
|
|
7025
7035
|
]
|
|
7026
7036
|
},
|
|
@@ -7167,9 +7177,14 @@ var instructions = [
|
|
|
7167
7177
|
{
|
|
7168
7178
|
name: "price_kamino_vault_shares",
|
|
7169
7179
|
docs: [
|
|
7180
|
+
"Price Kamino vault shares.",
|
|
7181
|
+
"- `num_vaults` Number of kamino vaults to price.",
|
|
7182
|
+
"",
|
|
7170
7183
|
"Extra accounts for pricing N kamino vault shares:",
|
|
7171
7184
|
"- (kvault_share_ata, kvault_share_mint, kvault_state, kvault_deposit_token_oracle) x N",
|
|
7172
|
-
"-
|
|
7185
|
+
"- reserve x M",
|
|
7186
|
+
"- M = number of reserves used by all kvaults' allocations",
|
|
7187
|
+
"- reserve pubkeys must follow the same order of reserves used by each allocation"
|
|
7173
7188
|
],
|
|
7174
7189
|
discriminator: [
|
|
7175
7190
|
112,
|
|
@@ -7212,10 +7227,6 @@ var instructions = [
|
|
|
7212
7227
|
writable: true,
|
|
7213
7228
|
signer: true
|
|
7214
7229
|
},
|
|
7215
|
-
{
|
|
7216
|
-
name: "kamino_lending_program",
|
|
7217
|
-
address: "KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD"
|
|
7218
|
-
},
|
|
7219
7230
|
{
|
|
7220
7231
|
name: "sol_oracle"
|
|
7221
7232
|
},
|
|
@@ -7280,22 +7291,6 @@ var instructions = [
|
|
|
7280
7291
|
]
|
|
7281
7292
|
}
|
|
7282
7293
|
}
|
|
7283
|
-
},
|
|
7284
|
-
{
|
|
7285
|
-
name: "pyth_oracle",
|
|
7286
|
-
optional: true
|
|
7287
|
-
},
|
|
7288
|
-
{
|
|
7289
|
-
name: "switchboard_price_oracle",
|
|
7290
|
-
optional: true
|
|
7291
|
-
},
|
|
7292
|
-
{
|
|
7293
|
-
name: "switchboard_twap_oracle",
|
|
7294
|
-
optional: true
|
|
7295
|
-
},
|
|
7296
|
-
{
|
|
7297
|
-
name: "scope_prices",
|
|
7298
|
-
optional: true
|
|
7299
7294
|
}
|
|
7300
7295
|
],
|
|
7301
7296
|
args: [
|
|
@@ -9608,6 +9603,10 @@ var instructions = [
|
|
|
9608
9603
|
{
|
|
9609
9604
|
name: "stake_history",
|
|
9610
9605
|
address: "SysvarStakeHistory1111111111111111111111111"
|
|
9606
|
+
},
|
|
9607
|
+
{
|
|
9608
|
+
name: "system_program",
|
|
9609
|
+
address: "11111111111111111111111111111111"
|
|
9611
9610
|
}
|
|
9612
9611
|
],
|
|
9613
9612
|
args: [
|
|
@@ -15604,12 +15603,12 @@ class BaseClient {
|
|
|
15604
15603
|
const { t: lookupTables } = data;
|
|
15605
15604
|
const pubkeys = Object.keys(lookupTables);
|
|
15606
15605
|
if (pubkeys.length > 0) {
|
|
15607
|
-
return await this.
|
|
15606
|
+
return await this.fetchAddressLookupTableAccounts(pubkeys);
|
|
15608
15607
|
}
|
|
15609
15608
|
}
|
|
15610
15609
|
const tablePubkey = STATES_LOOKUP_TABLES_MAP.get(this.statePda.toBase58());
|
|
15611
15610
|
if (tablePubkey) {
|
|
15612
|
-
return await this.
|
|
15611
|
+
return await this.fetchAddressLookupTableAccounts([
|
|
15613
15612
|
tablePubkey
|
|
15614
15613
|
]);
|
|
15615
15614
|
}
|
|
@@ -15660,12 +15659,12 @@ class BaseClient {
|
|
|
15660
15659
|
}
|
|
15661
15660
|
const lookupTableAccounts = [];
|
|
15662
15661
|
if (lookupTables.every((t)=>t instanceof web3_js.AddressLookupTableAccount)) {
|
|
15663
|
-
const accounts = await this.
|
|
15662
|
+
const accounts = await this.fetchAddressLookupTableAccounts([
|
|
15664
15663
|
...LOOKUP_TABLES
|
|
15665
15664
|
]);
|
|
15666
15665
|
lookupTableAccounts.push(...lookupTables, ...accounts);
|
|
15667
15666
|
} else {
|
|
15668
|
-
const accounts = await this.
|
|
15667
|
+
const accounts = await this.fetchAddressLookupTableAccounts([
|
|
15669
15668
|
...lookupTables,
|
|
15670
15669
|
...LOOKUP_TABLES
|
|
15671
15670
|
]);
|
|
@@ -15749,7 +15748,7 @@ class BaseClient {
|
|
|
15749
15748
|
*
|
|
15750
15749
|
* @param pubkeys Array of lookup table public keys.
|
|
15751
15750
|
* @returns
|
|
15752
|
-
*/ async
|
|
15751
|
+
*/ async fetchAddressLookupTableAccounts(pubkeys) {
|
|
15753
15752
|
if (!pubkeys) {
|
|
15754
15753
|
throw new Error("addressLookupTableAddresses is undefined");
|
|
15755
15754
|
}
|
|
@@ -20824,9 +20823,7 @@ class KaminoVaultsClient {
|
|
|
20824
20823
|
return vaultState;
|
|
20825
20824
|
}
|
|
20826
20825
|
async composeRemainingAccounts(allocationStrategies, pricingMode = false) {
|
|
20827
|
-
|
|
20828
|
-
const reservesSet = new Set(allocationStrategies.map((strategy)=>strategy.reserve.toBase58()));
|
|
20829
|
-
const reserves = Array.from(reservesSet).map((p)=>new web3_js.PublicKey(p));
|
|
20826
|
+
const reserves = allocationStrategies.map((strategy)=>strategy.reserve);
|
|
20830
20827
|
const parsedReserves = await this.kaminoLending.fetchAndParseReserves(reserves);
|
|
20831
20828
|
const reserveMetas = reserves.map((pubkey)=>({
|
|
20832
20829
|
pubkey,
|
|
@@ -21439,26 +21436,41 @@ class PriceClient {
|
|
|
21439
21436
|
oracles[i]
|
|
21440
21437
|
].map((pubkey)=>{
|
|
21441
21438
|
remainingAccounts.push({
|
|
21442
|
-
pubkey,
|
|
21439
|
+
pubkey: pubkey,
|
|
21443
21440
|
isSigner: false,
|
|
21444
21441
|
isWritable: false
|
|
21445
21442
|
});
|
|
21446
21443
|
});
|
|
21447
21444
|
}
|
|
21448
|
-
// markets and reserves
|
|
21449
21445
|
const marketsAndReserves = (await Promise.all(kvaultStates.map((kvault)=>{
|
|
21450
21446
|
return this.kvaults.composeRemainingAccounts(kvault.vaultAllocationStrategy.filter((alloc)=>!alloc.reserve.equals(web3_js.PublicKey.default)), true);
|
|
21451
21447
|
}))).flat();
|
|
21452
|
-
|
|
21448
|
+
const processed = new Set();
|
|
21449
|
+
const preInstructions = [];
|
|
21450
|
+
const chunkSize = 2;
|
|
21451
|
+
for(let i = 0; i < marketsAndReserves.length; i += chunkSize){
|
|
21452
|
+
const chunk = marketsAndReserves.slice(i, i + chunkSize);
|
|
21453
|
+
const market = chunk[0].pubkey;
|
|
21454
|
+
const reserve = chunk[1].pubkey;
|
|
21455
|
+
// reserve should always be added to remaining accounts
|
|
21456
|
+
remainingAccounts.push(chunk[1]);
|
|
21457
|
+
// each reserve should only be refreshed once
|
|
21458
|
+
if (!processed.has(reserve.toBase58())) {
|
|
21459
|
+
const ix = this.klend.refreshReserveIxs(market, [
|
|
21460
|
+
reserve
|
|
21461
|
+
]);
|
|
21462
|
+
preInstructions.push(...ix);
|
|
21463
|
+
processed.add(reserve.toBase58());
|
|
21464
|
+
}
|
|
21465
|
+
}
|
|
21453
21466
|
const priceIx = await this.base.program.methods.priceKaminoVaultShares(priceDenom, shareAtas.length).accounts({
|
|
21454
21467
|
glamState: this.base.statePda,
|
|
21455
|
-
solOracle: SOL_ORACLE
|
|
21456
|
-
pythOracle: null,
|
|
21457
|
-
switchboardPriceOracle: null,
|
|
21458
|
-
switchboardTwapOracle: null,
|
|
21459
|
-
scopePrices: KAMINO_SCOPE_PRICES
|
|
21468
|
+
solOracle: SOL_ORACLE
|
|
21460
21469
|
}).remainingAccounts(remainingAccounts).instruction();
|
|
21461
|
-
return
|
|
21470
|
+
return [
|
|
21471
|
+
...preInstructions,
|
|
21472
|
+
priceIx
|
|
21473
|
+
];
|
|
21462
21474
|
}
|
|
21463
21475
|
/**
|
|
21464
21476
|
* Returns an instruction that prices all Drift users (aka sub-accounts) controlled by the GLAM vault.
|
|
@@ -21526,43 +21538,8 @@ class PriceClient {
|
|
|
21526
21538
|
if (parsedVaultDepositors.length === 0) {
|
|
21527
21539
|
return null;
|
|
21528
21540
|
}
|
|
21529
|
-
|
|
21530
|
-
|
|
21531
|
-
// - drift vault
|
|
21532
|
-
// - drift user of the vault
|
|
21533
|
-
// - oracles
|
|
21534
|
-
// - spot & perp markets
|
|
21535
|
-
// There might be overlaps between markets and oracles so we use a set to avoid duplicates
|
|
21536
|
-
const remainingAccounts = [];
|
|
21537
|
-
const marketsAndOracles = new Set();
|
|
21538
|
-
for (const depositor of parsedVaultDepositors){
|
|
21539
|
-
const { user: driftUser } = await this.dvaults.parseDriftVault(depositor.driftVault);
|
|
21540
|
-
remainingAccounts.push({
|
|
21541
|
-
pubkey: depositor.address,
|
|
21542
|
-
isSigner: false,
|
|
21543
|
-
isWritable: false
|
|
21544
|
-
});
|
|
21545
|
-
remainingAccounts.push({
|
|
21546
|
-
pubkey: depositor.driftVault,
|
|
21547
|
-
isSigner: false,
|
|
21548
|
-
isWritable: false
|
|
21549
|
-
});
|
|
21550
|
-
remainingAccounts.push({
|
|
21551
|
-
pubkey: driftUser,
|
|
21552
|
-
isSigner: false,
|
|
21553
|
-
isWritable: false
|
|
21554
|
-
});
|
|
21555
|
-
const markets_and_oracles = (await this.dvaults.composeRemainingAccounts(driftUser)).map((a)=>a.pubkey.toBase58());
|
|
21556
|
-
for (const k of markets_and_oracles){
|
|
21557
|
-
marketsAndOracles.add(k);
|
|
21558
|
-
}
|
|
21559
|
-
}
|
|
21560
|
-
Array.from(marketsAndOracles).forEach((k)=>remainingAccounts.push({
|
|
21561
|
-
pubkey: new web3_js.PublicKey(k),
|
|
21562
|
-
isSigner: false,
|
|
21563
|
-
isWritable: false
|
|
21564
|
-
}));
|
|
21565
|
-
const priceIx = await this.base.program.methods.priceDriftVaultDepositors(priceDenom, parsedVaultDepositors.length).accounts({
|
|
21541
|
+
const { remainingAccounts, numSpotMarkets, numPerpMarkets } = await this.remainingAccountsForPricingDriftVaultDepositors(parsedVaultDepositors);
|
|
21542
|
+
const priceIx = await this.base.program.methods.priceDriftVaultDepositors(priceDenom, parsedVaultDepositors.length, numSpotMarkets, numPerpMarkets).accounts({
|
|
21566
21543
|
glamState: this.base.statePda,
|
|
21567
21544
|
solOracle: SOL_ORACLE
|
|
21568
21545
|
}).remainingAccounts(remainingAccounts).instruction();
|
|
@@ -21629,12 +21606,11 @@ class PriceClient {
|
|
|
21629
21606
|
}
|
|
21630
21607
|
const integrations = (stateModel.integrations || []).map((i)=>Object.keys(i)[0]);
|
|
21631
21608
|
const integrationsToPricingFns = {
|
|
21632
|
-
drift: this.priceDriftUsersIx.bind(this),
|
|
21633
|
-
kaminoLending: this.priceKaminoObligationsIx.bind(this),
|
|
21634
|
-
nativeStaking: this.priceStakesIx.bind(this),
|
|
21635
|
-
meteoraDlmm: this.priceMeteoraPositionsIx.bind(this),
|
|
21636
|
-
driftVaults: this.priceDriftVaultDepositorsIx.bind(this)
|
|
21637
|
-
kaminoVaults: this.priceKaminoVaultSharesIx.bind(this)
|
|
21609
|
+
// drift: this.priceDriftUsersIx.bind(this),
|
|
21610
|
+
// kaminoLending: this.priceKaminoObligationsIx.bind(this),
|
|
21611
|
+
// nativeStaking: this.priceStakesIx.bind(this),
|
|
21612
|
+
// meteoraDlmm: this.priceMeteoraPositionsIx.bind(this),
|
|
21613
|
+
driftVaults: this.priceDriftVaultDepositorsIx.bind(this)
|
|
21638
21614
|
};
|
|
21639
21615
|
const pricingFns = integrations.map((integration)=>integrationsToPricingFns[integration]).filter(Boolean);
|
|
21640
21616
|
const pricingIxs = [
|
|
@@ -21642,72 +21618,130 @@ class PriceClient {
|
|
|
21642
21618
|
];
|
|
21643
21619
|
for (const fn of pricingFns){
|
|
21644
21620
|
const ix = await fn(priceDenom);
|
|
21645
|
-
|
|
21621
|
+
if (Array.isArray(ix)) {
|
|
21622
|
+
pricingIxs.push(...ix);
|
|
21623
|
+
} else {
|
|
21624
|
+
pricingIxs.push(ix);
|
|
21625
|
+
}
|
|
21646
21626
|
}
|
|
21647
21627
|
return pricingIxs.filter(Boolean);
|
|
21648
21628
|
}
|
|
21629
|
+
async remainingAccountsForPricingDriftVaultDepositors(parsedVaultDepositors) {
|
|
21630
|
+
// Extra accounts for pricing N vault depositors:
|
|
21631
|
+
// - (vault_depositor, drift_vault, drift_user) x N
|
|
21632
|
+
// - spot_market used by drift users of vaults (no specific order)
|
|
21633
|
+
// - perp markets used by drift users of vaults (no specific order)
|
|
21634
|
+
// - oracles of spot markets and perp markets (no specific order)
|
|
21635
|
+
const remainingAccounts = [];
|
|
21636
|
+
const spotMarketsSet = new Set();
|
|
21637
|
+
const perpMarketsSet = new Set();
|
|
21638
|
+
const oraclesSet = new Set();
|
|
21639
|
+
for (const { address: depositor, driftVault } of parsedVaultDepositors){
|
|
21640
|
+
const { user } = await this.dvaults.parseDriftVault(driftVault); // get drift user used by the vault
|
|
21641
|
+
[
|
|
21642
|
+
depositor,
|
|
21643
|
+
driftVault,
|
|
21644
|
+
user
|
|
21645
|
+
].forEach((k)=>remainingAccounts.push({
|
|
21646
|
+
pubkey: k,
|
|
21647
|
+
isSigner: false,
|
|
21648
|
+
isWritable: false
|
|
21649
|
+
}));
|
|
21650
|
+
const { spotPositions, perpPositions } = await this.dvaults.fetchUserPositions(user);
|
|
21651
|
+
const spotMarketIndexes = spotPositions.map((p)=>p.marketIndex);
|
|
21652
|
+
const perpMarketIndexes = perpPositions.map((p)=>p.marketIndex);
|
|
21653
|
+
// If there are perp positions, add spot market 0 as it's used as quote market for perp
|
|
21654
|
+
if (perpMarketIndexes.length > 0 && !spotMarketIndexes.includes(0)) {
|
|
21655
|
+
spotMarketIndexes.push(0);
|
|
21656
|
+
}
|
|
21657
|
+
const spotMarkets = await this.drift.fetchAndParseSpotMarkets(spotMarketIndexes);
|
|
21658
|
+
const perpMarkets = await this.drift.fetchAndParsePerpMarkets(perpMarketIndexes);
|
|
21659
|
+
spotMarkets.forEach((m)=>{
|
|
21660
|
+
oraclesSet.add(m.oracle.toBase58());
|
|
21661
|
+
spotMarketsSet.add(m.marketPda.toBase58());
|
|
21662
|
+
});
|
|
21663
|
+
perpMarkets.forEach((m)=>{
|
|
21664
|
+
oraclesSet.add(m.oracle.toBase58());
|
|
21665
|
+
perpMarketsSet.add(m.marketPda.toBase58());
|
|
21666
|
+
});
|
|
21667
|
+
}
|
|
21668
|
+
[
|
|
21669
|
+
...spotMarketsSet,
|
|
21670
|
+
...perpMarketsSet,
|
|
21671
|
+
...oraclesSet
|
|
21672
|
+
].forEach((k)=>remainingAccounts.push({
|
|
21673
|
+
pubkey: new web3_js.PublicKey(k),
|
|
21674
|
+
isSigner: false,
|
|
21675
|
+
isWritable: false
|
|
21676
|
+
}));
|
|
21677
|
+
return {
|
|
21678
|
+
remainingAccounts,
|
|
21679
|
+
numSpotMarkets: spotMarketsSet.size,
|
|
21680
|
+
numPerpMarkets: perpMarketsSet.size
|
|
21681
|
+
};
|
|
21682
|
+
}
|
|
21683
|
+
async remainingAccountsForPricingMeteora() {
|
|
21684
|
+
const positions = await fetchMeteoraPositions(this.base.provider.connection, this.base.vaultPda);
|
|
21685
|
+
let chunks = await Promise.all(positions.map(async (pubkey)=>{
|
|
21686
|
+
const { lbPair, binArrayLower, binArrayUpper } = await parseMeteoraPosition(this.base.provider.connection, pubkey);
|
|
21687
|
+
return [
|
|
21688
|
+
pubkey,
|
|
21689
|
+
lbPair,
|
|
21690
|
+
binArrayLower,
|
|
21691
|
+
binArrayUpper,
|
|
21692
|
+
SOL_ORACLE,
|
|
21693
|
+
USDC_ORACLE
|
|
21694
|
+
].map((k)=>({
|
|
21695
|
+
pubkey: k,
|
|
21696
|
+
isSigner: false,
|
|
21697
|
+
isWritable: false
|
|
21698
|
+
}));
|
|
21699
|
+
}));
|
|
21700
|
+
return chunks.flat();
|
|
21701
|
+
}
|
|
21702
|
+
async remainingAccountsForPricingVaultAssets(baseAssetOnly = false) {
|
|
21703
|
+
const stateModel = await this.base.fetchStateModel();
|
|
21704
|
+
if (baseAssetOnly) {
|
|
21705
|
+
if (!stateModel.baseAsset) {
|
|
21706
|
+
throw new Error("Base asset not configured for the vault");
|
|
21707
|
+
}
|
|
21708
|
+
// FIXME: support token 2022 base asset
|
|
21709
|
+
const ata = this.base.getVaultAta(stateModel.baseAsset);
|
|
21710
|
+
// Set oracle to default pubkey (aka system program) to indicate oracle isn't needed
|
|
21711
|
+
return [
|
|
21712
|
+
ata,
|
|
21713
|
+
stateModel.baseAsset,
|
|
21714
|
+
web3_js.PublicKey.default
|
|
21715
|
+
].map((k)=>({
|
|
21716
|
+
pubkey: k,
|
|
21717
|
+
isSigner: false,
|
|
21718
|
+
isWritable: false
|
|
21719
|
+
}));
|
|
21720
|
+
}
|
|
21721
|
+
const assetsForPricing = (stateModel.borrowableAssets || []).concat(stateModel.assets || []);
|
|
21722
|
+
return assetsForPricing.map((mint)=>{
|
|
21723
|
+
const assetMeta = ASSETS_MAINNET.get(mint.toBase58());
|
|
21724
|
+
if (!assetMeta) {
|
|
21725
|
+
throw new Error(`Asset meta not found for ${mint}`);
|
|
21726
|
+
}
|
|
21727
|
+
const ata = this.base.getVaultAta(mint, assetMeta?.programId);
|
|
21728
|
+
return [
|
|
21729
|
+
ata,
|
|
21730
|
+
mint,
|
|
21731
|
+
assetMeta?.oracle
|
|
21732
|
+
];
|
|
21733
|
+
}).flat().map((a)=>({
|
|
21734
|
+
pubkey: a,
|
|
21735
|
+
isSigner: false,
|
|
21736
|
+
isWritable: false
|
|
21737
|
+
}));
|
|
21738
|
+
}
|
|
21649
21739
|
constructor(base, klend, kvaults, drift, dvaults){
|
|
21650
21740
|
this.base = base;
|
|
21651
21741
|
this.klend = klend;
|
|
21652
21742
|
this.kvaults = kvaults;
|
|
21653
21743
|
this.drift = drift;
|
|
21654
21744
|
this.dvaults = dvaults;
|
|
21655
|
-
this.remainingAccountsForPricingMeteora = async ()=>{
|
|
21656
|
-
const positions = await fetchMeteoraPositions(this.base.provider.connection, this.base.vaultPda);
|
|
21657
|
-
let chunks = await Promise.all(positions.map(async (pubkey)=>{
|
|
21658
|
-
const { lbPair, binArrayLower, binArrayUpper } = await parseMeteoraPosition(this.base.provider.connection, pubkey);
|
|
21659
|
-
return [
|
|
21660
|
-
pubkey,
|
|
21661
|
-
lbPair,
|
|
21662
|
-
binArrayLower,
|
|
21663
|
-
binArrayUpper,
|
|
21664
|
-
SOL_ORACLE,
|
|
21665
|
-
USDC_ORACLE
|
|
21666
|
-
].map((k)=>({
|
|
21667
|
-
pubkey: k,
|
|
21668
|
-
isSigner: false,
|
|
21669
|
-
isWritable: false
|
|
21670
|
-
}));
|
|
21671
|
-
}));
|
|
21672
|
-
return chunks.flat();
|
|
21673
|
-
};
|
|
21674
|
-
this.remainingAccountsForPricingVaultAssets = async (baseAssetOnly = false)=>{
|
|
21675
|
-
const stateModel = await this.base.fetchStateModel();
|
|
21676
|
-
if (baseAssetOnly) {
|
|
21677
|
-
if (!stateModel.baseAsset) {
|
|
21678
|
-
throw new Error("Base asset not configured for the vault");
|
|
21679
|
-
}
|
|
21680
|
-
// FIXME: support token 2022 base asset
|
|
21681
|
-
const ata = this.base.getVaultAta(stateModel.baseAsset);
|
|
21682
|
-
// Set oracle to default pubkey (aka system program) to indicate oracle isn't needed
|
|
21683
|
-
return [
|
|
21684
|
-
ata,
|
|
21685
|
-
stateModel.baseAsset,
|
|
21686
|
-
web3_js.PublicKey.default
|
|
21687
|
-
].map((k)=>({
|
|
21688
|
-
pubkey: k,
|
|
21689
|
-
isSigner: false,
|
|
21690
|
-
isWritable: false
|
|
21691
|
-
}));
|
|
21692
|
-
}
|
|
21693
|
-
const assetsForPricing = (stateModel.borrowableAssets || []).concat(stateModel.assets || []);
|
|
21694
|
-
return assetsForPricing.map((mint)=>{
|
|
21695
|
-
const assetMeta = ASSETS_MAINNET.get(mint.toBase58());
|
|
21696
|
-
if (!assetMeta) {
|
|
21697
|
-
throw new Error(`Asset meta not found for ${mint}`);
|
|
21698
|
-
}
|
|
21699
|
-
const ata = this.base.getVaultAta(mint, assetMeta?.programId);
|
|
21700
|
-
return [
|
|
21701
|
-
ata,
|
|
21702
|
-
mint,
|
|
21703
|
-
assetMeta?.oracle
|
|
21704
|
-
];
|
|
21705
|
-
}).flat().map((a)=>({
|
|
21706
|
-
pubkey: a,
|
|
21707
|
-
isSigner: false,
|
|
21708
|
-
isWritable: false
|
|
21709
|
-
}));
|
|
21710
|
-
};
|
|
21711
21745
|
}
|
|
21712
21746
|
}
|
|
21713
21747
|
|
package/index.esm.js
CHANGED
|
@@ -14,7 +14,7 @@ import { getStakePoolAccount } from '@solana/spl-stake-pool';
|
|
|
14
14
|
var address = "GLAMbTqav9N9witRjswJ8enwp9vv5G8bsSJ2kPJ4rcyc";
|
|
15
15
|
var metadata = {
|
|
16
16
|
name: "glam_protocol",
|
|
17
|
-
version: "0.4.
|
|
17
|
+
version: "0.4.35",
|
|
18
18
|
spec: "0.1.0",
|
|
19
19
|
description: "Glam Protocol"
|
|
20
20
|
};
|
|
@@ -6880,7 +6880,9 @@ var instructions = [
|
|
|
6880
6880
|
docs: [
|
|
6881
6881
|
"Extra accounts for pricing N vault depositors:",
|
|
6882
6882
|
"- (vault_depositor, drift_vault, drift_user) x N",
|
|
6883
|
-
"-
|
|
6883
|
+
"- spot_market used by drift users of vaults (no specific order)",
|
|
6884
|
+
"- perp markets used by drift users of vaults (no specific order)",
|
|
6885
|
+
"- oracles of spot markets and perp markets (no specific order)"
|
|
6884
6886
|
],
|
|
6885
6887
|
discriminator: [
|
|
6886
6888
|
234,
|
|
@@ -7001,6 +7003,14 @@ var instructions = [
|
|
|
7001
7003
|
{
|
|
7002
7004
|
name: "num_vault_depositors",
|
|
7003
7005
|
type: "u8"
|
|
7006
|
+
},
|
|
7007
|
+
{
|
|
7008
|
+
name: "num_spot_markets",
|
|
7009
|
+
type: "u8"
|
|
7010
|
+
},
|
|
7011
|
+
{
|
|
7012
|
+
name: "num_perp_markets",
|
|
7013
|
+
type: "u8"
|
|
7004
7014
|
}
|
|
7005
7015
|
]
|
|
7006
7016
|
},
|
|
@@ -7147,9 +7157,14 @@ var instructions = [
|
|
|
7147
7157
|
{
|
|
7148
7158
|
name: "price_kamino_vault_shares",
|
|
7149
7159
|
docs: [
|
|
7160
|
+
"Price Kamino vault shares.",
|
|
7161
|
+
"- `num_vaults` Number of kamino vaults to price.",
|
|
7162
|
+
"",
|
|
7150
7163
|
"Extra accounts for pricing N kamino vault shares:",
|
|
7151
7164
|
"- (kvault_share_ata, kvault_share_mint, kvault_state, kvault_deposit_token_oracle) x N",
|
|
7152
|
-
"-
|
|
7165
|
+
"- reserve x M",
|
|
7166
|
+
"- M = number of reserves used by all kvaults' allocations",
|
|
7167
|
+
"- reserve pubkeys must follow the same order of reserves used by each allocation"
|
|
7153
7168
|
],
|
|
7154
7169
|
discriminator: [
|
|
7155
7170
|
112,
|
|
@@ -7192,10 +7207,6 @@ var instructions = [
|
|
|
7192
7207
|
writable: true,
|
|
7193
7208
|
signer: true
|
|
7194
7209
|
},
|
|
7195
|
-
{
|
|
7196
|
-
name: "kamino_lending_program",
|
|
7197
|
-
address: "KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD"
|
|
7198
|
-
},
|
|
7199
7210
|
{
|
|
7200
7211
|
name: "sol_oracle"
|
|
7201
7212
|
},
|
|
@@ -7260,22 +7271,6 @@ var instructions = [
|
|
|
7260
7271
|
]
|
|
7261
7272
|
}
|
|
7262
7273
|
}
|
|
7263
|
-
},
|
|
7264
|
-
{
|
|
7265
|
-
name: "pyth_oracle",
|
|
7266
|
-
optional: true
|
|
7267
|
-
},
|
|
7268
|
-
{
|
|
7269
|
-
name: "switchboard_price_oracle",
|
|
7270
|
-
optional: true
|
|
7271
|
-
},
|
|
7272
|
-
{
|
|
7273
|
-
name: "switchboard_twap_oracle",
|
|
7274
|
-
optional: true
|
|
7275
|
-
},
|
|
7276
|
-
{
|
|
7277
|
-
name: "scope_prices",
|
|
7278
|
-
optional: true
|
|
7279
7274
|
}
|
|
7280
7275
|
],
|
|
7281
7276
|
args: [
|
|
@@ -9588,6 +9583,10 @@ var instructions = [
|
|
|
9588
9583
|
{
|
|
9589
9584
|
name: "stake_history",
|
|
9590
9585
|
address: "SysvarStakeHistory1111111111111111111111111"
|
|
9586
|
+
},
|
|
9587
|
+
{
|
|
9588
|
+
name: "system_program",
|
|
9589
|
+
address: "11111111111111111111111111111111"
|
|
9591
9590
|
}
|
|
9592
9591
|
],
|
|
9593
9592
|
args: [
|
|
@@ -15584,12 +15583,12 @@ class BaseClient {
|
|
|
15584
15583
|
const { t: lookupTables } = data;
|
|
15585
15584
|
const pubkeys = Object.keys(lookupTables);
|
|
15586
15585
|
if (pubkeys.length > 0) {
|
|
15587
|
-
return await this.
|
|
15586
|
+
return await this.fetchAddressLookupTableAccounts(pubkeys);
|
|
15588
15587
|
}
|
|
15589
15588
|
}
|
|
15590
15589
|
const tablePubkey = STATES_LOOKUP_TABLES_MAP.get(this.statePda.toBase58());
|
|
15591
15590
|
if (tablePubkey) {
|
|
15592
|
-
return await this.
|
|
15591
|
+
return await this.fetchAddressLookupTableAccounts([
|
|
15593
15592
|
tablePubkey
|
|
15594
15593
|
]);
|
|
15595
15594
|
}
|
|
@@ -15640,12 +15639,12 @@ class BaseClient {
|
|
|
15640
15639
|
}
|
|
15641
15640
|
const lookupTableAccounts = [];
|
|
15642
15641
|
if (lookupTables.every((t)=>t instanceof AddressLookupTableAccount)) {
|
|
15643
|
-
const accounts = await this.
|
|
15642
|
+
const accounts = await this.fetchAddressLookupTableAccounts([
|
|
15644
15643
|
...LOOKUP_TABLES
|
|
15645
15644
|
]);
|
|
15646
15645
|
lookupTableAccounts.push(...lookupTables, ...accounts);
|
|
15647
15646
|
} else {
|
|
15648
|
-
const accounts = await this.
|
|
15647
|
+
const accounts = await this.fetchAddressLookupTableAccounts([
|
|
15649
15648
|
...lookupTables,
|
|
15650
15649
|
...LOOKUP_TABLES
|
|
15651
15650
|
]);
|
|
@@ -15729,7 +15728,7 @@ class BaseClient {
|
|
|
15729
15728
|
*
|
|
15730
15729
|
* @param pubkeys Array of lookup table public keys.
|
|
15731
15730
|
* @returns
|
|
15732
|
-
*/ async
|
|
15731
|
+
*/ async fetchAddressLookupTableAccounts(pubkeys) {
|
|
15733
15732
|
if (!pubkeys) {
|
|
15734
15733
|
throw new Error("addressLookupTableAddresses is undefined");
|
|
15735
15734
|
}
|
|
@@ -20804,9 +20803,7 @@ class KaminoVaultsClient {
|
|
|
20804
20803
|
return vaultState;
|
|
20805
20804
|
}
|
|
20806
20805
|
async composeRemainingAccounts(allocationStrategies, pricingMode = false) {
|
|
20807
|
-
|
|
20808
|
-
const reservesSet = new Set(allocationStrategies.map((strategy)=>strategy.reserve.toBase58()));
|
|
20809
|
-
const reserves = Array.from(reservesSet).map((p)=>new PublicKey(p));
|
|
20806
|
+
const reserves = allocationStrategies.map((strategy)=>strategy.reserve);
|
|
20810
20807
|
const parsedReserves = await this.kaminoLending.fetchAndParseReserves(reserves);
|
|
20811
20808
|
const reserveMetas = reserves.map((pubkey)=>({
|
|
20812
20809
|
pubkey,
|
|
@@ -21419,26 +21416,41 @@ class PriceClient {
|
|
|
21419
21416
|
oracles[i]
|
|
21420
21417
|
].map((pubkey)=>{
|
|
21421
21418
|
remainingAccounts.push({
|
|
21422
|
-
pubkey,
|
|
21419
|
+
pubkey: pubkey,
|
|
21423
21420
|
isSigner: false,
|
|
21424
21421
|
isWritable: false
|
|
21425
21422
|
});
|
|
21426
21423
|
});
|
|
21427
21424
|
}
|
|
21428
|
-
// markets and reserves
|
|
21429
21425
|
const marketsAndReserves = (await Promise.all(kvaultStates.map((kvault)=>{
|
|
21430
21426
|
return this.kvaults.composeRemainingAccounts(kvault.vaultAllocationStrategy.filter((alloc)=>!alloc.reserve.equals(PublicKey.default)), true);
|
|
21431
21427
|
}))).flat();
|
|
21432
|
-
|
|
21428
|
+
const processed = new Set();
|
|
21429
|
+
const preInstructions = [];
|
|
21430
|
+
const chunkSize = 2;
|
|
21431
|
+
for(let i = 0; i < marketsAndReserves.length; i += chunkSize){
|
|
21432
|
+
const chunk = marketsAndReserves.slice(i, i + chunkSize);
|
|
21433
|
+
const market = chunk[0].pubkey;
|
|
21434
|
+
const reserve = chunk[1].pubkey;
|
|
21435
|
+
// reserve should always be added to remaining accounts
|
|
21436
|
+
remainingAccounts.push(chunk[1]);
|
|
21437
|
+
// each reserve should only be refreshed once
|
|
21438
|
+
if (!processed.has(reserve.toBase58())) {
|
|
21439
|
+
const ix = this.klend.refreshReserveIxs(market, [
|
|
21440
|
+
reserve
|
|
21441
|
+
]);
|
|
21442
|
+
preInstructions.push(...ix);
|
|
21443
|
+
processed.add(reserve.toBase58());
|
|
21444
|
+
}
|
|
21445
|
+
}
|
|
21433
21446
|
const priceIx = await this.base.program.methods.priceKaminoVaultShares(priceDenom, shareAtas.length).accounts({
|
|
21434
21447
|
glamState: this.base.statePda,
|
|
21435
|
-
solOracle: SOL_ORACLE
|
|
21436
|
-
pythOracle: null,
|
|
21437
|
-
switchboardPriceOracle: null,
|
|
21438
|
-
switchboardTwapOracle: null,
|
|
21439
|
-
scopePrices: KAMINO_SCOPE_PRICES
|
|
21448
|
+
solOracle: SOL_ORACLE
|
|
21440
21449
|
}).remainingAccounts(remainingAccounts).instruction();
|
|
21441
|
-
return
|
|
21450
|
+
return [
|
|
21451
|
+
...preInstructions,
|
|
21452
|
+
priceIx
|
|
21453
|
+
];
|
|
21442
21454
|
}
|
|
21443
21455
|
/**
|
|
21444
21456
|
* Returns an instruction that prices all Drift users (aka sub-accounts) controlled by the GLAM vault.
|
|
@@ -21506,43 +21518,8 @@ class PriceClient {
|
|
|
21506
21518
|
if (parsedVaultDepositors.length === 0) {
|
|
21507
21519
|
return null;
|
|
21508
21520
|
}
|
|
21509
|
-
|
|
21510
|
-
|
|
21511
|
-
// - drift vault
|
|
21512
|
-
// - drift user of the vault
|
|
21513
|
-
// - oracles
|
|
21514
|
-
// - spot & perp markets
|
|
21515
|
-
// There might be overlaps between markets and oracles so we use a set to avoid duplicates
|
|
21516
|
-
const remainingAccounts = [];
|
|
21517
|
-
const marketsAndOracles = new Set();
|
|
21518
|
-
for (const depositor of parsedVaultDepositors){
|
|
21519
|
-
const { user: driftUser } = await this.dvaults.parseDriftVault(depositor.driftVault);
|
|
21520
|
-
remainingAccounts.push({
|
|
21521
|
-
pubkey: depositor.address,
|
|
21522
|
-
isSigner: false,
|
|
21523
|
-
isWritable: false
|
|
21524
|
-
});
|
|
21525
|
-
remainingAccounts.push({
|
|
21526
|
-
pubkey: depositor.driftVault,
|
|
21527
|
-
isSigner: false,
|
|
21528
|
-
isWritable: false
|
|
21529
|
-
});
|
|
21530
|
-
remainingAccounts.push({
|
|
21531
|
-
pubkey: driftUser,
|
|
21532
|
-
isSigner: false,
|
|
21533
|
-
isWritable: false
|
|
21534
|
-
});
|
|
21535
|
-
const markets_and_oracles = (await this.dvaults.composeRemainingAccounts(driftUser)).map((a)=>a.pubkey.toBase58());
|
|
21536
|
-
for (const k of markets_and_oracles){
|
|
21537
|
-
marketsAndOracles.add(k);
|
|
21538
|
-
}
|
|
21539
|
-
}
|
|
21540
|
-
Array.from(marketsAndOracles).forEach((k)=>remainingAccounts.push({
|
|
21541
|
-
pubkey: new PublicKey(k),
|
|
21542
|
-
isSigner: false,
|
|
21543
|
-
isWritable: false
|
|
21544
|
-
}));
|
|
21545
|
-
const priceIx = await this.base.program.methods.priceDriftVaultDepositors(priceDenom, parsedVaultDepositors.length).accounts({
|
|
21521
|
+
const { remainingAccounts, numSpotMarkets, numPerpMarkets } = await this.remainingAccountsForPricingDriftVaultDepositors(parsedVaultDepositors);
|
|
21522
|
+
const priceIx = await this.base.program.methods.priceDriftVaultDepositors(priceDenom, parsedVaultDepositors.length, numSpotMarkets, numPerpMarkets).accounts({
|
|
21546
21523
|
glamState: this.base.statePda,
|
|
21547
21524
|
solOracle: SOL_ORACLE
|
|
21548
21525
|
}).remainingAccounts(remainingAccounts).instruction();
|
|
@@ -21609,12 +21586,11 @@ class PriceClient {
|
|
|
21609
21586
|
}
|
|
21610
21587
|
const integrations = (stateModel.integrations || []).map((i)=>Object.keys(i)[0]);
|
|
21611
21588
|
const integrationsToPricingFns = {
|
|
21612
|
-
drift: this.priceDriftUsersIx.bind(this),
|
|
21613
|
-
kaminoLending: this.priceKaminoObligationsIx.bind(this),
|
|
21614
|
-
nativeStaking: this.priceStakesIx.bind(this),
|
|
21615
|
-
meteoraDlmm: this.priceMeteoraPositionsIx.bind(this),
|
|
21616
|
-
driftVaults: this.priceDriftVaultDepositorsIx.bind(this)
|
|
21617
|
-
kaminoVaults: this.priceKaminoVaultSharesIx.bind(this)
|
|
21589
|
+
// drift: this.priceDriftUsersIx.bind(this),
|
|
21590
|
+
// kaminoLending: this.priceKaminoObligationsIx.bind(this),
|
|
21591
|
+
// nativeStaking: this.priceStakesIx.bind(this),
|
|
21592
|
+
// meteoraDlmm: this.priceMeteoraPositionsIx.bind(this),
|
|
21593
|
+
driftVaults: this.priceDriftVaultDepositorsIx.bind(this)
|
|
21618
21594
|
};
|
|
21619
21595
|
const pricingFns = integrations.map((integration)=>integrationsToPricingFns[integration]).filter(Boolean);
|
|
21620
21596
|
const pricingIxs = [
|
|
@@ -21622,72 +21598,130 @@ class PriceClient {
|
|
|
21622
21598
|
];
|
|
21623
21599
|
for (const fn of pricingFns){
|
|
21624
21600
|
const ix = await fn(priceDenom);
|
|
21625
|
-
|
|
21601
|
+
if (Array.isArray(ix)) {
|
|
21602
|
+
pricingIxs.push(...ix);
|
|
21603
|
+
} else {
|
|
21604
|
+
pricingIxs.push(ix);
|
|
21605
|
+
}
|
|
21626
21606
|
}
|
|
21627
21607
|
return pricingIxs.filter(Boolean);
|
|
21628
21608
|
}
|
|
21609
|
+
async remainingAccountsForPricingDriftVaultDepositors(parsedVaultDepositors) {
|
|
21610
|
+
// Extra accounts for pricing N vault depositors:
|
|
21611
|
+
// - (vault_depositor, drift_vault, drift_user) x N
|
|
21612
|
+
// - spot_market used by drift users of vaults (no specific order)
|
|
21613
|
+
// - perp markets used by drift users of vaults (no specific order)
|
|
21614
|
+
// - oracles of spot markets and perp markets (no specific order)
|
|
21615
|
+
const remainingAccounts = [];
|
|
21616
|
+
const spotMarketsSet = new Set();
|
|
21617
|
+
const perpMarketsSet = new Set();
|
|
21618
|
+
const oraclesSet = new Set();
|
|
21619
|
+
for (const { address: depositor, driftVault } of parsedVaultDepositors){
|
|
21620
|
+
const { user } = await this.dvaults.parseDriftVault(driftVault); // get drift user used by the vault
|
|
21621
|
+
[
|
|
21622
|
+
depositor,
|
|
21623
|
+
driftVault,
|
|
21624
|
+
user
|
|
21625
|
+
].forEach((k)=>remainingAccounts.push({
|
|
21626
|
+
pubkey: k,
|
|
21627
|
+
isSigner: false,
|
|
21628
|
+
isWritable: false
|
|
21629
|
+
}));
|
|
21630
|
+
const { spotPositions, perpPositions } = await this.dvaults.fetchUserPositions(user);
|
|
21631
|
+
const spotMarketIndexes = spotPositions.map((p)=>p.marketIndex);
|
|
21632
|
+
const perpMarketIndexes = perpPositions.map((p)=>p.marketIndex);
|
|
21633
|
+
// If there are perp positions, add spot market 0 as it's used as quote market for perp
|
|
21634
|
+
if (perpMarketIndexes.length > 0 && !spotMarketIndexes.includes(0)) {
|
|
21635
|
+
spotMarketIndexes.push(0);
|
|
21636
|
+
}
|
|
21637
|
+
const spotMarkets = await this.drift.fetchAndParseSpotMarkets(spotMarketIndexes);
|
|
21638
|
+
const perpMarkets = await this.drift.fetchAndParsePerpMarkets(perpMarketIndexes);
|
|
21639
|
+
spotMarkets.forEach((m)=>{
|
|
21640
|
+
oraclesSet.add(m.oracle.toBase58());
|
|
21641
|
+
spotMarketsSet.add(m.marketPda.toBase58());
|
|
21642
|
+
});
|
|
21643
|
+
perpMarkets.forEach((m)=>{
|
|
21644
|
+
oraclesSet.add(m.oracle.toBase58());
|
|
21645
|
+
perpMarketsSet.add(m.marketPda.toBase58());
|
|
21646
|
+
});
|
|
21647
|
+
}
|
|
21648
|
+
[
|
|
21649
|
+
...spotMarketsSet,
|
|
21650
|
+
...perpMarketsSet,
|
|
21651
|
+
...oraclesSet
|
|
21652
|
+
].forEach((k)=>remainingAccounts.push({
|
|
21653
|
+
pubkey: new PublicKey(k),
|
|
21654
|
+
isSigner: false,
|
|
21655
|
+
isWritable: false
|
|
21656
|
+
}));
|
|
21657
|
+
return {
|
|
21658
|
+
remainingAccounts,
|
|
21659
|
+
numSpotMarkets: spotMarketsSet.size,
|
|
21660
|
+
numPerpMarkets: perpMarketsSet.size
|
|
21661
|
+
};
|
|
21662
|
+
}
|
|
21663
|
+
async remainingAccountsForPricingMeteora() {
|
|
21664
|
+
const positions = await fetchMeteoraPositions(this.base.provider.connection, this.base.vaultPda);
|
|
21665
|
+
let chunks = await Promise.all(positions.map(async (pubkey)=>{
|
|
21666
|
+
const { lbPair, binArrayLower, binArrayUpper } = await parseMeteoraPosition(this.base.provider.connection, pubkey);
|
|
21667
|
+
return [
|
|
21668
|
+
pubkey,
|
|
21669
|
+
lbPair,
|
|
21670
|
+
binArrayLower,
|
|
21671
|
+
binArrayUpper,
|
|
21672
|
+
SOL_ORACLE,
|
|
21673
|
+
USDC_ORACLE
|
|
21674
|
+
].map((k)=>({
|
|
21675
|
+
pubkey: k,
|
|
21676
|
+
isSigner: false,
|
|
21677
|
+
isWritable: false
|
|
21678
|
+
}));
|
|
21679
|
+
}));
|
|
21680
|
+
return chunks.flat();
|
|
21681
|
+
}
|
|
21682
|
+
async remainingAccountsForPricingVaultAssets(baseAssetOnly = false) {
|
|
21683
|
+
const stateModel = await this.base.fetchStateModel();
|
|
21684
|
+
if (baseAssetOnly) {
|
|
21685
|
+
if (!stateModel.baseAsset) {
|
|
21686
|
+
throw new Error("Base asset not configured for the vault");
|
|
21687
|
+
}
|
|
21688
|
+
// FIXME: support token 2022 base asset
|
|
21689
|
+
const ata = this.base.getVaultAta(stateModel.baseAsset);
|
|
21690
|
+
// Set oracle to default pubkey (aka system program) to indicate oracle isn't needed
|
|
21691
|
+
return [
|
|
21692
|
+
ata,
|
|
21693
|
+
stateModel.baseAsset,
|
|
21694
|
+
PublicKey.default
|
|
21695
|
+
].map((k)=>({
|
|
21696
|
+
pubkey: k,
|
|
21697
|
+
isSigner: false,
|
|
21698
|
+
isWritable: false
|
|
21699
|
+
}));
|
|
21700
|
+
}
|
|
21701
|
+
const assetsForPricing = (stateModel.borrowableAssets || []).concat(stateModel.assets || []);
|
|
21702
|
+
return assetsForPricing.map((mint)=>{
|
|
21703
|
+
const assetMeta = ASSETS_MAINNET.get(mint.toBase58());
|
|
21704
|
+
if (!assetMeta) {
|
|
21705
|
+
throw new Error(`Asset meta not found for ${mint}`);
|
|
21706
|
+
}
|
|
21707
|
+
const ata = this.base.getVaultAta(mint, assetMeta?.programId);
|
|
21708
|
+
return [
|
|
21709
|
+
ata,
|
|
21710
|
+
mint,
|
|
21711
|
+
assetMeta?.oracle
|
|
21712
|
+
];
|
|
21713
|
+
}).flat().map((a)=>({
|
|
21714
|
+
pubkey: a,
|
|
21715
|
+
isSigner: false,
|
|
21716
|
+
isWritable: false
|
|
21717
|
+
}));
|
|
21718
|
+
}
|
|
21629
21719
|
constructor(base, klend, kvaults, drift, dvaults){
|
|
21630
21720
|
this.base = base;
|
|
21631
21721
|
this.klend = klend;
|
|
21632
21722
|
this.kvaults = kvaults;
|
|
21633
21723
|
this.drift = drift;
|
|
21634
21724
|
this.dvaults = dvaults;
|
|
21635
|
-
this.remainingAccountsForPricingMeteora = async ()=>{
|
|
21636
|
-
const positions = await fetchMeteoraPositions(this.base.provider.connection, this.base.vaultPda);
|
|
21637
|
-
let chunks = await Promise.all(positions.map(async (pubkey)=>{
|
|
21638
|
-
const { lbPair, binArrayLower, binArrayUpper } = await parseMeteoraPosition(this.base.provider.connection, pubkey);
|
|
21639
|
-
return [
|
|
21640
|
-
pubkey,
|
|
21641
|
-
lbPair,
|
|
21642
|
-
binArrayLower,
|
|
21643
|
-
binArrayUpper,
|
|
21644
|
-
SOL_ORACLE,
|
|
21645
|
-
USDC_ORACLE
|
|
21646
|
-
].map((k)=>({
|
|
21647
|
-
pubkey: k,
|
|
21648
|
-
isSigner: false,
|
|
21649
|
-
isWritable: false
|
|
21650
|
-
}));
|
|
21651
|
-
}));
|
|
21652
|
-
return chunks.flat();
|
|
21653
|
-
};
|
|
21654
|
-
this.remainingAccountsForPricingVaultAssets = async (baseAssetOnly = false)=>{
|
|
21655
|
-
const stateModel = await this.base.fetchStateModel();
|
|
21656
|
-
if (baseAssetOnly) {
|
|
21657
|
-
if (!stateModel.baseAsset) {
|
|
21658
|
-
throw new Error("Base asset not configured for the vault");
|
|
21659
|
-
}
|
|
21660
|
-
// FIXME: support token 2022 base asset
|
|
21661
|
-
const ata = this.base.getVaultAta(stateModel.baseAsset);
|
|
21662
|
-
// Set oracle to default pubkey (aka system program) to indicate oracle isn't needed
|
|
21663
|
-
return [
|
|
21664
|
-
ata,
|
|
21665
|
-
stateModel.baseAsset,
|
|
21666
|
-
PublicKey.default
|
|
21667
|
-
].map((k)=>({
|
|
21668
|
-
pubkey: k,
|
|
21669
|
-
isSigner: false,
|
|
21670
|
-
isWritable: false
|
|
21671
|
-
}));
|
|
21672
|
-
}
|
|
21673
|
-
const assetsForPricing = (stateModel.borrowableAssets || []).concat(stateModel.assets || []);
|
|
21674
|
-
return assetsForPricing.map((mint)=>{
|
|
21675
|
-
const assetMeta = ASSETS_MAINNET.get(mint.toBase58());
|
|
21676
|
-
if (!assetMeta) {
|
|
21677
|
-
throw new Error(`Asset meta not found for ${mint}`);
|
|
21678
|
-
}
|
|
21679
|
-
const ata = this.base.getVaultAta(mint, assetMeta?.programId);
|
|
21680
|
-
return [
|
|
21681
|
-
ata,
|
|
21682
|
-
mint,
|
|
21683
|
-
assetMeta?.oracle
|
|
21684
|
-
];
|
|
21685
|
-
}).flat().map((a)=>({
|
|
21686
|
-
pubkey: a,
|
|
21687
|
-
isSigner: false,
|
|
21688
|
-
isWritable: false
|
|
21689
|
-
}));
|
|
21690
|
-
};
|
|
21691
21725
|
}
|
|
21692
21726
|
}
|
|
21693
21727
|
|
package/package.json
CHANGED
package/src/client/base.d.ts
CHANGED
|
@@ -62,7 +62,7 @@ export declare class BaseClient {
|
|
|
62
62
|
* @param pubkeys Array of lookup table public keys.
|
|
63
63
|
* @returns
|
|
64
64
|
*/
|
|
65
|
-
|
|
65
|
+
fetchAddressLookupTableAccounts(pubkeys?: string[] | PublicKey[]): Promise<AddressLookupTableAccount[]>;
|
|
66
66
|
getWallet(): Wallet;
|
|
67
67
|
getSigner(): PublicKey;
|
|
68
68
|
get signer(): PublicKey;
|
package/src/client/price.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PublicKey, TransactionInstruction } from "@solana/web3.js";
|
|
1
|
+
import { AccountMeta, PublicKey, TransactionInstruction } from "@solana/web3.js";
|
|
2
2
|
import { KaminoLendingClient, KaminoVaultsClient } from "./kamino";
|
|
3
3
|
import { BaseClient } from "./base";
|
|
4
4
|
import { PriceDenom } from "../models";
|
|
@@ -21,7 +21,7 @@ export declare class PriceClient {
|
|
|
21
21
|
* If there are no Kamino obligations, returns null.
|
|
22
22
|
*/
|
|
23
23
|
priceKaminoObligationsIx(priceDenom: PriceDenom): Promise<TransactionInstruction | null>;
|
|
24
|
-
priceKaminoVaultSharesIx(priceDenom: PriceDenom): Promise<TransactionInstruction | null>;
|
|
24
|
+
priceKaminoVaultSharesIx(priceDenom: PriceDenom): Promise<TransactionInstruction[] | null>;
|
|
25
25
|
/**
|
|
26
26
|
* Returns an instruction that prices all Drift users (aka sub-accounts) controlled by the GLAM vault.
|
|
27
27
|
*/
|
|
@@ -46,14 +46,15 @@ export declare class PriceClient {
|
|
|
46
46
|
*/
|
|
47
47
|
priceMeteoraPositionsIx(priceDenom: PriceDenom): Promise<TransactionInstruction | null>;
|
|
48
48
|
priceVaultIxs(priceDenom: PriceDenom): Promise<TransactionInstruction[]>;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}[]
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
49
|
+
remainingAccountsForPricingDriftVaultDepositors(parsedVaultDepositors: {
|
|
50
|
+
address: PublicKey;
|
|
51
|
+
driftVault: PublicKey;
|
|
52
|
+
shares: any;
|
|
53
|
+
}[]): Promise<{
|
|
54
|
+
remainingAccounts: AccountMeta[];
|
|
55
|
+
numSpotMarkets: number;
|
|
56
|
+
numPerpMarkets: number;
|
|
57
|
+
}>;
|
|
58
|
+
remainingAccountsForPricingMeteora(): Promise<AccountMeta[]>;
|
|
59
|
+
remainingAccountsForPricingVaultAssets(baseAssetOnly?: boolean): Promise<AccountMeta[]>;
|
|
59
60
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"address": "GLAMbTqav9N9witRjswJ8enwp9vv5G8bsSJ2kPJ4rcyc",
|
|
3
3
|
"metadata": {
|
|
4
4
|
"name": "glam_protocol",
|
|
5
|
-
"version": "0.4.
|
|
5
|
+
"version": "0.4.35",
|
|
6
6
|
"spec": "0.1.0",
|
|
7
7
|
"description": "Glam Protocol"
|
|
8
8
|
},
|
|
@@ -6868,7 +6868,9 @@
|
|
|
6868
6868
|
"docs": [
|
|
6869
6869
|
"Extra accounts for pricing N vault depositors:",
|
|
6870
6870
|
"- (vault_depositor, drift_vault, drift_user) x N",
|
|
6871
|
-
"-
|
|
6871
|
+
"- spot_market used by drift users of vaults (no specific order)",
|
|
6872
|
+
"- perp markets used by drift users of vaults (no specific order)",
|
|
6873
|
+
"- oracles of spot markets and perp markets (no specific order)"
|
|
6872
6874
|
],
|
|
6873
6875
|
"discriminator": [
|
|
6874
6876
|
234,
|
|
@@ -6989,6 +6991,14 @@
|
|
|
6989
6991
|
{
|
|
6990
6992
|
"name": "num_vault_depositors",
|
|
6991
6993
|
"type": "u8"
|
|
6994
|
+
},
|
|
6995
|
+
{
|
|
6996
|
+
"name": "num_spot_markets",
|
|
6997
|
+
"type": "u8"
|
|
6998
|
+
},
|
|
6999
|
+
{
|
|
7000
|
+
"name": "num_perp_markets",
|
|
7001
|
+
"type": "u8"
|
|
6992
7002
|
}
|
|
6993
7003
|
]
|
|
6994
7004
|
},
|
|
@@ -7135,9 +7145,14 @@
|
|
|
7135
7145
|
{
|
|
7136
7146
|
"name": "price_kamino_vault_shares",
|
|
7137
7147
|
"docs": [
|
|
7148
|
+
"Price Kamino vault shares.",
|
|
7149
|
+
"- `num_vaults` Number of kamino vaults to price.",
|
|
7150
|
+
"",
|
|
7138
7151
|
"Extra accounts for pricing N kamino vault shares:",
|
|
7139
7152
|
"- (kvault_share_ata, kvault_share_mint, kvault_state, kvault_deposit_token_oracle) x N",
|
|
7140
|
-
"-
|
|
7153
|
+
"- reserve x M",
|
|
7154
|
+
"- M = number of reserves used by all kvaults' allocations",
|
|
7155
|
+
"- reserve pubkeys must follow the same order of reserves used by each allocation"
|
|
7141
7156
|
],
|
|
7142
7157
|
"discriminator": [
|
|
7143
7158
|
112,
|
|
@@ -7180,10 +7195,6 @@
|
|
|
7180
7195
|
"writable": true,
|
|
7181
7196
|
"signer": true
|
|
7182
7197
|
},
|
|
7183
|
-
{
|
|
7184
|
-
"name": "kamino_lending_program",
|
|
7185
|
-
"address": "KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD"
|
|
7186
|
-
},
|
|
7187
7198
|
{
|
|
7188
7199
|
"name": "sol_oracle"
|
|
7189
7200
|
},
|
|
@@ -7248,22 +7259,6 @@
|
|
|
7248
7259
|
]
|
|
7249
7260
|
}
|
|
7250
7261
|
}
|
|
7251
|
-
},
|
|
7252
|
-
{
|
|
7253
|
-
"name": "pyth_oracle",
|
|
7254
|
-
"optional": true
|
|
7255
|
-
},
|
|
7256
|
-
{
|
|
7257
|
-
"name": "switchboard_price_oracle",
|
|
7258
|
-
"optional": true
|
|
7259
|
-
},
|
|
7260
|
-
{
|
|
7261
|
-
"name": "switchboard_twap_oracle",
|
|
7262
|
-
"optional": true
|
|
7263
|
-
},
|
|
7264
|
-
{
|
|
7265
|
-
"name": "scope_prices",
|
|
7266
|
-
"optional": true
|
|
7267
7262
|
}
|
|
7268
7263
|
],
|
|
7269
7264
|
"args": [
|
|
@@ -9576,6 +9571,10 @@
|
|
|
9576
9571
|
{
|
|
9577
9572
|
"name": "stake_history",
|
|
9578
9573
|
"address": "SysvarStakeHistory1111111111111111111111111"
|
|
9574
|
+
},
|
|
9575
|
+
{
|
|
9576
|
+
"name": "system_program",
|
|
9577
|
+
"address": "11111111111111111111111111111111"
|
|
9579
9578
|
}
|
|
9580
9579
|
],
|
|
9581
9580
|
"args": [
|
|
@@ -8,7 +8,7 @@ export type GlamProtocol = {
|
|
|
8
8
|
"address": "GLAMbTqav9N9witRjswJ8enwp9vv5G8bsSJ2kPJ4rcyc";
|
|
9
9
|
"metadata": {
|
|
10
10
|
"name": "glamProtocol";
|
|
11
|
-
"version": "0.4.
|
|
11
|
+
"version": "0.4.35";
|
|
12
12
|
"spec": "0.1.0";
|
|
13
13
|
"description": "Glam Protocol";
|
|
14
14
|
};
|
|
@@ -6874,7 +6874,9 @@ export type GlamProtocol = {
|
|
|
6874
6874
|
"docs": [
|
|
6875
6875
|
"Extra accounts for pricing N vault depositors:",
|
|
6876
6876
|
"- (vault_depositor, drift_vault, drift_user) x N",
|
|
6877
|
-
"-
|
|
6877
|
+
"- spot_market used by drift users of vaults (no specific order)",
|
|
6878
|
+
"- perp markets used by drift users of vaults (no specific order)",
|
|
6879
|
+
"- oracles of spot markets and perp markets (no specific order)"
|
|
6878
6880
|
];
|
|
6879
6881
|
"discriminator": [
|
|
6880
6882
|
234,
|
|
@@ -6995,6 +6997,14 @@ export type GlamProtocol = {
|
|
|
6995
6997
|
{
|
|
6996
6998
|
"name": "numVaultDepositors";
|
|
6997
6999
|
"type": "u8";
|
|
7000
|
+
},
|
|
7001
|
+
{
|
|
7002
|
+
"name": "numSpotMarkets";
|
|
7003
|
+
"type": "u8";
|
|
7004
|
+
},
|
|
7005
|
+
{
|
|
7006
|
+
"name": "numPerpMarkets";
|
|
7007
|
+
"type": "u8";
|
|
6998
7008
|
}
|
|
6999
7009
|
];
|
|
7000
7010
|
},
|
|
@@ -7141,9 +7151,14 @@ export type GlamProtocol = {
|
|
|
7141
7151
|
{
|
|
7142
7152
|
"name": "priceKaminoVaultShares";
|
|
7143
7153
|
"docs": [
|
|
7154
|
+
"Price Kamino vault shares.",
|
|
7155
|
+
"- `num_vaults` Number of kamino vaults to price.",
|
|
7156
|
+
"",
|
|
7144
7157
|
"Extra accounts for pricing N kamino vault shares:",
|
|
7145
7158
|
"- (kvault_share_ata, kvault_share_mint, kvault_state, kvault_deposit_token_oracle) x N",
|
|
7146
|
-
"-
|
|
7159
|
+
"- reserve x M",
|
|
7160
|
+
"- M = number of reserves used by all kvaults' allocations",
|
|
7161
|
+
"- reserve pubkeys must follow the same order of reserves used by each allocation"
|
|
7147
7162
|
];
|
|
7148
7163
|
"discriminator": [
|
|
7149
7164
|
112,
|
|
@@ -7186,10 +7201,6 @@ export type GlamProtocol = {
|
|
|
7186
7201
|
"writable": true;
|
|
7187
7202
|
"signer": true;
|
|
7188
7203
|
},
|
|
7189
|
-
{
|
|
7190
|
-
"name": "kaminoLendingProgram";
|
|
7191
|
-
"address": "KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD";
|
|
7192
|
-
},
|
|
7193
7204
|
{
|
|
7194
7205
|
"name": "solOracle";
|
|
7195
7206
|
},
|
|
@@ -7254,22 +7265,6 @@ export type GlamProtocol = {
|
|
|
7254
7265
|
];
|
|
7255
7266
|
};
|
|
7256
7267
|
};
|
|
7257
|
-
},
|
|
7258
|
-
{
|
|
7259
|
-
"name": "pythOracle";
|
|
7260
|
-
"optional": true;
|
|
7261
|
-
},
|
|
7262
|
-
{
|
|
7263
|
-
"name": "switchboardPriceOracle";
|
|
7264
|
-
"optional": true;
|
|
7265
|
-
},
|
|
7266
|
-
{
|
|
7267
|
-
"name": "switchboardTwapOracle";
|
|
7268
|
-
"optional": true;
|
|
7269
|
-
},
|
|
7270
|
-
{
|
|
7271
|
-
"name": "scopePrices";
|
|
7272
|
-
"optional": true;
|
|
7273
7268
|
}
|
|
7274
7269
|
];
|
|
7275
7270
|
"args": [
|
|
@@ -9582,6 +9577,10 @@ export type GlamProtocol = {
|
|
|
9582
9577
|
{
|
|
9583
9578
|
"name": "stakeHistory";
|
|
9584
9579
|
"address": "SysvarStakeHistory1111111111111111111111111";
|
|
9580
|
+
},
|
|
9581
|
+
{
|
|
9582
|
+
"name": "systemProgram";
|
|
9583
|
+
"address": "11111111111111111111111111111111";
|
|
9585
9584
|
}
|
|
9586
9585
|
];
|
|
9587
9586
|
"args": [
|
|
@@ -8,7 +8,7 @@ export type GlamProtocol = {
|
|
|
8
8
|
"address": "GLAMbTqav9N9witRjswJ8enwp9vv5G8bsSJ2kPJ4rcyc",
|
|
9
9
|
"metadata": {
|
|
10
10
|
"name": "glamProtocol",
|
|
11
|
-
"version": "0.4.
|
|
11
|
+
"version": "0.4.35",
|
|
12
12
|
"spec": "0.1.0",
|
|
13
13
|
"description": "Glam Protocol"
|
|
14
14
|
},
|
|
@@ -6874,7 +6874,9 @@ export type GlamProtocol = {
|
|
|
6874
6874
|
"docs": [
|
|
6875
6875
|
"Extra accounts for pricing N vault depositors:",
|
|
6876
6876
|
"- (vault_depositor, drift_vault, drift_user) x N",
|
|
6877
|
-
"-
|
|
6877
|
+
"- spot_market used by drift users of vaults (no specific order)",
|
|
6878
|
+
"- perp markets used by drift users of vaults (no specific order)",
|
|
6879
|
+
"- oracles of spot markets and perp markets (no specific order)"
|
|
6878
6880
|
],
|
|
6879
6881
|
"discriminator": [
|
|
6880
6882
|
234,
|
|
@@ -6995,6 +6997,14 @@ export type GlamProtocol = {
|
|
|
6995
6997
|
{
|
|
6996
6998
|
"name": "numVaultDepositors",
|
|
6997
6999
|
"type": "u8"
|
|
7000
|
+
},
|
|
7001
|
+
{
|
|
7002
|
+
"name": "numSpotMarkets",
|
|
7003
|
+
"type": "u8"
|
|
7004
|
+
},
|
|
7005
|
+
{
|
|
7006
|
+
"name": "numPerpMarkets",
|
|
7007
|
+
"type": "u8"
|
|
6998
7008
|
}
|
|
6999
7009
|
]
|
|
7000
7010
|
},
|
|
@@ -7141,9 +7151,14 @@ export type GlamProtocol = {
|
|
|
7141
7151
|
{
|
|
7142
7152
|
"name": "priceKaminoVaultShares",
|
|
7143
7153
|
"docs": [
|
|
7154
|
+
"Price Kamino vault shares.",
|
|
7155
|
+
"- `num_vaults` Number of kamino vaults to price.",
|
|
7156
|
+
"",
|
|
7144
7157
|
"Extra accounts for pricing N kamino vault shares:",
|
|
7145
7158
|
"- (kvault_share_ata, kvault_share_mint, kvault_state, kvault_deposit_token_oracle) x N",
|
|
7146
|
-
"-
|
|
7159
|
+
"- reserve x M",
|
|
7160
|
+
"- M = number of reserves used by all kvaults' allocations",
|
|
7161
|
+
"- reserve pubkeys must follow the same order of reserves used by each allocation"
|
|
7147
7162
|
],
|
|
7148
7163
|
"discriminator": [
|
|
7149
7164
|
112,
|
|
@@ -7186,10 +7201,6 @@ export type GlamProtocol = {
|
|
|
7186
7201
|
"writable": true,
|
|
7187
7202
|
"signer": true
|
|
7188
7203
|
},
|
|
7189
|
-
{
|
|
7190
|
-
"name": "kaminoLendingProgram",
|
|
7191
|
-
"address": "KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD"
|
|
7192
|
-
},
|
|
7193
7204
|
{
|
|
7194
7205
|
"name": "solOracle"
|
|
7195
7206
|
},
|
|
@@ -7254,22 +7265,6 @@ export type GlamProtocol = {
|
|
|
7254
7265
|
]
|
|
7255
7266
|
}
|
|
7256
7267
|
}
|
|
7257
|
-
},
|
|
7258
|
-
{
|
|
7259
|
-
"name": "pythOracle",
|
|
7260
|
-
"optional": true
|
|
7261
|
-
},
|
|
7262
|
-
{
|
|
7263
|
-
"name": "switchboardPriceOracle",
|
|
7264
|
-
"optional": true
|
|
7265
|
-
},
|
|
7266
|
-
{
|
|
7267
|
-
"name": "switchboardTwapOracle",
|
|
7268
|
-
"optional": true
|
|
7269
|
-
},
|
|
7270
|
-
{
|
|
7271
|
-
"name": "scopePrices",
|
|
7272
|
-
"optional": true
|
|
7273
7268
|
}
|
|
7274
7269
|
],
|
|
7275
7270
|
"args": [
|
|
@@ -9582,6 +9577,10 @@ export type GlamProtocol = {
|
|
|
9582
9577
|
{
|
|
9583
9578
|
"name": "stakeHistory",
|
|
9584
9579
|
"address": "SysvarStakeHistory1111111111111111111111111"
|
|
9580
|
+
},
|
|
9581
|
+
{
|
|
9582
|
+
"name": "systemProgram",
|
|
9583
|
+
"address": "11111111111111111111111111111111"
|
|
9585
9584
|
}
|
|
9586
9585
|
],
|
|
9587
9586
|
"args": [
|