@kamino-finance/klend-sdk 7.0.11 → 7.0.12
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/dist/classes/manager.d.ts.map +1 -1
- package/dist/classes/manager.js +13 -5
- package/dist/classes/manager.js.map +1 -1
- package/dist/classes/market.d.ts +1 -1
- package/dist/classes/market.d.ts.map +1 -1
- package/dist/classes/market.js +10 -4
- package/dist/classes/market.js.map +1 -1
- package/dist/classes/reserve.d.ts.map +1 -1
- package/dist/classes/reserve.js +1 -1
- package/dist/classes/reserve.js.map +1 -1
- package/dist/classes/vault.d.ts.map +1 -1
- package/dist/classes/vault.js +17 -3
- package/dist/classes/vault.js.map +1 -1
- package/dist/utils/oracle.d.ts +3 -2
- package/dist/utils/oracle.d.ts.map +1 -1
- package/dist/utils/oracle.js +5 -3
- package/dist/utils/oracle.js.map +1 -1
- package/package.json +1 -1
- package/src/classes/manager.ts +15 -7
- package/src/classes/market.ts +14 -8
- package/src/classes/reserve.ts +5 -1
- package/src/classes/vault.ts +17 -5
- package/src/utils/oracle.ts +14 -6
package/src/classes/market.ts
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
Slot,
|
|
18
18
|
} from '@solana/kit';
|
|
19
19
|
import { KaminoObligation } from './obligation';
|
|
20
|
-
import { KaminoReserve, KaminoReserveRpcApi } from './reserve';
|
|
20
|
+
import { KaminoReserve, KaminoReserveRpcApi, ReserveWithAddress } from './reserve';
|
|
21
21
|
import { LendingMarket, Obligation, ReferrerTokenState, Reserve, UserMetadata } from '../@codegen/klend/accounts';
|
|
22
22
|
import {
|
|
23
23
|
AllOracleAccounts,
|
|
@@ -446,13 +446,13 @@ export class KaminoMarket {
|
|
|
446
446
|
/**
|
|
447
447
|
* @returns The max borrowable amount for leverage positions
|
|
448
448
|
*/
|
|
449
|
-
|
|
449
|
+
getMaxLeverageBorrowableAmount(
|
|
450
450
|
collReserve: KaminoReserve,
|
|
451
451
|
debtReserve: KaminoReserve,
|
|
452
452
|
slot: Slot,
|
|
453
453
|
requestElevationGroup: boolean,
|
|
454
454
|
obligation?: KaminoObligation
|
|
455
|
-
):
|
|
455
|
+
): Decimal {
|
|
456
456
|
return obligation
|
|
457
457
|
? obligation.getMaxBorrowAmount(this, debtReserve.getLiquidityMint(), slot, requestElevationGroup)
|
|
458
458
|
: debtReserve.getMaxBorrowAmountWithCollReserve(this, collReserve, slot);
|
|
@@ -463,7 +463,7 @@ export class KaminoMarket {
|
|
|
463
463
|
const reserveAccounts = await this.rpc
|
|
464
464
|
.getMultipleAccounts(addresses, { commitment: 'processed', encoding: 'base64' })
|
|
465
465
|
.send();
|
|
466
|
-
const deserializedReserves = reserveAccounts.value.map((reserve, i) => {
|
|
466
|
+
const deserializedReserves: ReserveWithAddress[] = reserveAccounts.value.map((reserve, i) => {
|
|
467
467
|
if (reserve === null) {
|
|
468
468
|
// maybe reuse old here
|
|
469
469
|
throw new Error(`Reserve account ${addresses[i]} was not found`);
|
|
@@ -472,7 +472,10 @@ export class KaminoMarket {
|
|
|
472
472
|
if (!reserveAccount) {
|
|
473
473
|
throw Error(`Could not parse reserve ${addresses[i]}`);
|
|
474
474
|
}
|
|
475
|
-
return
|
|
475
|
+
return {
|
|
476
|
+
address: addresses[i],
|
|
477
|
+
state: reserveAccount,
|
|
478
|
+
};
|
|
476
479
|
});
|
|
477
480
|
const reservesAndOracles = await getTokenOracleData(this.getRpc(), deserializedReserves, oracleAccounts);
|
|
478
481
|
const kaminoReserves = new Map<Address, KaminoReserve>();
|
|
@@ -1594,7 +1597,7 @@ export async function getReservesForMarket(
|
|
|
1594
1597
|
encoding: 'base64',
|
|
1595
1598
|
})
|
|
1596
1599
|
.send();
|
|
1597
|
-
const deserializedReserves = reserves.map((reserve) => {
|
|
1600
|
+
const deserializedReserves: ReserveWithAddress[] = reserves.map((reserve) => {
|
|
1598
1601
|
if (reserve.account === null) {
|
|
1599
1602
|
throw new Error(`Reserve account ${reserve.pubkey} does not exist`);
|
|
1600
1603
|
}
|
|
@@ -1604,7 +1607,10 @@ export async function getReservesForMarket(
|
|
|
1604
1607
|
if (!reserveAccount) {
|
|
1605
1608
|
throw Error(`Could not parse reserve ${reserve.pubkey}`);
|
|
1606
1609
|
}
|
|
1607
|
-
return
|
|
1610
|
+
return {
|
|
1611
|
+
address: reserve.pubkey,
|
|
1612
|
+
state: reserveAccount,
|
|
1613
|
+
};
|
|
1608
1614
|
});
|
|
1609
1615
|
const reservesAndOracles = await getTokenOracleData(rpc, deserializedReserves, oracleAccounts);
|
|
1610
1616
|
const reservesByAddress = new Map<Address, KaminoReserve>();
|
|
@@ -1630,7 +1636,7 @@ export async function getSingleReserve(
|
|
|
1630
1636
|
if (reserve === null) {
|
|
1631
1637
|
throw new Error(`Reserve account ${reservePk} does not exist`);
|
|
1632
1638
|
}
|
|
1633
|
-
const reservesAndOracles = await getTokenOracleData(rpc, [reserve], oracleAccounts);
|
|
1639
|
+
const reservesAndOracles = await getTokenOracleData(rpc, [{ address: reservePk, state: reserve }], oracleAccounts);
|
|
1634
1640
|
const [, oracle] = reservesAndOracles[0];
|
|
1635
1641
|
|
|
1636
1642
|
if (!oracle) {
|
package/src/classes/reserve.ts
CHANGED
|
@@ -112,7 +112,11 @@ export class KaminoReserve {
|
|
|
112
112
|
throw new Error(`Reserve account ${address} does not exist`);
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
const tokenOracleDataWithReserve = await getTokenOracleData(
|
|
115
|
+
const tokenOracleDataWithReserve = await getTokenOracleData(
|
|
116
|
+
rpc,
|
|
117
|
+
[{ address: address, state: reserve }],
|
|
118
|
+
oracleAccounts
|
|
119
|
+
);
|
|
116
120
|
if (!tokenOracleDataWithReserve[0]) {
|
|
117
121
|
throw new Error('Token oracle data not found');
|
|
118
122
|
}
|
package/src/classes/vault.ts
CHANGED
|
@@ -2386,7 +2386,10 @@ export class KaminoVaultClient {
|
|
|
2386
2386
|
if (!reserveAccount) {
|
|
2387
2387
|
throw Error(`Could not parse reserve ${vaultReservesAddresses[i]}`);
|
|
2388
2388
|
}
|
|
2389
|
-
return
|
|
2389
|
+
return {
|
|
2390
|
+
address: vaultReservesAddresses[i],
|
|
2391
|
+
state: reserveAccount,
|
|
2392
|
+
};
|
|
2390
2393
|
});
|
|
2391
2394
|
|
|
2392
2395
|
const reservesAndOracles = await getTokenOracleData(this.getConnection(), deserializedReserves, oracleAccounts);
|
|
@@ -2445,9 +2448,18 @@ export class KaminoVaultClient {
|
|
|
2445
2448
|
});
|
|
2446
2449
|
|
|
2447
2450
|
// read missing reserves
|
|
2448
|
-
const
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
+
const missingReserveAddresses = [...missingReserves];
|
|
2452
|
+
const missingReservesStates = (await Reserve.fetchMultiple(this.getConnection(), missingReserveAddresses))
|
|
2453
|
+
.map((reserve, index) => {
|
|
2454
|
+
if (!reserve) {
|
|
2455
|
+
return null;
|
|
2456
|
+
}
|
|
2457
|
+
return {
|
|
2458
|
+
address: missingReserveAddresses[index],
|
|
2459
|
+
state: reserve,
|
|
2460
|
+
};
|
|
2461
|
+
})
|
|
2462
|
+
.filter((state) => state !== null);
|
|
2451
2463
|
const missingReservesAndOracles = await getTokenOracleData(
|
|
2452
2464
|
this.getConnection(),
|
|
2453
2465
|
missingReservesStates,
|
|
@@ -2456,7 +2468,7 @@ export class KaminoVaultClient {
|
|
|
2456
2468
|
missingReservesAndOracles.forEach(([reserve, oracle], index) => {
|
|
2457
2469
|
const fetchedReserve = new KaminoReserve(
|
|
2458
2470
|
reserve,
|
|
2459
|
-
[
|
|
2471
|
+
missingReserveAddresses[index]!, // Set maintains order
|
|
2460
2472
|
oracle!,
|
|
2461
2473
|
this.getConnection(),
|
|
2462
2474
|
this.recentSlotDurationMs
|
package/src/utils/oracle.ts
CHANGED
|
@@ -3,7 +3,7 @@ import Decimal from 'decimal.js';
|
|
|
3
3
|
import { Scope } from '@kamino-finance/scope-sdk';
|
|
4
4
|
import { OraclePrices } from '@kamino-finance/scope-sdk/dist/@codegen/scope/accounts/OraclePrices';
|
|
5
5
|
import { isNotNullPubkey } from './pubkey';
|
|
6
|
-
import { parseTokenSymbol } from '../classes';
|
|
6
|
+
import { parseTokenSymbol, ReserveWithAddress } from '../classes';
|
|
7
7
|
import { Reserve } from '../lib';
|
|
8
8
|
import { batchFetch } from '@kamino-finance/kliquidity-sdk';
|
|
9
9
|
import BN from 'bn.js';
|
|
@@ -43,12 +43,12 @@ export type ScopePriceRefreshConfig = {
|
|
|
43
43
|
scopeConfigurations: [Address, Configuration][];
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
-
export function getTokenOracleDataSync(allOracleAccounts: AllOracleAccounts, reserves:
|
|
46
|
+
export function getTokenOracleDataSync(allOracleAccounts: AllOracleAccounts, reserves: ReserveWithAddress[]) {
|
|
47
47
|
const tokenOracleDataForReserves: Array<[Reserve, TokenOracleData | undefined]> = [];
|
|
48
48
|
const pythCache = new Map<Address, PythPrices>();
|
|
49
49
|
const switchboardCache = new Map<Address, CandidatePrice>();
|
|
50
50
|
const scopeCache = new Map<Address, OraclePrices>();
|
|
51
|
-
for (const reserve of reserves) {
|
|
51
|
+
for (const { address, state: reserve } of reserves) {
|
|
52
52
|
let currentBest: CandidatePrice | undefined = undefined;
|
|
53
53
|
const oracle = {
|
|
54
54
|
pythAddress: reserve.config.tokenInfo.pythConfiguration.price,
|
|
@@ -86,7 +86,10 @@ export function getTokenOracleDataSync(allOracleAccounts: AllOracleAccounts, res
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
if (!currentBest) {
|
|
89
|
-
|
|
89
|
+
const reserveSymbol = parseTokenSymbol(reserve.config.tokenInfo.name);
|
|
90
|
+
console.error(
|
|
91
|
+
`No price found for reserve: ${reserveSymbol ?? 'unknown'} (${address}) in market: ${reserve.lendingMarket}`
|
|
92
|
+
);
|
|
90
93
|
tokenOracleDataForReserves.push([reserve, undefined]);
|
|
91
94
|
continue;
|
|
92
95
|
}
|
|
@@ -105,10 +108,15 @@ export function getTokenOracleDataSync(allOracleAccounts: AllOracleAccounts, res
|
|
|
105
108
|
// TODO: Add freshness of the latest price to match sc logic
|
|
106
109
|
export async function getTokenOracleData(
|
|
107
110
|
rpc: Rpc<GetMultipleAccountsApi>,
|
|
108
|
-
reserves:
|
|
111
|
+
reserves: ReserveWithAddress[],
|
|
109
112
|
oracleAccounts?: AllOracleAccounts
|
|
110
113
|
): Promise<Array<[Reserve, TokenOracleData | undefined]>> {
|
|
111
|
-
const allOracleAccounts =
|
|
114
|
+
const allOracleAccounts =
|
|
115
|
+
oracleAccounts ??
|
|
116
|
+
(await getAllOracleAccounts(
|
|
117
|
+
rpc,
|
|
118
|
+
reserves.map((r) => r.state)
|
|
119
|
+
));
|
|
112
120
|
return getTokenOracleDataSync(allOracleAccounts, reserves);
|
|
113
121
|
}
|
|
114
122
|
|