@kamino-finance/klend-sdk 6.0.5-beta.5 → 6.0.5-beta.7

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.
Files changed (39) hide show
  1. package/dist/classes/action.d.ts +1 -1
  2. package/dist/classes/action.d.ts.map +1 -1
  3. package/dist/classes/action.js +28 -13
  4. package/dist/classes/action.js.map +1 -1
  5. package/dist/classes/manager.d.ts +29 -18
  6. package/dist/classes/manager.d.ts.map +1 -1
  7. package/dist/classes/manager.js +65 -47
  8. package/dist/classes/manager.js.map +1 -1
  9. package/dist/classes/market.d.ts +2 -3
  10. package/dist/classes/market.d.ts.map +1 -1
  11. package/dist/classes/market.js +8 -9
  12. package/dist/classes/market.js.map +1 -1
  13. package/dist/client_kamino_manager.d.ts.map +1 -1
  14. package/dist/client_kamino_manager.js +30 -22
  15. package/dist/client_kamino_manager.js.map +1 -1
  16. package/dist/leverage/operations.d.ts.map +1 -1
  17. package/dist/leverage/operations.js +8 -5
  18. package/dist/leverage/operations.js.map +1 -1
  19. package/dist/utils/managerTypes.d.ts +1 -2
  20. package/dist/utils/managerTypes.d.ts.map +1 -1
  21. package/dist/utils/managerTypes.js +9 -9
  22. package/dist/utils/managerTypes.js.map +1 -1
  23. package/dist/utils/oracle.d.ts +2 -2
  24. package/dist/utils/oracle.d.ts.map +1 -1
  25. package/dist/utils/oracle.js.map +1 -1
  26. package/dist/utils/pubkey.d.ts +1 -0
  27. package/dist/utils/pubkey.d.ts.map +1 -1
  28. package/dist/utils/pubkey.js +10 -0
  29. package/dist/utils/pubkey.js.map +1 -1
  30. package/package.json +2 -2
  31. package/src/classes/action.ts +28 -12
  32. package/src/classes/manager.ts +80 -51
  33. package/src/classes/market.ts +14 -19
  34. package/src/client.ts +4 -4
  35. package/src/client_kamino_manager.ts +40 -35
  36. package/src/leverage/operations.ts +9 -10
  37. package/src/utils/managerTypes.ts +1 -2
  38. package/src/utils/oracle.ts +2 -2
  39. package/src/utils/pubkey.ts +9 -0
@@ -22,6 +22,7 @@ import {
22
22
  CandidatePrice,
23
23
  PublicKeySet,
24
24
  DEPOSITS_LIMIT,
25
+ setOrAppend,
25
26
  } from '../utils';
26
27
  import base58 from 'bs58';
27
28
  import { BN } from '@coral-xyz/anchor';
@@ -62,7 +63,7 @@ export class KaminoMarket {
62
63
 
63
64
  private readonly recentSlotDurationMs: number;
64
65
 
65
- private readonly scopeFeeds: PublicKeySet<PublicKey>;
66
+ readonly scopeFeeds: PublicKeySet<PublicKey>;
66
67
 
67
68
  private constructor(
68
69
  connection: Connection,
@@ -93,7 +94,6 @@ export class KaminoMarket {
93
94
  * @param recentSlotDurationMs
94
95
  * @param programId
95
96
  * @param withReserves
96
- * @param setupLocalTest
97
97
  * @param withReserves
98
98
  */
99
99
  static async load(
@@ -1544,16 +1544,7 @@ export async function getSingleReserve(
1544
1544
  if (!oracle) {
1545
1545
  throw Error(`Could not find oracle for ${parseTokenSymbol(reserveState.config.tokenInfo.name)} reserve`);
1546
1546
  }
1547
- const kaminoReserve = KaminoReserve.initialize(
1548
- reserve,
1549
- reservePk,
1550
- reserveState,
1551
- oracle,
1552
- connection,
1553
- recentSlotDurationMs
1554
- );
1555
-
1556
- return kaminoReserve;
1547
+ return KaminoReserve.initialize(reserve, reservePk, reserveState, oracle, connection, recentSlotDurationMs);
1557
1548
  }
1558
1549
 
1559
1550
  export function getReservesActive(reserves: Map<PublicKey, KaminoReserve>): Map<PublicKey, KaminoReserve> {
@@ -1566,8 +1557,11 @@ export function getReservesActive(reserves: Map<PublicKey, KaminoReserve>): Map<
1566
1557
  return reservesActive;
1567
1558
  }
1568
1559
 
1569
- export function getTokenIdsForScopeRefresh(kaminoMarket: KaminoMarket, reserves: PublicKey[]): number[] {
1570
- const tokenIds: number[] = [];
1560
+ export function getTokenIdsForScopeRefresh(
1561
+ kaminoMarket: KaminoMarket,
1562
+ reserves: PublicKey[]
1563
+ ): PubkeyHashMap<PublicKey, number[]> {
1564
+ const tokenIds = new PubkeyHashMap<PublicKey, number[]>();
1571
1565
 
1572
1566
  for (const reserveAddress of reserves) {
1573
1567
  const reserve = kaminoMarket.getReserveByAddress(reserveAddress);
@@ -1575,17 +1569,18 @@ export function getTokenIdsForScopeRefresh(kaminoMarket: KaminoMarket, reserves:
1575
1569
  throw new Error(`Reserve not found for reserve ${reserveAddress.toBase58()}`);
1576
1570
  }
1577
1571
 
1578
- if (!reserve.state.config.tokenInfo.scopeConfiguration.priceFeed.equals(PublicKey.default)) {
1572
+ const { scopeConfiguration } = reserve.state.config.tokenInfo;
1573
+ if (!scopeConfiguration.priceFeed.equals(PublicKey.default)) {
1579
1574
  let x = 0;
1580
1575
 
1581
- while (reserve.state.config.tokenInfo.scopeConfiguration.priceChain[x] !== U16_MAX) {
1582
- tokenIds.push(reserve.state.config.tokenInfo.scopeConfiguration.priceChain[x]);
1576
+ while (scopeConfiguration.priceChain[x] !== U16_MAX) {
1577
+ setOrAppend(tokenIds, scopeConfiguration.priceFeed, scopeConfiguration.priceChain[x]);
1583
1578
  x++;
1584
1579
  }
1585
1580
 
1586
1581
  x = 0;
1587
- while (reserve.state.config.tokenInfo.scopeConfiguration.twapChain[x] !== U16_MAX) {
1588
- tokenIds.push(reserve.state.config.tokenInfo.scopeConfiguration.twapChain[x]);
1582
+ while (scopeConfiguration.twapChain[x] !== U16_MAX) {
1583
+ setOrAppend(tokenIds, scopeConfiguration.priceFeed, scopeConfiguration.twapChain[x]);
1589
1584
  x++;
1590
1585
  }
1591
1586
  }
package/src/client.ts CHANGED
@@ -362,7 +362,7 @@ async function deposit(connection: Connection, wallet: Keypair, token: string, d
362
362
  wallet.publicKey,
363
363
  new VanillaObligation(STAGING_LENDING_MARKET),
364
364
  true,
365
- { scope: new Scope('mainnet-beta', connection), scopeFeed: 'hubble' }
365
+ { scope: new Scope('mainnet-beta', connection) }
366
366
  );
367
367
  console.log('User obligation', kaminoAction.getObligationPda().toString());
368
368
 
@@ -384,7 +384,7 @@ async function withdraw(connection: Connection, wallet: Keypair, token: string,
384
384
  wallet.publicKey,
385
385
  new VanillaObligation(new PublicKey(STAGING_LENDING_MARKET)),
386
386
  true,
387
- { scope: new Scope('mainnet-beta', connection), scopeFeed: 'hubble' }
387
+ { scope: new Scope('mainnet-beta', connection) }
388
388
  );
389
389
  console.log('User obligation', kaminoAction.getObligationPda().toString());
390
390
 
@@ -406,7 +406,7 @@ async function borrow(connection: Connection, wallet: Keypair, token: string, bo
406
406
  wallet.publicKey,
407
407
  new VanillaObligation(new PublicKey(STAGING_LENDING_MARKET)),
408
408
  true,
409
- { scope: new Scope('mainnet-beta', connection), scopeFeed: 'hubble' }
409
+ { scope: new Scope('mainnet-beta', connection) }
410
410
  );
411
411
  console.log('User obligation', kaminoAction.getObligationPda().toString());
412
412
 
@@ -428,7 +428,7 @@ async function repay(connection: Connection, wallet: Keypair, token: string, bor
428
428
  wallet.publicKey,
429
429
  new VanillaObligation(new PublicKey(STAGING_LENDING_MARKET)),
430
430
  true,
431
- { scope: new Scope('mainnet-beta', connection), scopeFeed: 'hubble' },
431
+ { scope: new Scope('mainnet-beta', connection) },
432
432
  await connection.getSlot()
433
433
  );
434
434
  console.log('User obligation', kaminoAction.getObligationPda().toString());
@@ -52,18 +52,18 @@ import {
52
52
  TokenInfo,
53
53
  WithdrawalCaps,
54
54
  } from './idl_codegen/types';
55
- import { Fraction } from './classes/fraction';
55
+ import { Fraction } from './classes';
56
56
  import Decimal from 'decimal.js';
57
57
  import { BN } from '@coral-xyz/anchor';
58
58
  import { PythConfiguration, SwitchboardConfiguration } from './idl_codegen_kamino_vault/types';
59
59
  import * as fs from 'fs';
60
- import { MarketWithAddress } from './utils/managerTypes';
60
+ import { MarketWithAddress } from './utils';
61
61
  import {
62
62
  ManagementFeeBps,
63
63
  PendingVaultAdmin,
64
64
  PerformanceFeeBps,
65
65
  } from './idl_codegen_kamino_vault/types/VaultConfigField';
66
- import { getAccountOwner } from './utils/rpc';
66
+ import { getAccountOwner } from './utils';
67
67
  import { getAssociatedTokenAddressSync } from '@solana/spl-token';
68
68
 
69
69
  dotenv.config({
@@ -157,12 +157,12 @@ async function main() {
157
157
 
158
158
  console.log('reserve: ', reserve.publicKey);
159
159
 
160
- const _createReserveSig = await processTxn(env.client, env.payer, txnIxs[0], mode, 2500, [reserve]);
160
+ await processTxn(env.client, env.payer, txnIxs[0], mode, 2500, [reserve]);
161
161
 
162
162
  const [lut, createLutIxs] = await createUpdateReserveConfigLutIxs(env, marketAddress, reserve.publicKey);
163
163
  await processTxn(env.client, env.payer, createLutIxs, mode, 2500, []);
164
164
 
165
- const _updateSig = await processTxn(env.client, env.payer, txnIxs[1], mode, 2500, [], 400_000, 1000, [lut]);
165
+ await processTxn(env.client, env.payer, txnIxs[1], mode, 2500, [], 400_000, 1000, [lut]);
166
166
 
167
167
  mode === 'execute' &&
168
168
  console.log(
@@ -224,7 +224,7 @@ async function main() {
224
224
  updateEntireConfig
225
225
  );
226
226
 
227
- const _updateReserveSig = await processTxn(env.client, env.payer, ixs, mode, 2500, [], 400_000);
227
+ await processTxn(env.client, env.payer, ixs, mode, 2500, [], 400_000);
228
228
 
229
229
  mode === 'execute' && console.log('Reserve Updated with config -> ', JSON.parse(JSON.stringify(reserveConfig)));
230
230
  });
@@ -296,7 +296,7 @@ async function main() {
296
296
 
297
297
  const { vault: vaultKp, initVaultIxs: instructions } = await kaminoManager.createVaultIxs(kaminoVaultConfig);
298
298
 
299
- const _createVaultSig = await processTxn(
299
+ await processTxn(
300
300
  env.client,
301
301
  env.payer,
302
302
  [...instructions.createAtaIfNeededIxs, ...instructions.initVaultIxs, instructions.createLUTIx],
@@ -305,7 +305,7 @@ async function main() {
305
305
  [vaultKp]
306
306
  );
307
307
  await sleep(2000);
308
- const _populateLUTSig = await processTxn(
308
+ await processTxn(
309
309
  env.client,
310
310
  env.payer,
311
311
  [...instructions.populateLUTIxs, ...instructions.cleanupIxs],
@@ -314,14 +314,7 @@ async function main() {
314
314
  []
315
315
  );
316
316
 
317
- const _setSharesMetadataSig = await processTxn(
318
- env.client,
319
- env.payer,
320
- [instructions.initSharesMetadataIx],
321
- mode,
322
- 2500,
323
- []
324
- );
317
+ await processTxn(env.client, env.payer, [instructions.initSharesMetadataIx], mode, 2500, []);
325
318
  mode === 'execute' && console.log('Vault created:', vaultKp.publicKey.toBase58());
326
319
  });
327
320
 
@@ -1173,19 +1166,33 @@ async function main() {
1173
1166
  }
1174
1167
  });
1175
1168
 
1176
- commands.command('get-oracle-mappings').action(async () => {
1177
- const env = initializeClient(false, false);
1178
- const kaminoManager = new KaminoManager(
1179
- env.connection,
1180
- DEFAULT_RECENT_SLOT_DURATION_MS,
1181
- env.kLendProgramId,
1182
- env.kVaultProgramId
1183
- );
1169
+ commands
1170
+ .command('get-oracle-mappings')
1171
+ .requiredOption('--lending-market <string>', 'Lending Market Address')
1172
+ .action(async ({ lendingMarket }) => {
1173
+ const env = initializeClient(false, false);
1174
+ const kaminoManager = new KaminoManager(
1175
+ env.connection,
1176
+ DEFAULT_RECENT_SLOT_DURATION_MS,
1177
+ env.kLendProgramId,
1178
+ env.kVaultProgramId
1179
+ );
1180
+ const market = await KaminoMarket.load(
1181
+ env.connection,
1182
+ new PublicKey(lendingMarket),
1183
+ DEFAULT_RECENT_SLOT_DURATION_MS,
1184
+ env.kLendProgramId
1185
+ );
1186
+ if (!market) {
1187
+ throw Error(`Lending market ${lendingMarket} not found`);
1188
+ }
1184
1189
 
1185
- console.log('Getting oracle mappings');
1186
- const oracleConfigs = await kaminoManager.getScopeOracleConfigs();
1187
- console.log('oracleConfigs', JSON.parse(JSON.stringify(oracleConfigs)));
1188
- });
1190
+ console.log('Getting oracle mappings');
1191
+ const oracleConfigs = await kaminoManager.getScopeOracleConfigs(market);
1192
+ for (const [oraclePrices, configs] of oracleConfigs.entries()) {
1193
+ console.log(`OraclePrices pubkey: ${oraclePrices.toString()}`, 'Configs:', JSON.parse(JSON.stringify(configs)));
1194
+ }
1195
+ });
1189
1196
 
1190
1197
  commands.command('get-all-vaults').action(async () => {
1191
1198
  const env = initializeClient(false, false);
@@ -1370,7 +1377,7 @@ async function main() {
1370
1377
  // executing 6 ixs in a txn to make sure they fit
1371
1378
  for (let ixnIndex = 0; ixnIndex < ixs.length; ixnIndex += 6) {
1372
1379
  const ixnToExecute = ixs.slice(ixnIndex, ixnIndex + 6);
1373
- const _updateLendingMarketSig = await processTxn(env.client, env.payer, ixnToExecute, mode, 2500, [], 400_000);
1380
+ await processTxn(env.client, env.payer, ixnToExecute, mode, 2500, [], 400_000);
1374
1381
  }
1375
1382
 
1376
1383
  mode === 'execute' &&
@@ -1410,7 +1417,7 @@ async function main() {
1410
1417
 
1411
1418
  const ix = kaminoManager.updateLendingMarketOwnerIxs(marketWithAddress);
1412
1419
 
1413
- const _updateLendingMarketSig = await processTxn(env.client, env.payer, [ix], mode, 2500, [], 400_000);
1420
+ await processTxn(env.client, env.payer, [ix], mode, 2500, [], 400_000);
1414
1421
 
1415
1422
  mode === 'execute' &&
1416
1423
  console.log(
@@ -1465,7 +1472,7 @@ async function main() {
1465
1472
 
1466
1473
  const ixs = kaminoManager.updateLendingMarketIxs(marketWithAddress, newLendingMarket);
1467
1474
 
1468
- const _updateLendingMarketSig = await processTxn(env.client, env.payer, ixs, mode, 2500, [], 400_000);
1475
+ await processTxn(env.client, env.payer, ixs, mode, 2500, [], 400_000);
1469
1476
 
1470
1477
  mode === 'execute' &&
1471
1478
  console.log(
@@ -1520,7 +1527,7 @@ async function main() {
1520
1527
 
1521
1528
  const ixs = await kaminoManager.updateReserveIxs(marketWithAddress, reserveAddress, newReserveConfig);
1522
1529
 
1523
- const _updateLendingMarketSig = await processTxn(env.client, env.payer, ixs, mode, 2500, [], 400_000);
1530
+ await processTxn(env.client, env.payer, ixs, mode, 2500, [], 400_000);
1524
1531
 
1525
1532
  mode === 'execute' &&
1526
1533
  console.log(
@@ -1811,9 +1818,7 @@ function parseBorrowRateCurve(reserveConfigFromFile: any): BorrowRateCurve {
1811
1818
 
1812
1819
  curvePoints.forEach((curvePoint, index) => (finalCurvePoints[index] = curvePoint));
1813
1820
 
1814
- const borrowRateCurve = new BorrowRateCurve({ points: finalCurvePoints });
1815
-
1816
- return borrowRateCurve;
1821
+ return new BorrowRateCurve({ points: finalCurvePoints });
1817
1822
  }
1818
1823
 
1819
1824
  function parseReserveBorrowLimitAgainstCollInEmode(reserveConfigFromFile: any): BN[] {
@@ -1685,18 +1685,17 @@ export const getScopeRefreshIx = async (
1685
1685
  debtReserve.address,
1686
1686
  ]).toArray()
1687
1687
  : new PublicKeySet<PublicKey>([collReserve.address, debtReserve.address]).toArray();
1688
- const tokenIds = getTokenIdsForScopeRefresh(market, allReserves);
1689
1688
 
1690
1689
  const scopeRefreshIxs: TransactionInstruction[] = [];
1691
- if (tokenIds.length > 0 && scopeRefreshConfig) {
1692
- scopeRefreshIxs.push(
1693
- await scopeRefreshConfig.scope.refreshPriceListIx(
1694
- {
1695
- feed: scopeRefreshConfig.scopeFeed,
1696
- },
1697
- tokenIds
1698
- )
1699
- );
1690
+ const scopeTokensMap = getTokenIdsForScopeRefresh(market, allReserves);
1691
+
1692
+ if (scopeTokensMap.size > 0 && scopeRefreshConfig) {
1693
+ for (const [configPubkey, config] of scopeRefreshConfig.scopeConfigurations) {
1694
+ const tokenIds = scopeTokensMap.get(config.oraclePrices);
1695
+ if (tokenIds && tokenIds.length > 0) {
1696
+ scopeRefreshIxs.push(await scopeRefreshConfig.scope.refreshPriceListIx({ config: configPubkey }, tokenIds));
1697
+ }
1698
+ }
1700
1699
  }
1701
1700
 
1702
1701
  return scopeRefreshIxs;
@@ -13,7 +13,7 @@ import {
13
13
  WithdrawalCaps,
14
14
  } from '../idl_codegen/types';
15
15
  import Decimal from 'decimal.js';
16
- import { Fraction, ZERO_FRACTION } from '../classes/fraction';
16
+ import { Fraction, ZERO_FRACTION } from '../classes';
17
17
  import BN from 'bn.js';
18
18
  import { numberToLamportsDecimal } from '../classes';
19
19
  import { NULL_PUBKEY } from './pubkey';
@@ -21,7 +21,6 @@ import { OracleType, U16_MAX } from '@kamino-finance/scope-sdk';
21
21
  import { LendingMarket } from '../lib';
22
22
 
23
23
  export type ScopeOracleConfig = {
24
- scopePriceConfigAddress: PublicKey;
25
24
  name: string;
26
25
  oracleType: string;
27
26
  oracleId: number;
@@ -1,6 +1,6 @@
1
1
  import { AccountInfo, Connection, PublicKey } from '@solana/web3.js';
2
2
  import Decimal from 'decimal.js';
3
- import { OraclePrices, Scope } from '@kamino-finance/scope-sdk';
3
+ import { Configuration, OraclePrices, Scope } from '@kamino-finance/scope-sdk';
4
4
  import { isNotNullPubkey, PubkeyHashMap, PublicKeySet } from './pubkey';
5
5
  import { parseTokenSymbol } from '../classes';
6
6
  import SwitchboardProgram from '@switchboard-xyz/sbv2-lite';
@@ -37,7 +37,7 @@ export type CandidatePrice = {
37
37
 
38
38
  export type ScopePriceRefreshConfig = {
39
39
  scope: Scope;
40
- scopeFeed: string;
40
+ scopeConfigurations: [PublicKey, Configuration][];
41
41
  };
42
42
 
43
43
  export function getTokenOracleDataSync(
@@ -253,6 +253,15 @@ export class PubkeyHashMap<K extends PublicKey, V> implements Map<K, V> {
253
253
  }
254
254
  }
255
255
 
256
+ export function setOrAppend<K, V>(map: Map<K, V[]>, key: K, value: V): void {
257
+ const existing = map.get(key);
258
+ if (existing) {
259
+ existing.push(value);
260
+ } else {
261
+ map.set(key, [value]);
262
+ }
263
+ }
264
+
256
265
  export class HashablePublicKey extends PublicKey implements IEquality<HashablePublicKey> {
257
266
  // We only use the last 32 bits of the public key for hashing
258
267
  static MASK = new BN(1).shln(32).subn(1);