@glamsystems/glam-sdk 0.1.26 → 0.1.27
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 +536 -95
- package/index.esm.js +536 -96
- package/package.json +1 -1
- package/src/client/base.d.ts +1 -1
- package/src/client/drift.d.ts +8 -8
- package/src/client/kamino.d.ts +18 -1
- package/src/client/price.d.ts +5 -3
- package/src/client/vault.d.ts +1 -1
- package/src/client.d.ts +3 -1
- package/src/constants.d.ts +1 -0
- package/src/{layouts/drift-vault.d.ts → deser/driftLayouts.d.ts} +17 -0
- package/src/deser/kaminoLayouts.d.ts +55 -0
- package/src/utils/driftTypes.d.ts +1 -0
- package/target/idl/glam_protocol.json +147 -3
- package/target/types/glam_protocol.d.ts +145 -1
- package/target/types/glam_protocol.ts +147 -3
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.29",
|
|
38
38
|
spec: "0.1.0",
|
|
39
39
|
description: "Glam Protocol"
|
|
40
40
|
};
|
|
@@ -4284,10 +4284,12 @@ var instructions = [
|
|
|
4284
4284
|
],
|
|
4285
4285
|
accounts: [
|
|
4286
4286
|
{
|
|
4287
|
-
name: "glam_state"
|
|
4287
|
+
name: "glam_state",
|
|
4288
|
+
writable: true
|
|
4288
4289
|
},
|
|
4289
4290
|
{
|
|
4290
4291
|
name: "glam_vault",
|
|
4292
|
+
writable: true,
|
|
4291
4293
|
pda: {
|
|
4292
4294
|
seeds: [
|
|
4293
4295
|
{
|
|
@@ -4379,10 +4381,12 @@ var instructions = [
|
|
|
4379
4381
|
],
|
|
4380
4382
|
accounts: [
|
|
4381
4383
|
{
|
|
4382
|
-
name: "glam_state"
|
|
4384
|
+
name: "glam_state",
|
|
4385
|
+
writable: true
|
|
4383
4386
|
},
|
|
4384
4387
|
{
|
|
4385
4388
|
name: "glam_vault",
|
|
4389
|
+
writable: true,
|
|
4386
4390
|
pda: {
|
|
4387
4391
|
seeds: [
|
|
4388
4392
|
{
|
|
@@ -6662,6 +6666,146 @@ var instructions = [
|
|
|
6662
6666
|
}
|
|
6663
6667
|
]
|
|
6664
6668
|
},
|
|
6669
|
+
{
|
|
6670
|
+
name: "price_kamino_vault_shares",
|
|
6671
|
+
discriminator: [
|
|
6672
|
+
112,
|
|
6673
|
+
92,
|
|
6674
|
+
238,
|
|
6675
|
+
224,
|
|
6676
|
+
145,
|
|
6677
|
+
105,
|
|
6678
|
+
38,
|
|
6679
|
+
249
|
|
6680
|
+
],
|
|
6681
|
+
accounts: [
|
|
6682
|
+
{
|
|
6683
|
+
name: "glam_state",
|
|
6684
|
+
writable: true
|
|
6685
|
+
},
|
|
6686
|
+
{
|
|
6687
|
+
name: "glam_vault",
|
|
6688
|
+
pda: {
|
|
6689
|
+
seeds: [
|
|
6690
|
+
{
|
|
6691
|
+
kind: "const",
|
|
6692
|
+
value: [
|
|
6693
|
+
118,
|
|
6694
|
+
97,
|
|
6695
|
+
117,
|
|
6696
|
+
108,
|
|
6697
|
+
116
|
|
6698
|
+
]
|
|
6699
|
+
},
|
|
6700
|
+
{
|
|
6701
|
+
kind: "account",
|
|
6702
|
+
path: "glam_state"
|
|
6703
|
+
}
|
|
6704
|
+
]
|
|
6705
|
+
}
|
|
6706
|
+
},
|
|
6707
|
+
{
|
|
6708
|
+
name: "signer",
|
|
6709
|
+
writable: true,
|
|
6710
|
+
signer: true
|
|
6711
|
+
},
|
|
6712
|
+
{
|
|
6713
|
+
name: "kamino_lending_program",
|
|
6714
|
+
address: "KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD"
|
|
6715
|
+
},
|
|
6716
|
+
{
|
|
6717
|
+
name: "sol_oracle"
|
|
6718
|
+
},
|
|
6719
|
+
{
|
|
6720
|
+
name: "glam_config",
|
|
6721
|
+
pda: {
|
|
6722
|
+
seeds: [
|
|
6723
|
+
{
|
|
6724
|
+
kind: "const",
|
|
6725
|
+
value: [
|
|
6726
|
+
103,
|
|
6727
|
+
108,
|
|
6728
|
+
111,
|
|
6729
|
+
98,
|
|
6730
|
+
97,
|
|
6731
|
+
108,
|
|
6732
|
+
95,
|
|
6733
|
+
99,
|
|
6734
|
+
111,
|
|
6735
|
+
110,
|
|
6736
|
+
102,
|
|
6737
|
+
105,
|
|
6738
|
+
103
|
|
6739
|
+
]
|
|
6740
|
+
}
|
|
6741
|
+
],
|
|
6742
|
+
program: {
|
|
6743
|
+
kind: "const",
|
|
6744
|
+
value: [
|
|
6745
|
+
10,
|
|
6746
|
+
11,
|
|
6747
|
+
0,
|
|
6748
|
+
83,
|
|
6749
|
+
72,
|
|
6750
|
+
16,
|
|
6751
|
+
46,
|
|
6752
|
+
144,
|
|
6753
|
+
46,
|
|
6754
|
+
42,
|
|
6755
|
+
79,
|
|
6756
|
+
22,
|
|
6757
|
+
157,
|
|
6758
|
+
123,
|
|
6759
|
+
21,
|
|
6760
|
+
242,
|
|
6761
|
+
192,
|
|
6762
|
+
146,
|
|
6763
|
+
1,
|
|
6764
|
+
78,
|
|
6765
|
+
88,
|
|
6766
|
+
59,
|
|
6767
|
+
102,
|
|
6768
|
+
9,
|
|
6769
|
+
190,
|
|
6770
|
+
226,
|
|
6771
|
+
92,
|
|
6772
|
+
189,
|
|
6773
|
+
187,
|
|
6774
|
+
232,
|
|
6775
|
+
83,
|
|
6776
|
+
220
|
|
6777
|
+
]
|
|
6778
|
+
}
|
|
6779
|
+
}
|
|
6780
|
+
},
|
|
6781
|
+
{
|
|
6782
|
+
name: "pyth_oracle",
|
|
6783
|
+
optional: true
|
|
6784
|
+
},
|
|
6785
|
+
{
|
|
6786
|
+
name: "switchboard_price_oracle",
|
|
6787
|
+
optional: true
|
|
6788
|
+
},
|
|
6789
|
+
{
|
|
6790
|
+
name: "switchboard_twap_oracle",
|
|
6791
|
+
optional: true
|
|
6792
|
+
},
|
|
6793
|
+
{
|
|
6794
|
+
name: "scope_prices",
|
|
6795
|
+
optional: true
|
|
6796
|
+
}
|
|
6797
|
+
],
|
|
6798
|
+
args: [
|
|
6799
|
+
{
|
|
6800
|
+
name: "denom",
|
|
6801
|
+
type: {
|
|
6802
|
+
defined: {
|
|
6803
|
+
name: "PriceDenom"
|
|
6804
|
+
}
|
|
6805
|
+
}
|
|
6806
|
+
}
|
|
6807
|
+
]
|
|
6808
|
+
},
|
|
6665
6809
|
{
|
|
6666
6810
|
name: "price_meteora_positions",
|
|
6667
6811
|
discriminator: [
|
|
@@ -13738,6 +13882,7 @@ const MERKLE_DISTRIBUTOR_PROGRAM = new web3_js.PublicKey("DiS3nNjFVMieMgmiQFm6wg
|
|
|
13738
13882
|
const TRANSFER_HOOK_PROGRAM = new web3_js.PublicKey("po1iCYakK3gHCLbuju4wGzFowTMpAJxkqK1iwUqMonY");
|
|
13739
13883
|
const METEORA_DLMM_PROGRAM = new web3_js.PublicKey("LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo");
|
|
13740
13884
|
const KAMINO_LENDING_PROGRAM = new web3_js.PublicKey("KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD");
|
|
13885
|
+
const KAMINO_VAULTS_PROGRAM = new web3_js.PublicKey("KvauGMspG5k6rtzrqqn7WNn3oZdyKqLKwK2XWQ8FLjd");
|
|
13741
13886
|
const KAMINO_FARM_PROGRAM = new web3_js.PublicKey("FarmsPZpWu9i7Kky8tPN37rs2TpmMrAZrC7S7vJa91Hr");
|
|
13742
13887
|
const MEMO_PROGRAM = new web3_js.PublicKey("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr");
|
|
13743
13888
|
/**
|
|
@@ -14681,7 +14826,7 @@ class BaseClient {
|
|
|
14681
14826
|
set statePda(statePda) {
|
|
14682
14827
|
this._statePda = statePda;
|
|
14683
14828
|
}
|
|
14684
|
-
isMainnet() {
|
|
14829
|
+
get isMainnet() {
|
|
14685
14830
|
return this.cluster === ClusterNetwork.Mainnet;
|
|
14686
14831
|
}
|
|
14687
14832
|
isPhantom() {
|
|
@@ -14696,7 +14841,7 @@ class BaseClient {
|
|
|
14696
14841
|
* @returns Metadata of the asset
|
|
14697
14842
|
*/ getAssetMeta(assetMint) {
|
|
14698
14843
|
let assetMeta = ASSETS_MAINNET.get(assetMint);
|
|
14699
|
-
if (!assetMeta && !this.isMainnet
|
|
14844
|
+
if (!assetMeta && !this.isMainnet) {
|
|
14700
14845
|
assetMeta = ASSETS_TESTS.get(assetMint);
|
|
14701
14846
|
}
|
|
14702
14847
|
if (!assetMeta) {
|
|
@@ -15086,9 +15231,9 @@ class BaseClient {
|
|
|
15086
15231
|
if (stateAccount.mints.length > 0) {
|
|
15087
15232
|
const mintPubkey = glamStatePda.equals(this.statePda) ? this.mintPda : getMintPda(glamStatePda, 0, this.program.programId);
|
|
15088
15233
|
const { mint } = await this.fetchMintAndTokenProgram(mintPubkey);
|
|
15089
|
-
return StateModel.fromOnchainAccounts(
|
|
15234
|
+
return StateModel.fromOnchainAccounts(glamStatePda, stateAccount, openfundsMetadataAccount, mint, this.program.programId);
|
|
15090
15235
|
}
|
|
15091
|
-
return StateModel.fromOnchainAccounts(
|
|
15236
|
+
return StateModel.fromOnchainAccounts(glamStatePda, stateAccount, openfundsMetadataAccount, undefined, this.program.programId);
|
|
15092
15237
|
}
|
|
15093
15238
|
/**
|
|
15094
15239
|
* Fetch all glam state models if no filter options provided
|
|
@@ -15308,6 +15453,12 @@ DepositDirection.WITHDRAW = {
|
|
|
15308
15453
|
withdraw: {}
|
|
15309
15454
|
};
|
|
15310
15455
|
class OracleSource {
|
|
15456
|
+
static fromString(name) {
|
|
15457
|
+
const k = name.slice(0, 1).toLowerCase() + name.slice(1);
|
|
15458
|
+
return {
|
|
15459
|
+
[k]: {}
|
|
15460
|
+
};
|
|
15461
|
+
}
|
|
15311
15462
|
static get(n) {
|
|
15312
15463
|
const name = Object.entries(OracleSourceNum).find(([, v])=>v === n)?.[0];
|
|
15313
15464
|
const source = Object.entries(OracleSource).find(([key, _])=>key.toLocaleLowerCase() === name?.toLocaleLowerCase())?.[1];
|
|
@@ -15763,6 +15914,24 @@ const DriftVaultLayout = borsh.struct([
|
|
|
15763
15914
|
// Final padding
|
|
15764
15915
|
borsh.array(borsh.u64(), 3, "padding")
|
|
15765
15916
|
]);
|
|
15917
|
+
borsh.struct([
|
|
15918
|
+
borsh.array(borsh.u8(), 8, "discriminator"),
|
|
15919
|
+
borsh.publicKey("marketPda"),
|
|
15920
|
+
borsh.publicKey("oracle"),
|
|
15921
|
+
borsh.publicKey("mint"),
|
|
15922
|
+
borsh.publicKey("vault"),
|
|
15923
|
+
borsh.array(borsh.u8(), 32, "name"),
|
|
15924
|
+
// Padding for bytes between name and cumulativeDepositInterest
|
|
15925
|
+
borsh.array(borsh.u8(), 464 - 168, "padding1"),
|
|
15926
|
+
borsh.u128("cumulativeDepositInterest"),
|
|
15927
|
+
borsh.u128("cumulativeBorrowInterest"),
|
|
15928
|
+
// Padding for bytes between cumulativeBorrowInterest and decimals
|
|
15929
|
+
borsh.array(borsh.u8(), 680 - 496, "padding2"),
|
|
15930
|
+
borsh.u32("decimals"),
|
|
15931
|
+
borsh.u16("marketIndex"),
|
|
15932
|
+
borsh.u8("padding3"),
|
|
15933
|
+
borsh.u8("oracleSource")
|
|
15934
|
+
]);
|
|
15766
15935
|
|
|
15767
15936
|
function readUnsignedBigInt64LE(buffer, offset) {
|
|
15768
15937
|
return new anchor.BN(buffer.subarray(offset, offset + 8), 10, "le");
|
|
@@ -16223,17 +16392,17 @@ class DriftClient {
|
|
|
16223
16392
|
Buffer.from("drift_state")
|
|
16224
16393
|
], DRIFT_PROGRAM_ID)[0];
|
|
16225
16394
|
}
|
|
16226
|
-
async fetchAndParseSpotMarket(marketIndex) {
|
|
16395
|
+
async fetchAndParseSpotMarket(marketIndex, skipCache = false) {
|
|
16227
16396
|
const markets = await this.fetchAndParseSpotMarkets([
|
|
16228
16397
|
marketIndex
|
|
16229
|
-
]);
|
|
16398
|
+
], skipCache);
|
|
16230
16399
|
if (!markets || markets.length === 0) {
|
|
16231
16400
|
throw new Error(`Spot market not found at index ${marketIndex}`);
|
|
16232
16401
|
}
|
|
16233
16402
|
return markets[0];
|
|
16234
16403
|
}
|
|
16235
|
-
async fetchAndParseSpotMarkets(marketIndexes) {
|
|
16236
|
-
const indexesToFetch = marketIndexes.filter((marketIndex)
|
|
16404
|
+
async fetchAndParseSpotMarkets(marketIndexes, skipCache = false) {
|
|
16405
|
+
const indexesToFetch = marketIndexes.filter((marketIndex)=>skipCache || !this.spotMarkets.has(marketIndex));
|
|
16237
16406
|
if (indexesToFetch.length > 0) {
|
|
16238
16407
|
if (process.env.NODE_ENV === "development") {
|
|
16239
16408
|
console.log("Fetching spot markets:", indexesToFetch);
|
|
@@ -16256,17 +16425,17 @@ class DriftClient {
|
|
|
16256
16425
|
}
|
|
16257
16426
|
return spotMarkets;
|
|
16258
16427
|
}
|
|
16259
|
-
async fetchAndParsePerpMarket(marketIndex) {
|
|
16428
|
+
async fetchAndParsePerpMarket(marketIndex, skipCache = false) {
|
|
16260
16429
|
const markets = await this.fetchAndParsePerpMarkets([
|
|
16261
16430
|
marketIndex
|
|
16262
|
-
]);
|
|
16431
|
+
], skipCache);
|
|
16263
16432
|
if (!markets || markets.length === 0) {
|
|
16264
16433
|
throw new Error(`Perp market not found at index ${marketIndex}`);
|
|
16265
16434
|
}
|
|
16266
16435
|
return markets[0];
|
|
16267
16436
|
}
|
|
16268
|
-
async fetchAndParsePerpMarkets(marketIndexes) {
|
|
16269
|
-
const indexesToFetch = marketIndexes.filter((marketIndex)
|
|
16437
|
+
async fetchAndParsePerpMarkets(marketIndexes, skipCache = false) {
|
|
16438
|
+
const indexesToFetch = marketIndexes.filter((marketIndex)=>skipCache || !this.perpMarkets.has(marketIndex));
|
|
16270
16439
|
if (indexesToFetch.length > 0) {
|
|
16271
16440
|
if (process.env.NODE_ENV === "development") {
|
|
16272
16441
|
console.log("Fetching perp markets:", indexesToFetch);
|
|
@@ -16291,33 +16460,56 @@ class DriftClient {
|
|
|
16291
16460
|
}
|
|
16292
16461
|
return perpMarkets;
|
|
16293
16462
|
}
|
|
16294
|
-
async fetchMarketConfigs() {
|
|
16295
|
-
//
|
|
16296
|
-
|
|
16297
|
-
|
|
16298
|
-
|
|
16299
|
-
|
|
16300
|
-
|
|
16301
|
-
|
|
16302
|
-
|
|
16303
|
-
|
|
16304
|
-
|
|
16305
|
-
|
|
16306
|
-
|
|
16307
|
-
|
|
16308
|
-
|
|
16309
|
-
|
|
16310
|
-
|
|
16311
|
-
|
|
16312
|
-
|
|
16313
|
-
|
|
16314
|
-
|
|
16315
|
-
|
|
16316
|
-
|
|
16317
|
-
|
|
16463
|
+
async fetchMarketConfigs(skipCache = false) {
|
|
16464
|
+
// Attempt to fetch market configs from glam API first
|
|
16465
|
+
const glamApi = process.env.NEXT_PUBLIC_GLAM_API || process.env.GLAM_API;
|
|
16466
|
+
if (glamApi) {
|
|
16467
|
+
const response = await fetch(`${glamApi}/v0/drift/market_configs/`);
|
|
16468
|
+
if (!response.ok) {
|
|
16469
|
+
throw new Error(`Failed to fetch market configs from ${glamApi}: ${response.status}`);
|
|
16470
|
+
}
|
|
16471
|
+
const data = await response.json();
|
|
16472
|
+
const { orderConstants, perp, spot } = data;
|
|
16473
|
+
// Transform perp market from API to `PerpMarket` type
|
|
16474
|
+
const perpMarkets = perp.map((m)=>({
|
|
16475
|
+
name: m.symbol,
|
|
16476
|
+
marketIndex: m.marketIndex,
|
|
16477
|
+
marketPda: new web3_js.PublicKey(m.marketPDA),
|
|
16478
|
+
oracle: new web3_js.PublicKey(m.oracle),
|
|
16479
|
+
oracleSource: OracleSource.fromString(m.oracleSource)
|
|
16480
|
+
}));
|
|
16481
|
+
perpMarkets.forEach((m)=>{
|
|
16482
|
+
this.perpMarkets.set(m.marketIndex, m);
|
|
16483
|
+
});
|
|
16484
|
+
// Transform spot market from API to `SpotMarket` type
|
|
16485
|
+
const spotMarkets = spot.map((m)=>({
|
|
16486
|
+
name: m.symbol,
|
|
16487
|
+
marketIndex: m.marketIndex,
|
|
16488
|
+
marketPda: new web3_js.PublicKey(m.marketPDA),
|
|
16489
|
+
vault: new web3_js.PublicKey(m.vaultPDA),
|
|
16490
|
+
oracle: new web3_js.PublicKey(m.oracle),
|
|
16491
|
+
oracleSource: OracleSource.fromString(m.oracleSource),
|
|
16492
|
+
mint: new web3_js.PublicKey(m.mint),
|
|
16493
|
+
decimals: m.decimals,
|
|
16494
|
+
tokenProgram: new web3_js.PublicKey(m.tokenProgram),
|
|
16495
|
+
cumulativeDepositInterest: new anchor.BN(m.cumulativeDepositInterest),
|
|
16496
|
+
cumulativeBorrowInterest: new anchor.BN(m.cumulativeBorrowInterest)
|
|
16497
|
+
}));
|
|
16498
|
+
spotMarkets.forEach((m)=>{
|
|
16499
|
+
this.spotMarkets.set(m.marketIndex, m);
|
|
16500
|
+
});
|
|
16501
|
+
const marketConfigs = {
|
|
16502
|
+
orderConstants,
|
|
16503
|
+
perpMarkets,
|
|
16504
|
+
spotMarkets
|
|
16505
|
+
};
|
|
16506
|
+
this.marketConfigs = marketConfigs;
|
|
16507
|
+
return marketConfigs;
|
|
16508
|
+
}
|
|
16509
|
+
// If glam API is not available, fetch market configs from RPC
|
|
16318
16510
|
if (!this.marketConfigs) {
|
|
16319
|
-
const perpMarkets = await this.fetchAndParsePerpMarkets(Array.from(Array(100).keys()));
|
|
16320
|
-
const spotMarkets = await this.fetchAndParseSpotMarkets(Array.from(Array(100).keys()));
|
|
16511
|
+
const perpMarkets = await this.fetchAndParsePerpMarkets(Array.from(Array(100).keys()), skipCache);
|
|
16512
|
+
const spotMarkets = await this.fetchAndParseSpotMarkets(Array.from(Array(100).keys()), skipCache);
|
|
16321
16513
|
this.marketConfigs = {
|
|
16322
16514
|
orderConstants: {
|
|
16323
16515
|
perpBaseScale: 9,
|
|
@@ -16329,24 +16521,10 @@ class DriftClient {
|
|
|
16329
16521
|
}
|
|
16330
16522
|
return this.marketConfigs;
|
|
16331
16523
|
}
|
|
16332
|
-
// public async fetchGlamDriftUser(
|
|
16333
|
-
// glamState: PublicKey | string,
|
|
16334
|
-
// subAccountId: number = 0,
|
|
16335
|
-
// ): Promise<GlamDriftUser> {
|
|
16336
|
-
// const vault = this.base.getVaultPda(new PublicKey(glamState));
|
|
16337
|
-
// const response = await fetch(
|
|
16338
|
-
// `https://api.glam.systems/v0/drift/user?authority=${vault.toBase58()}&accountId=${subAccountId}`,
|
|
16339
|
-
// );
|
|
16340
|
-
// const data = await response.json();
|
|
16341
|
-
// if (!data) {
|
|
16342
|
-
// throw new Error("Failed to fetch drift user.");
|
|
16343
|
-
// }
|
|
16344
|
-
// return data as GlamDriftUser;
|
|
16345
|
-
// }
|
|
16346
16524
|
charsToName(chars) {
|
|
16347
16525
|
return String.fromCharCode(...chars).replace(/\0/g, "").trim();
|
|
16348
16526
|
}
|
|
16349
|
-
async fetchDriftUser(subAccountId = 0) {
|
|
16527
|
+
async fetchDriftUser(subAccountId = 0, skipCache = false) {
|
|
16350
16528
|
const { user } = this.getDriftUserPdas(subAccountId);
|
|
16351
16529
|
const accountInfo = await this.base.provider.connection.getAccountInfo(user);
|
|
16352
16530
|
if (!accountInfo) {
|
|
@@ -16354,7 +16532,7 @@ class DriftClient {
|
|
|
16354
16532
|
}
|
|
16355
16533
|
const { delegate, name, spotPositions, marginMode, perpPositions, isMarginTradingEnabled, maxMarginRatio, orders } = decodeUser(accountInfo.data);
|
|
16356
16534
|
// Prefetch market configs
|
|
16357
|
-
const marketConfigs = await this.fetchMarketConfigs();
|
|
16535
|
+
const marketConfigs = await this.fetchMarketConfigs(skipCache);
|
|
16358
16536
|
const spotPositionsExt = await Promise.all(spotPositions.map(async (p)=>{
|
|
16359
16537
|
const { amount, uiAmount } = await this.calcSpotBalance(p.marketIndex, p.scaledBalance, p.balanceType);
|
|
16360
16538
|
const spotMarket = marketConfigs.spotMarkets.find((m)=>m.marketIndex === p.marketIndex);
|
|
@@ -16379,22 +16557,10 @@ class DriftClient {
|
|
|
16379
16557
|
maxMarginRatio
|
|
16380
16558
|
};
|
|
16381
16559
|
}
|
|
16382
|
-
// async getPositions(statePda: PublicKey | string, subAccountId: number = 0) {
|
|
16383
|
-
// const driftUser = await this.fetchDriftUser(
|
|
16384
|
-
// new PublicKey(statePda),
|
|
16385
|
-
// subAccountId,
|
|
16386
|
-
// );
|
|
16387
|
-
// if (!driftUser) {
|
|
16388
|
-
// return { spotPositions: [], perpPositions: [] };
|
|
16389
|
-
// }
|
|
16390
|
-
// const marketConfigs = await this.fetchMarketConfigs();
|
|
16391
|
-
// const { spotPositions, perpPositions } = driftUser;
|
|
16392
|
-
// return { spotPositions, perpPositions };
|
|
16393
|
-
// }
|
|
16394
16560
|
/**
|
|
16395
16561
|
* @deprecated
|
|
16396
|
-
*/ async fetchPolicyConfig(
|
|
16397
|
-
const driftUserAccount =
|
|
16562
|
+
*/ async fetchPolicyConfig(stateModel) {
|
|
16563
|
+
const driftUserAccount = await this.fetchDriftUser();
|
|
16398
16564
|
let delegate = driftUserAccount?.delegate;
|
|
16399
16565
|
if (delegate && delegate.equals(web3_js.PublicKey.default)) {
|
|
16400
16566
|
delegate = undefined;
|
|
@@ -16402,11 +16568,11 @@ class DriftClient {
|
|
|
16402
16568
|
return {
|
|
16403
16569
|
driftAccessControl: delegate ? 0 : 1,
|
|
16404
16570
|
driftDelegatedAccount: delegate || null,
|
|
16405
|
-
driftMarketIndexesPerp:
|
|
16406
|
-
driftOrderTypes:
|
|
16571
|
+
driftMarketIndexesPerp: stateModel?.driftMarketIndexesPerp || [],
|
|
16572
|
+
driftOrderTypes: stateModel?.driftOrderTypes || [],
|
|
16407
16573
|
driftMaxLeverage: driftUserAccount?.maxMarginRatio ? DRIFT_MARGIN_PRECISION / driftUserAccount?.maxMarginRatio : null,
|
|
16408
16574
|
driftEnableSpot: driftUserAccount?.isMarginTradingEnabled || false,
|
|
16409
|
-
driftMarketIndexesSpot:
|
|
16575
|
+
driftMarketIndexesSpot: stateModel?.driftMarketIndexesSpot || []
|
|
16410
16576
|
};
|
|
16411
16577
|
}
|
|
16412
16578
|
async composeRemainingAccounts(subAccountId, marketType, marketIndex) {
|
|
@@ -16501,7 +16667,8 @@ class DriftClient {
|
|
|
16501
16667
|
const glamSigner = txOptions.signer || this.base.getSigner();
|
|
16502
16668
|
const { user } = this.getDriftUserPdas(subAccountId);
|
|
16503
16669
|
// https://github.com/drift-labs/protocol-v2/blob/babed162b08b1fe34e49a81c5aa3e4ec0a88ecdf/programs/drift/src/math/constants.rs#L183-L184
|
|
16504
|
-
|
|
16670
|
+
// 0 means No Limit
|
|
16671
|
+
const marginRatio = maxLeverage === 0 ? 0 : DRIFT_MARGIN_PRECISION / maxLeverage;
|
|
16505
16672
|
return await this.base.program.methods.driftUpdateUserCustomMarginRatio(subAccountId, marginRatio).accounts({
|
|
16506
16673
|
glamState: this.base.statePda,
|
|
16507
16674
|
glamSigner,
|
|
@@ -17525,7 +17692,8 @@ class MarinadeClient {
|
|
|
17525
17692
|
// Fetch stake accounts by withdraw authority
|
|
17526
17693
|
// Filter by state "active" does not work in localnet tests
|
|
17527
17694
|
const stakeAccounts = await getStakeAccountsWithStates(this.base.provider.connection, stakeWithdrawAuthority);
|
|
17528
|
-
const
|
|
17695
|
+
const idx = this.base.cluster === ClusterNetwork.Mainnet ? stakeAccounts.findIndex((s)=>s.state === "active") : 0;
|
|
17696
|
+
const { stakeIndex, validatorIndex } = await this.getIndexes(stakeAccounts[idx], stakeList, validatorList);
|
|
17529
17697
|
const burnMsolFrom = this.base.getVaultAta(MSOL);
|
|
17530
17698
|
const newStake = web3_js.Keypair.generate();
|
|
17531
17699
|
const postInstructions = deactivate ? [
|
|
@@ -17541,7 +17709,7 @@ class MarinadeClient {
|
|
|
17541
17709
|
state: marinadeState.marinadeStateAddress,
|
|
17542
17710
|
validatorList: validatorList.account,
|
|
17543
17711
|
stakeList: stakeList.account,
|
|
17544
|
-
stakeAccount: stakeAccounts[
|
|
17712
|
+
stakeAccount: stakeAccounts[idx].address,
|
|
17545
17713
|
stakeWithdrawAuthority,
|
|
17546
17714
|
stakeDepositAuthority,
|
|
17547
17715
|
treasuryMsolAccount: marinadeState.treasuryMsolAccount,
|
|
@@ -17712,7 +17880,7 @@ class VaultClient {
|
|
|
17712
17880
|
const tx = new web3_js.Transaction().add(splToken.createAssociatedTokenAccountIdempotentInstruction(signer, vaultAta, this.base.vaultPda, asset, tokenProgram), splToken.createTransferCheckedInstruction(signerAta, asset, vaultAta, signer, new anchor.BN(amount).toNumber(), mint.decimals, [], tokenProgram));
|
|
17713
17881
|
return await this.base.intoVersionedTransaction(tx, txOptions);
|
|
17714
17882
|
}
|
|
17715
|
-
async withdrawIxs(asset, amount, txOptions) {
|
|
17883
|
+
async withdrawIxs(asset, amount, txOptions = {}) {
|
|
17716
17884
|
const glamSigner = txOptions.signer || this.base.getSigner();
|
|
17717
17885
|
const { tokenProgram } = await this.base.fetchMintAndTokenProgram(asset);
|
|
17718
17886
|
const signerAta = this.base.getAta(asset, glamSigner, tokenProgram);
|
|
@@ -18641,11 +18809,69 @@ class MintClient {
|
|
|
18641
18809
|
}
|
|
18642
18810
|
}
|
|
18643
18811
|
|
|
18812
|
+
const MAX_RESERVES = 25;
|
|
18813
|
+
const VaultAllocationLayout = borsh.struct([
|
|
18814
|
+
borsh.publicKey("reserve"),
|
|
18815
|
+
borsh.publicKey("ctokenVault"),
|
|
18816
|
+
borsh.u64("targetAllocationWeight"),
|
|
18817
|
+
borsh.u64("tokenAllocationCap"),
|
|
18818
|
+
borsh.u64("ctokenVaultBump"),
|
|
18819
|
+
borsh.array(borsh.u64(), 127, "configPadding"),
|
|
18820
|
+
borsh.u64("ctokenAllocation"),
|
|
18821
|
+
borsh.u64("lastInvestSlot"),
|
|
18822
|
+
borsh.u128("tokenTargetAllocationSf"),
|
|
18823
|
+
borsh.array(borsh.u64(), 128, "statePadding")
|
|
18824
|
+
]);
|
|
18825
|
+
const KVaultStateLayout = borsh.struct([
|
|
18826
|
+
borsh.array(borsh.u8(), 8, "discriminator"),
|
|
18827
|
+
// Admin
|
|
18828
|
+
borsh.publicKey("vaultAdminAuthority"),
|
|
18829
|
+
borsh.publicKey("baseVaultAuthority"),
|
|
18830
|
+
borsh.u64("baseVaultAuthorityBump"),
|
|
18831
|
+
borsh.publicKey("tokenMint"),
|
|
18832
|
+
borsh.u64("tokenMintDecimals"),
|
|
18833
|
+
borsh.publicKey("tokenVault"),
|
|
18834
|
+
borsh.publicKey("tokenProgram"),
|
|
18835
|
+
// shares
|
|
18836
|
+
borsh.publicKey("sharesMint"),
|
|
18837
|
+
borsh.u64("sharesMintDecimals"),
|
|
18838
|
+
// accounting
|
|
18839
|
+
borsh.u64("tokenAvailable"),
|
|
18840
|
+
borsh.u64("sharesIssued"),
|
|
18841
|
+
borsh.u64("availableCrankFunds"),
|
|
18842
|
+
borsh.u64("padding0"),
|
|
18843
|
+
borsh.u64("performanceFeeBps"),
|
|
18844
|
+
borsh.u64("managementFeeBps"),
|
|
18845
|
+
borsh.u64("lastFeeChargeTimestamp"),
|
|
18846
|
+
borsh.u128("prevAumSf"),
|
|
18847
|
+
borsh.u128("pendingFeesSf"),
|
|
18848
|
+
borsh.array(VaultAllocationLayout, MAX_RESERVES, "vaultAllocationStrategy"),
|
|
18849
|
+
borsh.array(borsh.u128(), 256, "padding1"),
|
|
18850
|
+
// General config
|
|
18851
|
+
borsh.u64("minDepositAmount"),
|
|
18852
|
+
borsh.u64("minWithdrawAmount"),
|
|
18853
|
+
borsh.u64("minInvestAmount"),
|
|
18854
|
+
borsh.u64("minInvestDelaySlots"),
|
|
18855
|
+
borsh.u64("crankFundFeePerReserve"),
|
|
18856
|
+
borsh.publicKey("pendingAdmin"),
|
|
18857
|
+
borsh.u128("cumulativeEarnedInterestSf"),
|
|
18858
|
+
borsh.u128("cumulativeMgmtFeesSf"),
|
|
18859
|
+
borsh.u128("cumulativePerfFeesSf"),
|
|
18860
|
+
borsh.array(borsh.u8(), 40, "name"),
|
|
18861
|
+
borsh.publicKey("vaultLookupTable"),
|
|
18862
|
+
borsh.publicKey("vaultFarm"),
|
|
18863
|
+
borsh.u64("creationTimestamp"),
|
|
18864
|
+
borsh.u64("padding2"),
|
|
18865
|
+
borsh.publicKey("allocationAdmin"),
|
|
18866
|
+
borsh.array(borsh.u128(), 242, "padding3")
|
|
18867
|
+
]);
|
|
18868
|
+
|
|
18644
18869
|
const LOOKUP_TABLE = new web3_js.PublicKey("284iwGtA9X9aLy3KsyV8uT2pXLARhYbiSi5SiM2g47M2");
|
|
18645
18870
|
const DEFAULT_OBLIGATION_ARGS = {
|
|
18646
18871
|
tag: 0,
|
|
18647
18872
|
id: 0
|
|
18648
18873
|
};
|
|
18874
|
+
const EVENT_AUTHORITY$1 = new web3_js.PublicKey("24tHwQyJJ9akVXxnvkekGfAoeUJXXS7mE6kQNioNySsK");
|
|
18649
18875
|
function refreshObligation(accounts, programId = KAMINO_LENDING_PROGRAM) {
|
|
18650
18876
|
const keys = [
|
|
18651
18877
|
{
|
|
@@ -19044,7 +19270,7 @@ class KaminoLendingClient {
|
|
|
19044
19270
|
/**
|
|
19045
19271
|
* Fetches and parses an obligation account
|
|
19046
19272
|
*/ async fetchAndParseObligation(obligation) {
|
|
19047
|
-
const cached = this.obligations.get(obligation);
|
|
19273
|
+
const cached = this.obligations.get(obligation.toBase58());
|
|
19048
19274
|
if (cached) {
|
|
19049
19275
|
return cached;
|
|
19050
19276
|
}
|
|
@@ -19058,7 +19284,7 @@ class KaminoLendingClient {
|
|
|
19058
19284
|
};
|
|
19059
19285
|
}
|
|
19060
19286
|
const parsedObligation = this.parseObligation(obligation, obligationAccount.data);
|
|
19061
|
-
this.obligations.set(obligation, parsedObligation);
|
|
19287
|
+
this.obligations.set(obligation.toBase58(), parsedObligation);
|
|
19062
19288
|
return parsedObligation;
|
|
19063
19289
|
}
|
|
19064
19290
|
parseReserveAccount(reserve, data) {
|
|
@@ -19068,6 +19294,7 @@ class KaminoLendingClient {
|
|
|
19068
19294
|
const liquidityMint = new web3_js.PublicKey(data.subarray(128, 160));
|
|
19069
19295
|
return {
|
|
19070
19296
|
address: reserve,
|
|
19297
|
+
market,
|
|
19071
19298
|
farmCollateral: farmCollateral.equals(web3_js.PublicKey.default) ? null : farmCollateral,
|
|
19072
19299
|
farmDebt: farmDebt.equals(web3_js.PublicKey.default) ? null : farmDebt,
|
|
19073
19300
|
liquidityMint,
|
|
@@ -19075,16 +19302,28 @@ class KaminoLendingClient {
|
|
|
19075
19302
|
};
|
|
19076
19303
|
}
|
|
19077
19304
|
async fetchAndParseReserves(reserves) {
|
|
19078
|
-
|
|
19079
|
-
|
|
19080
|
-
|
|
19081
|
-
|
|
19082
|
-
|
|
19305
|
+
const requestReservesSet = new Set(reserves.map((r)=>r.toBase58()));
|
|
19306
|
+
const cachedReservesSet = new Set(this.reserves.keys());
|
|
19307
|
+
// If all requested reserves are cached, return data from cache
|
|
19308
|
+
if ([
|
|
19309
|
+
...requestReservesSet
|
|
19310
|
+
].every((r)=>cachedReservesSet.has(r))) {
|
|
19311
|
+
return Array.from(this.reserves.values()).filter((r)=>requestReservesSet.has(r.address.toBase58()));
|
|
19312
|
+
}
|
|
19313
|
+
// Only fetch reserves that are not cached
|
|
19314
|
+
const reservesToFetch = [
|
|
19315
|
+
...requestReservesSet
|
|
19316
|
+
].filter((r)=>!cachedReservesSet.has(r)).map((r)=>new web3_js.PublicKey(r));
|
|
19317
|
+
if (process.env.NODE_ENV !== "production") {
|
|
19318
|
+
console.log("Fetching reserves:", reservesToFetch.map((r)=>r.toBase58()));
|
|
19319
|
+
}
|
|
19320
|
+
const reserveAccounts = await this.base.provider.connection.getMultipleAccountsInfo(reservesToFetch);
|
|
19321
|
+
if (reserveAccounts.some((a)=>!a)) {
|
|
19083
19322
|
throw new Error("Not all reserves can be found");
|
|
19084
19323
|
}
|
|
19085
|
-
return reserveAccounts.
|
|
19324
|
+
return reserveAccounts.map((account, i)=>{
|
|
19086
19325
|
const parsedReserve = this.parseReserveAccount(reserves[i], account.data);
|
|
19087
|
-
this.reserves.set(reserves[i], parsedReserve);
|
|
19326
|
+
this.reserves.set(reserves[i].toBase58(), parsedReserve);
|
|
19088
19327
|
return parsedReserve;
|
|
19089
19328
|
});
|
|
19090
19329
|
}
|
|
@@ -19112,7 +19351,7 @@ class KaminoLendingClient {
|
|
|
19112
19351
|
throw new Error("Reserve not found");
|
|
19113
19352
|
}
|
|
19114
19353
|
const parsedReserve = this.parseReserveAccount(accounts[0].pubkey, accounts[0].account.data);
|
|
19115
|
-
this.reserves.set(accounts[0].pubkey, parsedReserve);
|
|
19354
|
+
this.reserves.set(accounts[0].pubkey.toBase58(), parsedReserve);
|
|
19116
19355
|
return parsedReserve;
|
|
19117
19356
|
}
|
|
19118
19357
|
/**
|
|
@@ -19142,7 +19381,7 @@ class KaminoLendingClient {
|
|
|
19142
19381
|
// Parse obligations and cache them
|
|
19143
19382
|
return accounts.map((a)=>{
|
|
19144
19383
|
const parsedObligation = this.parseObligation(a.pubkey, a.account.data);
|
|
19145
|
-
this.obligations.set(a.pubkey, parsedObligation);
|
|
19384
|
+
this.obligations.set(a.pubkey.toBase58(), parsedObligation);
|
|
19146
19385
|
return parsedObligation;
|
|
19147
19386
|
});
|
|
19148
19387
|
}
|
|
@@ -19673,6 +19912,160 @@ class KaminoFarmClient {
|
|
|
19673
19912
|
], KAMINO_FARM_PROGRAM)[0];
|
|
19674
19913
|
}
|
|
19675
19914
|
}
|
|
19915
|
+
class KaminoVaultsClient {
|
|
19916
|
+
async deposit(vault, amount, txOptions = {}) {
|
|
19917
|
+
const tx = await this.depositTx(vault, amount, txOptions);
|
|
19918
|
+
return await this.base.sendAndConfirm(tx);
|
|
19919
|
+
}
|
|
19920
|
+
async withdraw(vault, amount, txOptions = {}) {
|
|
19921
|
+
const tx = await this.withdrawTx(vault, amount, txOptions);
|
|
19922
|
+
return await this.base.sendAndConfirm(tx);
|
|
19923
|
+
}
|
|
19924
|
+
async findAndParseKaminoVaults() {
|
|
19925
|
+
const accounts = await this.base.provider.connection.getProgramAccounts(KAMINO_VAULTS_PROGRAM, {
|
|
19926
|
+
filters: [
|
|
19927
|
+
{
|
|
19928
|
+
dataSize: 62552
|
|
19929
|
+
},
|
|
19930
|
+
{
|
|
19931
|
+
memcmp: {
|
|
19932
|
+
offset: 0,
|
|
19933
|
+
bytes: "5MRSpWLS65g=",
|
|
19934
|
+
encoding: "base64"
|
|
19935
|
+
}
|
|
19936
|
+
}
|
|
19937
|
+
]
|
|
19938
|
+
});
|
|
19939
|
+
if (accounts.length === 0) {
|
|
19940
|
+
throw new Error("Kamino vaults not found");
|
|
19941
|
+
}
|
|
19942
|
+
return accounts.map((a)=>{
|
|
19943
|
+
const vaultState = KVaultStateLayout.decode(a.account.data);
|
|
19944
|
+
this.vaultStates.set(a.pubkey.toBase58(), vaultState);
|
|
19945
|
+
this.shareMintToVaultPdaMap.set(vaultState.sharesMint.toBase58(), a.pubkey);
|
|
19946
|
+
return vaultState;
|
|
19947
|
+
});
|
|
19948
|
+
}
|
|
19949
|
+
async getVaultPdasByShareMints(mints) {
|
|
19950
|
+
if (this.vaultStates.size === 0) {
|
|
19951
|
+
await this.findAndParseKaminoVaults();
|
|
19952
|
+
}
|
|
19953
|
+
return mints.map((mint)=>this.shareMintToVaultPdaMap.get(mint.toBase58()));
|
|
19954
|
+
}
|
|
19955
|
+
async fetchAndParseVaultState(vault) {
|
|
19956
|
+
const vaultAccount = await this.base.provider.connection.getAccountInfo(vault);
|
|
19957
|
+
if (!vaultAccount) {
|
|
19958
|
+
throw new Error(`Kamino vault account not found:, ${vault}`);
|
|
19959
|
+
}
|
|
19960
|
+
const vaultState = KVaultStateLayout.decode(vaultAccount.data);
|
|
19961
|
+
this.vaultStates.set(vault.toBase58(), vaultState);
|
|
19962
|
+
this.shareMintToVaultPdaMap.set(vaultState.sharesMint.toBase58(), vault);
|
|
19963
|
+
return vaultState;
|
|
19964
|
+
}
|
|
19965
|
+
async composeRemainingAccounts(allocationStrategies) {
|
|
19966
|
+
// For each allocation get reserve and market pubkeys
|
|
19967
|
+
const reserves = allocationStrategies.map((strategy)=>strategy.reserve);
|
|
19968
|
+
const parsedReserves = await this.kaminoLending.fetchAndParseReserves(reserves);
|
|
19969
|
+
const reserveMetas = reserves.map((pubkey)=>({
|
|
19970
|
+
pubkey,
|
|
19971
|
+
isSigner: false,
|
|
19972
|
+
isWritable: true
|
|
19973
|
+
}));
|
|
19974
|
+
const marketMetas = parsedReserves.map(({ market })=>({
|
|
19975
|
+
pubkey: market,
|
|
19976
|
+
isSigner: false,
|
|
19977
|
+
isWritable: false
|
|
19978
|
+
}));
|
|
19979
|
+
return [
|
|
19980
|
+
...reserveMetas,
|
|
19981
|
+
...marketMetas
|
|
19982
|
+
];
|
|
19983
|
+
}
|
|
19984
|
+
async depositTx(vault, amount, txOptions = {}) {
|
|
19985
|
+
const glamSigner = txOptions.signer || this.base.getSigner();
|
|
19986
|
+
const vaultState = await this.fetchAndParseVaultState(vault);
|
|
19987
|
+
const amountBN = new anchor.BN(amount * 10 ** vaultState.tokenMintDecimals.toNumber());
|
|
19988
|
+
const { tokenProgram: sharesTokenProgram } = await this.base.fetchMintAndTokenProgram(vaultState.sharesMint);
|
|
19989
|
+
const userTokenAta = this.base.getVaultAta(vaultState.tokenMint, vaultState.tokenProgram);
|
|
19990
|
+
const userSharesAta = this.base.getVaultAta(vaultState.sharesMint, sharesTokenProgram);
|
|
19991
|
+
// Create user shares ata
|
|
19992
|
+
const preInstructions = [
|
|
19993
|
+
splToken.createAssociatedTokenAccountIdempotentInstruction(glamSigner, userSharesAta, this.base.vaultPda, vaultState.sharesMint, sharesTokenProgram)
|
|
19994
|
+
];
|
|
19995
|
+
// Remaining accounts, skip empty allocation strategies
|
|
19996
|
+
const remainingAccounts = await this.composeRemainingAccounts(vaultState.vaultAllocationStrategy.filter(({ reserve })=>!reserve.equals(web3_js.PublicKey.default)));
|
|
19997
|
+
const tx = await this.base.program.methods.kaminoVaultsDeposit(amountBN).accounts({
|
|
19998
|
+
glamState: this.base.statePda,
|
|
19999
|
+
glamSigner,
|
|
20000
|
+
vaultState: vault,
|
|
20001
|
+
tokenVault: vaultState.tokenVault,
|
|
20002
|
+
tokenMint: vaultState.tokenMint,
|
|
20003
|
+
baseVaultAuthority: vaultState.baseVaultAuthority,
|
|
20004
|
+
sharesMint: vaultState.sharesMint,
|
|
20005
|
+
userTokenAta,
|
|
20006
|
+
userSharesAta,
|
|
20007
|
+
klendProgram: KAMINO_LENDING_PROGRAM,
|
|
20008
|
+
tokenProgram: vaultState.tokenProgram,
|
|
20009
|
+
sharesTokenProgram,
|
|
20010
|
+
eventAuthority: EVENT_AUTHORITY$1,
|
|
20011
|
+
program: KAMINO_VAULTS_PROGRAM
|
|
20012
|
+
}).remainingAccounts(remainingAccounts).preInstructions(preInstructions).transaction();
|
|
20013
|
+
const vTx = await this.base.intoVersionedTransaction(tx, txOptions);
|
|
20014
|
+
return vTx;
|
|
20015
|
+
}
|
|
20016
|
+
async withdrawTx(vault, amount, txOptions = {}) {
|
|
20017
|
+
const glamSigner = txOptions.signer || this.base.getSigner();
|
|
20018
|
+
const vaultState = await this.fetchAndParseVaultState(vault);
|
|
20019
|
+
const userTokenAta = this.base.getVaultAta(vaultState.tokenMint, vaultState.tokenProgram);
|
|
20020
|
+
const { tokenProgram: sharesTokenProgram } = await this.base.fetchMintAndTokenProgram(vaultState.sharesMint);
|
|
20021
|
+
const userSharesAta = this.base.getVaultAta(vaultState.sharesMint, sharesTokenProgram);
|
|
20022
|
+
const amountBN = new anchor.BN(amount * 10 ** vaultState.sharesMintDecimals.toNumber());
|
|
20023
|
+
const reserves = vaultState.vaultAllocationStrategy.filter(({ reserve })=>!reserve.equals(web3_js.PublicKey.default));
|
|
20024
|
+
// Withdraw from the first reserve when kvault does not have enough liquidity
|
|
20025
|
+
const idx = 0;
|
|
20026
|
+
const withdrawReserve = (await this.kaminoLending.fetchAndParseReserves(reserves.map((r)=>r.reserve)))[idx];
|
|
20027
|
+
const vaultCollateralTokenVault = vaultState.vaultAllocationStrategy[idx].ctokenVault;
|
|
20028
|
+
const remainingAccounts = await this.composeRemainingAccounts(reserves);
|
|
20029
|
+
const preInstructions = [
|
|
20030
|
+
splToken.createAssociatedTokenAccountIdempotentInstruction(glamSigner, userTokenAta, this.base.vaultPda, vaultState.tokenMint, vaultState.tokenProgram)
|
|
20031
|
+
];
|
|
20032
|
+
const tx = await this.base.program.methods.kaminoVaultsWithdraw(amountBN).accounts({
|
|
20033
|
+
glamState: this.base.statePda,
|
|
20034
|
+
glamSigner,
|
|
20035
|
+
withdrawFromAvailableVaultState: vault,
|
|
20036
|
+
withdrawFromAvailableTokenVault: vaultState.tokenVault,
|
|
20037
|
+
withdrawFromAvailableBaseVaultAuthority: vaultState.baseVaultAuthority,
|
|
20038
|
+
withdrawFromAvailableUserTokenAta: userTokenAta,
|
|
20039
|
+
withdrawFromAvailableTokenMint: vaultState.tokenMint,
|
|
20040
|
+
withdrawFromAvailableUserSharesAta: userSharesAta,
|
|
20041
|
+
withdrawFromAvailableSharesMint: vaultState.sharesMint,
|
|
20042
|
+
withdrawFromAvailableTokenProgram: vaultState.tokenProgram,
|
|
20043
|
+
withdrawFromAvailableSharesTokenProgram: sharesTokenProgram,
|
|
20044
|
+
withdrawFromAvailableKlendProgram: KAMINO_LENDING_PROGRAM,
|
|
20045
|
+
withdrawFromAvailableEventAuthority: EVENT_AUTHORITY$1,
|
|
20046
|
+
withdrawFromAvailableProgram: KAMINO_VAULTS_PROGRAM,
|
|
20047
|
+
withdrawFromReserveVaultState: vault,
|
|
20048
|
+
withdrawFromReserveReserve: withdrawReserve.address,
|
|
20049
|
+
withdrawFromReserveCtokenVault: vaultCollateralTokenVault,
|
|
20050
|
+
withdrawFromReserveLendingMarket: withdrawReserve.market,
|
|
20051
|
+
withdrawFromReserveLendingMarketAuthority: this.kaminoLending.getMarketAuthority(withdrawReserve.market),
|
|
20052
|
+
withdrawFromReserveReserveLiquiditySupply: withdrawReserve.liquiditySupplyVault,
|
|
20053
|
+
withdrawFromReserveReserveCollateralMint: withdrawReserve.collateralMint,
|
|
20054
|
+
withdrawFromReserveReserveCollateralTokenProgram: splToken.TOKEN_PROGRAM_ID,
|
|
20055
|
+
withdrawFromReserveInstructionSysvarAccount: web3_js.SYSVAR_INSTRUCTIONS_PUBKEY,
|
|
20056
|
+
eventAuthority: EVENT_AUTHORITY$1,
|
|
20057
|
+
program: KAMINO_VAULTS_PROGRAM
|
|
20058
|
+
}).remainingAccounts(remainingAccounts).preInstructions(preInstructions).transaction();
|
|
20059
|
+
const vTx = await this.base.intoVersionedTransaction(tx, txOptions);
|
|
20060
|
+
return vTx;
|
|
20061
|
+
}
|
|
20062
|
+
constructor(base, kaminoLending){
|
|
20063
|
+
this.base = base;
|
|
20064
|
+
this.kaminoLending = kaminoLending;
|
|
20065
|
+
this.vaultStates = new Map();
|
|
20066
|
+
this.shareMintToVaultPdaMap = new Map();
|
|
20067
|
+
}
|
|
20068
|
+
}
|
|
19676
20069
|
|
|
19677
20070
|
// Pubkey::find_program_address(&[b"__event_authority"], &dlmm_interface::ID)
|
|
19678
20071
|
const EVENT_AUTHORITY = new web3_js.PublicKey("D1ZN9Wj1fRSUQfCjhvnu1hqDMT7hzjzBBpi12nVniYD6");
|
|
@@ -20171,6 +20564,46 @@ class PriceClient {
|
|
|
20171
20564
|
}).remainingAccounts(remainingAccounts).instruction();
|
|
20172
20565
|
return priceIx;
|
|
20173
20566
|
}
|
|
20567
|
+
async priceKaminoVaultSharesIx(priceDenom) {
|
|
20568
|
+
const allKvaultStates = await this.kvaults.findAndParseKaminoVaults();
|
|
20569
|
+
const allKvaultMints = allKvaultStates.map((kvault)=>kvault.sharesMint);
|
|
20570
|
+
// All share token accounts GLAM vault could possibly hold
|
|
20571
|
+
const possibleShareAtas = allKvaultMints.map((mint)=>this.base.getVaultAta(mint));
|
|
20572
|
+
const possibleShareAtaAccountsInfo = await this.base.provider.connection.getMultipleAccountsInfo(possibleShareAtas);
|
|
20573
|
+
const shareAtas = [];
|
|
20574
|
+
const shareMints = [];
|
|
20575
|
+
const kvaultStates = [];
|
|
20576
|
+
possibleShareAtaAccountsInfo.forEach((info, i)=>{
|
|
20577
|
+
if (info !== null) {
|
|
20578
|
+
shareAtas.push(possibleShareAtas[i]);
|
|
20579
|
+
shareMints.push(allKvaultMints[i]);
|
|
20580
|
+
kvaultStates.push(allKvaultStates[i]);
|
|
20581
|
+
}
|
|
20582
|
+
});
|
|
20583
|
+
const kvaultPdas = await this.kvaults.getVaultPdasByShareMints(shareMints);
|
|
20584
|
+
const remainingAccounts = (await Promise.all(kvaultStates.map((kvault)=>{
|
|
20585
|
+
return this.kvaults.composeRemainingAccounts(kvault.vaultAllocationStrategy.filter((alloc)=>!alloc.reserve.equals(web3_js.PublicKey.default)));
|
|
20586
|
+
}))).flat();
|
|
20587
|
+
[
|
|
20588
|
+
...kvaultPdas,
|
|
20589
|
+
...shareAtas
|
|
20590
|
+
].map((pubkey)=>{
|
|
20591
|
+
remainingAccounts.unshift({
|
|
20592
|
+
pubkey: pubkey,
|
|
20593
|
+
isSigner: false,
|
|
20594
|
+
isWritable: false
|
|
20595
|
+
});
|
|
20596
|
+
});
|
|
20597
|
+
const priceIx = await this.base.program.methods.priceKaminoVaultShares(priceDenom).accounts({
|
|
20598
|
+
glamState: this.base.statePda,
|
|
20599
|
+
solOracle: SOL_ORACLE,
|
|
20600
|
+
pythOracle: null,
|
|
20601
|
+
switchboardPriceOracle: null,
|
|
20602
|
+
switchboardTwapOracle: null,
|
|
20603
|
+
scopePrices: KAMINO_SCOPE_PRICES
|
|
20604
|
+
}).remainingAccounts(remainingAccounts).instruction();
|
|
20605
|
+
return priceIx;
|
|
20606
|
+
}
|
|
20174
20607
|
/**
|
|
20175
20608
|
* Returns an instruction that prices the all Drift users (aka sub-accounts) controlled by the GLAM vault.
|
|
20176
20609
|
* These Drift users must share the same user_stats that's also controlled by the GLAM vault.
|
|
@@ -20204,7 +20637,7 @@ class PriceClient {
|
|
|
20204
20637
|
* Returns an instruction that prices a drift vault depositor.
|
|
20205
20638
|
* If there are no vault depositor accounts, returns null.
|
|
20206
20639
|
*/ async priceDriftVaultDepositorsIx(priceDenom) {
|
|
20207
|
-
const parsedVaultDepositors = await this.
|
|
20640
|
+
const parsedVaultDepositors = await this.dvaults.findAndParseVaultDepositors();
|
|
20208
20641
|
if (parsedVaultDepositors.length === 0) {
|
|
20209
20642
|
return null;
|
|
20210
20643
|
}
|
|
@@ -20219,9 +20652,9 @@ class PriceClient {
|
|
|
20219
20652
|
for (const depositor of parsedVaultDepositors){
|
|
20220
20653
|
remainingAccountsKeys.add(depositor.address.toBase58());
|
|
20221
20654
|
remainingAccountsKeys.add(depositor.driftVault.toBase58());
|
|
20222
|
-
const { user: driftUser } = await this.
|
|
20655
|
+
const { user: driftUser } = await this.dvaults.parseDriftVault(depositor.driftVault);
|
|
20223
20656
|
remainingAccountsKeys.add(driftUser.toBase58());
|
|
20224
|
-
const markets_and_oracles = (await this.
|
|
20657
|
+
const markets_and_oracles = (await this.dvaults.composeRemainingAccounts(driftUser)).map((a)=>a.pubkey.toBase58());
|
|
20225
20658
|
for (const k of markets_and_oracles){
|
|
20226
20659
|
remainingAccountsKeys.add(k);
|
|
20227
20660
|
}
|
|
@@ -20310,11 +20743,12 @@ class PriceClient {
|
|
|
20310
20743
|
priceDriftVaultDepositorsIx
|
|
20311
20744
|
].filter((ix)=>ix !== null);
|
|
20312
20745
|
}
|
|
20313
|
-
constructor(base, klend, drift,
|
|
20746
|
+
constructor(base, klend, kvaults, drift, dvaults){
|
|
20314
20747
|
this.base = base;
|
|
20315
20748
|
this.klend = klend;
|
|
20749
|
+
this.kvaults = kvaults;
|
|
20316
20750
|
this.drift = drift;
|
|
20317
|
-
this.
|
|
20751
|
+
this.dvaults = dvaults;
|
|
20318
20752
|
this.remainingAccountsForPricingMeteora = async ()=>{
|
|
20319
20753
|
const positions = await fetchMeteoraPositions(this.base.provider.connection, this.base.vaultPda);
|
|
20320
20754
|
let chunks = await Promise.all(positions.map(async (pubkey)=>{
|
|
@@ -20429,7 +20863,7 @@ class PriceClient {
|
|
|
20429
20863
|
}
|
|
20430
20864
|
get price() {
|
|
20431
20865
|
if (!this._price) {
|
|
20432
|
-
this._price = new PriceClient(this, this.kaminoLending, this.drift, this.driftVaults);
|
|
20866
|
+
this._price = new PriceClient(this, this.kaminoLending, this.kaminoVaults, this.drift, this.driftVaults);
|
|
20433
20867
|
}
|
|
20434
20868
|
return this._price;
|
|
20435
20869
|
}
|
|
@@ -20457,6 +20891,12 @@ class PriceClient {
|
|
|
20457
20891
|
}
|
|
20458
20892
|
return this._kaminoFarm;
|
|
20459
20893
|
}
|
|
20894
|
+
get kaminoVaults() {
|
|
20895
|
+
if (!this._kaminoVaults) {
|
|
20896
|
+
this._kaminoVaults = new KaminoVaultsClient(this, this.kaminoLending);
|
|
20897
|
+
}
|
|
20898
|
+
return this._kaminoVaults;
|
|
20899
|
+
}
|
|
20460
20900
|
get meteoraDlmm() {
|
|
20461
20901
|
if (!this._meteoraDlmm) {
|
|
20462
20902
|
this._meteoraDlmm = new MeteoraDlmmClient(this);
|
|
@@ -20582,6 +21022,7 @@ exports.KAMINO_FARM_PROGRAM = KAMINO_FARM_PROGRAM;
|
|
|
20582
21022
|
exports.KAMINO_LENDING_PROGRAM = KAMINO_LENDING_PROGRAM;
|
|
20583
21023
|
exports.KAMINO_OBTRIGATION_SIZE = KAMINO_OBTRIGATION_SIZE;
|
|
20584
21024
|
exports.KAMINO_SCOPE_PRICES = KAMINO_SCOPE_PRICES;
|
|
21025
|
+
exports.KAMINO_VAULTS_PROGRAM = KAMINO_VAULTS_PROGRAM;
|
|
20585
21026
|
exports.LPAction = LPAction;
|
|
20586
21027
|
exports.LiquidationType = LiquidationType;
|
|
20587
21028
|
exports.MARINADE_NATIVE_STAKE_AUTHORITY = MARINADE_NATIVE_STAKE_AUTHORITY;
|