@kamino-finance/klend-sdk 7.3.2 → 7.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/classes/manager.d.ts.map +1 -1
- package/dist/classes/manager.js +6 -2
- package/dist/classes/manager.js.map +1 -1
- package/dist/classes/market.d.ts.map +1 -1
- package/dist/classes/market.js +16 -6
- package/dist/classes/market.js.map +1 -1
- package/dist/classes/reserve.d.ts +2 -1
- package/dist/classes/reserve.d.ts.map +1 -1
- package/dist/classes/reserve.js +11 -5
- package/dist/classes/reserve.js.map +1 -1
- package/dist/classes/shared.d.ts +1 -0
- package/dist/classes/shared.d.ts.map +1 -1
- package/dist/classes/shared.js.map +1 -1
- package/dist/classes/vault.d.ts.map +1 -1
- package/dist/classes/vault.js +6 -2
- package/dist/classes/vault.js.map +1 -1
- package/dist/utils/readCdnData.d.ts +25 -0
- package/dist/utils/readCdnData.d.ts.map +1 -0
- package/dist/utils/readCdnData.js +29 -0
- package/dist/utils/readCdnData.js.map +1 -0
- package/package.json +1 -1
- package/src/classes/manager.ts +7 -2
- package/src/classes/market.ts +24 -6
- package/src/classes/reserve.ts +13 -5
- package/src/classes/shared.ts +1 -0
- package/src/classes/vault.ts +7 -2
- package/src/utils/readCdnData.ts +50 -0
package/src/classes/market.ts
CHANGED
|
@@ -56,6 +56,7 @@ import { ObligationZP } from '../@codegen/klend/zero_padding';
|
|
|
56
56
|
import { checkDefined } from '../utils/validations';
|
|
57
57
|
import { Buffer } from 'buffer';
|
|
58
58
|
import { ReserveStatus } from '../@codegen/klend/types';
|
|
59
|
+
import { fetchKaminoCdnData } from '../utils/readCdnData';
|
|
59
60
|
|
|
60
61
|
export type KaminoMarketRpcApi = GetAccountInfoApi &
|
|
61
62
|
GetMultipleAccountsApi &
|
|
@@ -479,7 +480,10 @@ export class KaminoMarket {
|
|
|
479
480
|
state: reserveAccount,
|
|
480
481
|
};
|
|
481
482
|
});
|
|
482
|
-
const reservesAndOracles = await
|
|
483
|
+
const [reservesAndOracles, cdnResourcesData] = await Promise.all([
|
|
484
|
+
getTokenOracleData(this.getRpc(), deserializedReserves, oracleAccounts),
|
|
485
|
+
fetchKaminoCdnData(),
|
|
486
|
+
]);
|
|
483
487
|
const kaminoReserves = new Map<Address, KaminoReserve>();
|
|
484
488
|
reservesAndOracles.forEach(([reserve, oracle], index) => {
|
|
485
489
|
if (!oracle) {
|
|
@@ -494,7 +498,8 @@ export class KaminoMarket {
|
|
|
494
498
|
reserve,
|
|
495
499
|
oracle,
|
|
496
500
|
this.rpc,
|
|
497
|
-
this.recentSlotDurationMs
|
|
501
|
+
this.recentSlotDurationMs,
|
|
502
|
+
cdnResourcesData
|
|
498
503
|
);
|
|
499
504
|
kaminoReserves.set(kaminoReserve.address, kaminoReserve);
|
|
500
505
|
});
|
|
@@ -1712,7 +1717,10 @@ export async function getReservesForMarket(
|
|
|
1712
1717
|
state: reserveAccount,
|
|
1713
1718
|
};
|
|
1714
1719
|
});
|
|
1715
|
-
const reservesAndOracles = await
|
|
1720
|
+
const [reservesAndOracles, cdnResourcesData] = await Promise.all([
|
|
1721
|
+
getTokenOracleData(rpc, deserializedReserves, oracleAccounts),
|
|
1722
|
+
fetchKaminoCdnData(),
|
|
1723
|
+
]);
|
|
1716
1724
|
const reservesByAddress = new Map<Address, KaminoReserve>();
|
|
1717
1725
|
reservesAndOracles.forEach(([reserve, oracle], index) => {
|
|
1718
1726
|
if (reserve.config.status === ReserveStatus.Obsolete.discriminator) {
|
|
@@ -1725,7 +1733,14 @@ export async function getReservesForMarket(
|
|
|
1725
1733
|
}) reserve in market ${reserve.lendingMarket}`
|
|
1726
1734
|
);
|
|
1727
1735
|
}
|
|
1728
|
-
const kaminoReserve = KaminoReserve.initialize(
|
|
1736
|
+
const kaminoReserve = KaminoReserve.initialize(
|
|
1737
|
+
reserves[index].pubkey,
|
|
1738
|
+
reserve,
|
|
1739
|
+
oracle,
|
|
1740
|
+
rpc,
|
|
1741
|
+
recentSlotDurationMs,
|
|
1742
|
+
cdnResourcesData
|
|
1743
|
+
);
|
|
1729
1744
|
reservesByAddress.set(kaminoReserve.address, kaminoReserve);
|
|
1730
1745
|
});
|
|
1731
1746
|
return reservesByAddress;
|
|
@@ -1743,7 +1758,10 @@ export async function getSingleReserve(
|
|
|
1743
1758
|
if (reserve === null) {
|
|
1744
1759
|
throw new Error(`Reserve account ${reservePk} does not exist`);
|
|
1745
1760
|
}
|
|
1746
|
-
const reservesAndOracles = await
|
|
1761
|
+
const [reservesAndOracles, cdnResourcesData] = await Promise.all([
|
|
1762
|
+
getTokenOracleData(rpc, [{ address: reservePk, state: reserve }], oracleAccounts),
|
|
1763
|
+
fetchKaminoCdnData(),
|
|
1764
|
+
]);
|
|
1747
1765
|
const [, oracle] = reservesAndOracles[0];
|
|
1748
1766
|
|
|
1749
1767
|
if (!oracle) {
|
|
@@ -1753,7 +1771,7 @@ export async function getSingleReserve(
|
|
|
1753
1771
|
}`
|
|
1754
1772
|
);
|
|
1755
1773
|
}
|
|
1756
|
-
return KaminoReserve.initialize(reservePk, reserve, oracle, rpc, recentSlotDurationMs);
|
|
1774
|
+
return KaminoReserve.initialize(reservePk, reserve, oracle, rpc, recentSlotDurationMs, cdnResourcesData);
|
|
1757
1775
|
}
|
|
1758
1776
|
|
|
1759
1777
|
export function getReservesActive(reserves: Map<Address, KaminoReserve>): Map<Address, KaminoReserve> {
|
package/src/classes/reserve.ts
CHANGED
|
@@ -57,6 +57,7 @@ import { SYSVAR_RENT_ADDRESS } from '@solana/sysvars';
|
|
|
57
57
|
import { noopSigner } from '../utils/signer';
|
|
58
58
|
import { getRewardPerTimeUnitSecond } from './farm_utils';
|
|
59
59
|
import { Scope, ScopeEntryMetadata } from '@kamino-finance/scope-sdk';
|
|
60
|
+
import { fetchKaminoCdnData, KaminoCdnData } from '../utils/readCdnData';
|
|
60
61
|
|
|
61
62
|
export type KaminoReserveRpcApi = GetProgramAccountsApi & GetAccountInfoApi & GetMultipleAccountsApi;
|
|
62
63
|
|
|
@@ -97,10 +98,11 @@ export class KaminoReserve {
|
|
|
97
98
|
state: Reserve,
|
|
98
99
|
tokenOraclePrice: TokenOracleData,
|
|
99
100
|
rpc: Rpc<KaminoReserveRpcApi>,
|
|
100
|
-
recentSlotDurationMs: number
|
|
101
|
+
recentSlotDurationMs: number,
|
|
102
|
+
cdnResourcesData?: KaminoCdnData
|
|
101
103
|
): KaminoReserve {
|
|
102
104
|
const reserve = new KaminoReserve(state, address, tokenOraclePrice, rpc, recentSlotDurationMs);
|
|
103
|
-
reserve.stats = reserve.formatReserveData(state);
|
|
105
|
+
reserve.stats = reserve.formatReserveData(state, cdnResourcesData?.deprecatedAssets ?? []);
|
|
104
106
|
return reserve;
|
|
105
107
|
}
|
|
106
108
|
|
|
@@ -779,13 +781,16 @@ export class KaminoReserve {
|
|
|
779
781
|
}
|
|
780
782
|
|
|
781
783
|
async load(tokenOraclePrice: TokenOracleData) {
|
|
782
|
-
const parsedData = await
|
|
784
|
+
const [parsedData, cdnResourcesData] = await Promise.all([
|
|
785
|
+
Reserve.fetch(this.rpc, this.address),
|
|
786
|
+
fetchKaminoCdnData(),
|
|
787
|
+
]);
|
|
783
788
|
if (!parsedData) {
|
|
784
789
|
throw Error(`Unable to parse data of reserve ${this.symbol}`);
|
|
785
790
|
}
|
|
786
791
|
this.state = parsedData;
|
|
787
792
|
this.tokenOraclePrice = tokenOraclePrice;
|
|
788
|
-
this.stats = this.formatReserveData(parsedData);
|
|
793
|
+
this.stats = this.formatReserveData(parsedData, cdnResourcesData?.deprecatedAssets ?? []);
|
|
789
794
|
}
|
|
790
795
|
|
|
791
796
|
totalSupplyAPY(currentSlot: Slot) {
|
|
@@ -874,7 +879,7 @@ export class KaminoReserve {
|
|
|
874
879
|
return { apy: aprToApy(apr, 365), apr };
|
|
875
880
|
}
|
|
876
881
|
|
|
877
|
-
private formatReserveData(parsedData: ReserveFields): ReserveDataType {
|
|
882
|
+
private formatReserveData(parsedData: ReserveFields, deprecatedAssets: string[]): ReserveDataType {
|
|
878
883
|
const mintTotalSupply = new Decimal(parsedData.collateral.mintTotalSupply.toString()).div(this.getMintFactor());
|
|
879
884
|
let reserveStatus = ReserveStatus.Active;
|
|
880
885
|
switch (parsedData.config.status) {
|
|
@@ -888,6 +893,8 @@ export class KaminoReserve {
|
|
|
888
893
|
reserveStatus = ReserveStatus.Hidden;
|
|
889
894
|
break;
|
|
890
895
|
}
|
|
896
|
+
const reserveIsUIDeprecated =
|
|
897
|
+
deprecatedAssets.length > 0 ? deprecatedAssets.includes(this.address.toString()) : undefined;
|
|
891
898
|
return {
|
|
892
899
|
// Reserve config
|
|
893
900
|
|
|
@@ -910,6 +917,7 @@ export class KaminoReserve {
|
|
|
910
917
|
depositLimitCrossedTimestamp: parsedData.liquidity.depositLimitCrossedTimestamp.toNumber(),
|
|
911
918
|
borrowLimitCrossedTimestamp: parsedData.liquidity.borrowLimitCrossedTimestamp.toNumber(),
|
|
912
919
|
borrowFactor: parsedData.config.borrowFactorPct.toNumber(),
|
|
920
|
+
isUIDeprecated: reserveIsUIDeprecated,
|
|
913
921
|
};
|
|
914
922
|
}
|
|
915
923
|
|
package/src/classes/shared.ts
CHANGED
package/src/classes/vault.ts
CHANGED
|
@@ -139,6 +139,7 @@ import { Farms } from '@kamino-finance/farms-sdk';
|
|
|
139
139
|
import { getFarmIncentives } from '@kamino-finance/farms-sdk/dist/utils/apy';
|
|
140
140
|
import { computeReservesAllocation } from '../utils/vaultAllocation';
|
|
141
141
|
import { getReserveFarmRewardsAPY } from '../utils/farmUtils';
|
|
142
|
+
import { fetchKaminoCdnData } from '../utils/readCdnData';
|
|
142
143
|
|
|
143
144
|
export const kaminoVaultId = address('KvauGMspG5k6rtzrqqn7WNn3oZdyKqLKwK2XWQ8FLjd');
|
|
144
145
|
export const kaminoVaultStagingId = address('stKvQfwRsQiKnLtMNVLHKS3exFJmZFsgfzBPWHECUYK');
|
|
@@ -2581,7 +2582,10 @@ export class KaminoVaultClient {
|
|
|
2581
2582
|
const deserializedReserves = await batchFetch(vaultReservesAddresses, (chunk) =>
|
|
2582
2583
|
this.loadReserializedReserves(chunk)
|
|
2583
2584
|
);
|
|
2584
|
-
const reservesAndOracles = await
|
|
2585
|
+
const [reservesAndOracles, cdnResourcesData] = await Promise.all([
|
|
2586
|
+
getTokenOracleData(this.getConnection(), deserializedReserves, oracleAccounts),
|
|
2587
|
+
fetchKaminoCdnData(),
|
|
2588
|
+
]);
|
|
2585
2589
|
const kaminoReserves = new Map<Address, KaminoReserve>();
|
|
2586
2590
|
reservesAndOracles.forEach(([reserve, oracle], index) => {
|
|
2587
2591
|
if (!oracle) {
|
|
@@ -2596,7 +2600,8 @@ export class KaminoVaultClient {
|
|
|
2596
2600
|
reserve,
|
|
2597
2601
|
oracle,
|
|
2598
2602
|
this.getConnection(),
|
|
2599
|
-
this.recentSlotDurationMs
|
|
2603
|
+
this.recentSlotDurationMs,
|
|
2604
|
+
cdnResourcesData
|
|
2600
2605
|
);
|
|
2601
2606
|
kaminoReserves.set(kaminoReserve.address, kaminoReserve);
|
|
2602
2607
|
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { CDN_ENDPOINT } from './constants';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* CDN data structure containing Kamino resources for different networks
|
|
5
|
+
*/
|
|
6
|
+
export interface AllKaminoCdnData {
|
|
7
|
+
'mainnet-beta': KaminoCdnData;
|
|
8
|
+
devnet: KaminoCdnData;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Kamino CDN data structure
|
|
13
|
+
* This type can be extended with additional fields as needed
|
|
14
|
+
*/
|
|
15
|
+
export interface KaminoCdnData {
|
|
16
|
+
/**
|
|
17
|
+
* List of deprecated reserve addresses (pubkeys as strings)
|
|
18
|
+
* Note: This field is named 'deprecatedAssets' in the CDN but represents deprecated reserves
|
|
19
|
+
*/
|
|
20
|
+
deprecatedAssets: string[];
|
|
21
|
+
// Additional fields can be added here as they become relevant
|
|
22
|
+
[key: string]: unknown;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Fetches Kamino CDN data from the resources endpoint
|
|
27
|
+
* @returns Promise resolving to the CDN data for the specified cluster or undefined if fetching/parsing fails
|
|
28
|
+
*/
|
|
29
|
+
export async function fetchKaminoCdnData(): Promise<KaminoCdnData | undefined> {
|
|
30
|
+
const url = `${CDN_ENDPOINT}/resources.json`;
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
const response = await fetch(url);
|
|
34
|
+
|
|
35
|
+
if (!response.ok) {
|
|
36
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const text = await response.text();
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
const data: AllKaminoCdnData = JSON.parse(text);
|
|
43
|
+
return data['mainnet-beta'];
|
|
44
|
+
} catch (parseError) {
|
|
45
|
+
throw new Error('Invalid JSON in response');
|
|
46
|
+
}
|
|
47
|
+
} catch (error) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
}
|