@kamino-finance/klend-sdk 6.0.5 → 7.0.0

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 (97) hide show
  1. package/dist/@codegen/kvault/accounts/Reserve.js +1 -1
  2. package/dist/@codegen/kvault/accounts/VaultState.d.ts +6 -6
  3. package/dist/@codegen/kvault/accounts/VaultState.d.ts.map +1 -1
  4. package/dist/@codegen/kvault/accounts/VaultState.js +12 -12
  5. package/dist/@codegen/kvault/accounts/VaultState.js.map +1 -1
  6. package/dist/@codegen/kvault/errors/custom.d.ts +9 -1
  7. package/dist/@codegen/kvault/errors/custom.d.ts.map +1 -1
  8. package/dist/@codegen/kvault/errors/custom.js +15 -1
  9. package/dist/@codegen/kvault/errors/custom.js.map +1 -1
  10. package/dist/@codegen/kvault/types/VaultConfigField.d.ts +26 -0
  11. package/dist/@codegen/kvault/types/VaultConfigField.d.ts.map +1 -1
  12. package/dist/@codegen/kvault/types/VaultConfigField.js +49 -1
  13. package/dist/@codegen/kvault/types/VaultConfigField.js.map +1 -1
  14. package/dist/@codegen/kvault/types/index.d.ts +2 -2
  15. package/dist/@codegen/kvault/types/index.d.ts.map +1 -1
  16. package/dist/@codegen/kvault/types/index.js.map +1 -1
  17. package/dist/classes/action.d.ts +1 -1
  18. package/dist/classes/action.d.ts.map +1 -1
  19. package/dist/classes/action.js +26 -11
  20. package/dist/classes/action.js.map +1 -1
  21. package/dist/classes/manager.d.ts +25 -6
  22. package/dist/classes/manager.d.ts.map +1 -1
  23. package/dist/classes/manager.js +59 -27
  24. package/dist/classes/manager.js.map +1 -1
  25. package/dist/classes/market.d.ts +7 -2
  26. package/dist/classes/market.d.ts.map +1 -1
  27. package/dist/classes/market.js +12 -6
  28. package/dist/classes/market.js.map +1 -1
  29. package/dist/classes/vault.d.ts +22 -3
  30. package/dist/classes/vault.d.ts.map +1 -1
  31. package/dist/classes/vault.js +73 -40
  32. package/dist/classes/vault.js.map +1 -1
  33. package/dist/classes/vault_types.d.ts +9 -1
  34. package/dist/classes/vault_types.d.ts.map +1 -1
  35. package/dist/client/commands/borrow.d.ts.map +1 -1
  36. package/dist/client/commands/borrow.js +2 -1
  37. package/dist/client/commands/borrow.js.map +1 -1
  38. package/dist/client/commands/deposit.d.ts.map +1 -1
  39. package/dist/client/commands/deposit.js +2 -1
  40. package/dist/client/commands/deposit.js.map +1 -1
  41. package/dist/client/commands/repay.d.ts.map +1 -1
  42. package/dist/client/commands/repay.js +2 -1
  43. package/dist/client/commands/repay.js.map +1 -1
  44. package/dist/client/commands/withdraw.d.ts.map +1 -1
  45. package/dist/client/commands/withdraw.js +2 -1
  46. package/dist/client/commands/withdraw.js.map +1 -1
  47. package/dist/leverage/operations.d.ts.map +1 -1
  48. package/dist/leverage/operations.js +8 -5
  49. package/dist/leverage/operations.js.map +1 -1
  50. package/dist/manager/client_kamino_manager.js +10 -3
  51. package/dist/manager/client_kamino_manager.js.map +1 -1
  52. package/dist/utils/index.d.ts +1 -0
  53. package/dist/utils/index.d.ts.map +1 -1
  54. package/dist/utils/index.js +1 -0
  55. package/dist/utils/index.js.map +1 -1
  56. package/dist/utils/managerTypes.d.ts +2 -3
  57. package/dist/utils/managerTypes.d.ts.map +1 -1
  58. package/dist/utils/managerTypes.js +37 -34
  59. package/dist/utils/managerTypes.js.map +1 -1
  60. package/dist/utils/map.d.ts +2 -0
  61. package/dist/utils/map.d.ts.map +1 -0
  62. package/dist/utils/map.js +13 -0
  63. package/dist/utils/map.js.map +1 -0
  64. package/dist/utils/oracle.d.ts +2 -1
  65. package/dist/utils/oracle.d.ts.map +1 -1
  66. package/dist/utils/oracle.js +4 -4
  67. package/dist/utils/oracle.js.map +1 -1
  68. package/dist/utils/vault.js +2 -2
  69. package/dist/utils/vault.js.map +1 -1
  70. package/dist/utils/vaultAllocation.d.ts +21 -0
  71. package/dist/utils/vaultAllocation.d.ts.map +1 -0
  72. package/dist/utils/vaultAllocation.js +71 -0
  73. package/dist/utils/vaultAllocation.js.map +1 -0
  74. package/package.json +2 -2
  75. package/src/@codegen/kvault/accounts/Reserve.ts +1 -1
  76. package/src/@codegen/kvault/accounts/VaultState.ts +16 -16
  77. package/src/@codegen/kvault/errors/custom.ts +14 -0
  78. package/src/@codegen/kvault/types/VaultConfigField.ts +60 -0
  79. package/src/@codegen/kvault/types/index.ts +4 -0
  80. package/src/classes/action.ts +26 -11
  81. package/src/classes/manager.ts +92 -30
  82. package/src/classes/market.ts +15 -9
  83. package/src/classes/vault.ts +125 -42
  84. package/src/classes/vault_types.ts +11 -1
  85. package/src/client/commands/borrow.ts +2 -1
  86. package/src/client/commands/deposit.ts +2 -1
  87. package/src/client/commands/repay.ts +2 -1
  88. package/src/client/commands/withdraw.ts +2 -1
  89. package/src/idl/kvault.json +34 -12
  90. package/src/leverage/operations.ts +9 -10
  91. package/src/manager/client_kamino_manager.ts +15 -3
  92. package/src/utils/index.ts +1 -0
  93. package/src/utils/managerTypes.ts +29 -28
  94. package/src/utils/map.ts +8 -0
  95. package/src/utils/oracle.ts +4 -3
  96. package/src/utils/vault.ts +2 -2
  97. package/src/utils/vaultAllocation.ts +93 -0
@@ -28,7 +28,7 @@ export interface VaultStateFields {
28
28
  tokenAvailable: BN
29
29
  sharesIssued: BN
30
30
  availableCrankFunds: BN
31
- padding0: BN
31
+ unallocatedWeight: BN
32
32
  performanceFeeBps: BN
33
33
  managementFeeBps: BN
34
34
  lastFeeChargeTimestamp: BN
@@ -49,7 +49,7 @@ export interface VaultStateFields {
49
49
  vaultLookupTable: Address
50
50
  vaultFarm: Address
51
51
  creationTimestamp: BN
52
- padding2: BN
52
+ unallocatedTokensCap: BN
53
53
  allocationAdmin: Address
54
54
  padding3: Array<BN>
55
55
  }
@@ -67,7 +67,7 @@ export interface VaultStateJSON {
67
67
  tokenAvailable: string
68
68
  sharesIssued: string
69
69
  availableCrankFunds: string
70
- padding0: string
70
+ unallocatedWeight: string
71
71
  performanceFeeBps: string
72
72
  managementFeeBps: string
73
73
  lastFeeChargeTimestamp: string
@@ -88,7 +88,7 @@ export interface VaultStateJSON {
88
88
  vaultLookupTable: string
89
89
  vaultFarm: string
90
90
  creationTimestamp: string
91
- padding2: string
91
+ unallocatedTokensCap: string
92
92
  allocationAdmin: string
93
93
  padding3: Array<string>
94
94
  }
@@ -106,7 +106,7 @@ export class VaultState {
106
106
  readonly tokenAvailable: BN
107
107
  readonly sharesIssued: BN
108
108
  readonly availableCrankFunds: BN
109
- readonly padding0: BN
109
+ readonly unallocatedWeight: BN
110
110
  readonly performanceFeeBps: BN
111
111
  readonly managementFeeBps: BN
112
112
  readonly lastFeeChargeTimestamp: BN
@@ -127,7 +127,7 @@ export class VaultState {
127
127
  readonly vaultLookupTable: Address
128
128
  readonly vaultFarm: Address
129
129
  readonly creationTimestamp: BN
130
- readonly padding2: BN
130
+ readonly unallocatedTokensCap: BN
131
131
  readonly allocationAdmin: Address
132
132
  readonly padding3: Array<BN>
133
133
 
@@ -148,7 +148,7 @@ export class VaultState {
148
148
  borsh.u64("tokenAvailable"),
149
149
  borsh.u64("sharesIssued"),
150
150
  borsh.u64("availableCrankFunds"),
151
- borsh.u64("padding0"),
151
+ borsh.u64("unallocatedWeight"),
152
152
  borsh.u64("performanceFeeBps"),
153
153
  borsh.u64("managementFeeBps"),
154
154
  borsh.u64("lastFeeChargeTimestamp"),
@@ -169,7 +169,7 @@ export class VaultState {
169
169
  borshAddress("vaultLookupTable"),
170
170
  borshAddress("vaultFarm"),
171
171
  borsh.u64("creationTimestamp"),
172
- borsh.u64("padding2"),
172
+ borsh.u64("unallocatedTokensCap"),
173
173
  borshAddress("allocationAdmin"),
174
174
  borsh.array(borsh.u128(), 242, "padding3"),
175
175
  ])
@@ -187,7 +187,7 @@ export class VaultState {
187
187
  this.tokenAvailable = fields.tokenAvailable
188
188
  this.sharesIssued = fields.sharesIssued
189
189
  this.availableCrankFunds = fields.availableCrankFunds
190
- this.padding0 = fields.padding0
190
+ this.unallocatedWeight = fields.unallocatedWeight
191
191
  this.performanceFeeBps = fields.performanceFeeBps
192
192
  this.managementFeeBps = fields.managementFeeBps
193
193
  this.lastFeeChargeTimestamp = fields.lastFeeChargeTimestamp
@@ -210,7 +210,7 @@ export class VaultState {
210
210
  this.vaultLookupTable = fields.vaultLookupTable
211
211
  this.vaultFarm = fields.vaultFarm
212
212
  this.creationTimestamp = fields.creationTimestamp
213
- this.padding2 = fields.padding2
213
+ this.unallocatedTokensCap = fields.unallocatedTokensCap
214
214
  this.allocationAdmin = fields.allocationAdmin
215
215
  this.padding3 = fields.padding3
216
216
  }
@@ -271,7 +271,7 @@ export class VaultState {
271
271
  tokenAvailable: dec.tokenAvailable,
272
272
  sharesIssued: dec.sharesIssued,
273
273
  availableCrankFunds: dec.availableCrankFunds,
274
- padding0: dec.padding0,
274
+ unallocatedWeight: dec.unallocatedWeight,
275
275
  performanceFeeBps: dec.performanceFeeBps,
276
276
  managementFeeBps: dec.managementFeeBps,
277
277
  lastFeeChargeTimestamp: dec.lastFeeChargeTimestamp,
@@ -296,7 +296,7 @@ export class VaultState {
296
296
  vaultLookupTable: dec.vaultLookupTable,
297
297
  vaultFarm: dec.vaultFarm,
298
298
  creationTimestamp: dec.creationTimestamp,
299
- padding2: dec.padding2,
299
+ unallocatedTokensCap: dec.unallocatedTokensCap,
300
300
  allocationAdmin: dec.allocationAdmin,
301
301
  padding3: dec.padding3,
302
302
  })
@@ -316,7 +316,7 @@ export class VaultState {
316
316
  tokenAvailable: this.tokenAvailable.toString(),
317
317
  sharesIssued: this.sharesIssued.toString(),
318
318
  availableCrankFunds: this.availableCrankFunds.toString(),
319
- padding0: this.padding0.toString(),
319
+ unallocatedWeight: this.unallocatedWeight.toString(),
320
320
  performanceFeeBps: this.performanceFeeBps.toString(),
321
321
  managementFeeBps: this.managementFeeBps.toString(),
322
322
  lastFeeChargeTimestamp: this.lastFeeChargeTimestamp.toString(),
@@ -339,7 +339,7 @@ export class VaultState {
339
339
  vaultLookupTable: this.vaultLookupTable,
340
340
  vaultFarm: this.vaultFarm,
341
341
  creationTimestamp: this.creationTimestamp.toString(),
342
- padding2: this.padding2.toString(),
342
+ unallocatedTokensCap: this.unallocatedTokensCap.toString(),
343
343
  allocationAdmin: this.allocationAdmin,
344
344
  padding3: this.padding3.map((item) => item.toString()),
345
345
  }
@@ -359,7 +359,7 @@ export class VaultState {
359
359
  tokenAvailable: new BN(obj.tokenAvailable),
360
360
  sharesIssued: new BN(obj.sharesIssued),
361
361
  availableCrankFunds: new BN(obj.availableCrankFunds),
362
- padding0: new BN(obj.padding0),
362
+ unallocatedWeight: new BN(obj.unallocatedWeight),
363
363
  performanceFeeBps: new BN(obj.performanceFeeBps),
364
364
  managementFeeBps: new BN(obj.managementFeeBps),
365
365
  lastFeeChargeTimestamp: new BN(obj.lastFeeChargeTimestamp),
@@ -382,7 +382,7 @@ export class VaultState {
382
382
  vaultLookupTable: address(obj.vaultLookupTable),
383
383
  vaultFarm: address(obj.vaultFarm),
384
384
  creationTimestamp: new BN(obj.creationTimestamp),
385
- padding2: new BN(obj.padding2),
385
+ unallocatedTokensCap: new BN(obj.unallocatedTokensCap),
386
386
  allocationAdmin: address(obj.allocationAdmin),
387
387
  padding3: obj.padding3.map((item) => new BN(item)),
388
388
  })
@@ -47,6 +47,7 @@ export type CustomError =
47
47
  | InvestTooSoon
48
48
  | WrongAdminOrAllocationAdmin
49
49
  | ReserveHasNonZeroAllocationOrCTokens
50
+ | DepositAmountGreaterThanRequestedAmount
50
51
 
51
52
  export class DepositAmountsZero extends Error {
52
53
  static readonly code = 7000
@@ -579,6 +580,17 @@ export class ReserveHasNonZeroAllocationOrCTokens extends Error {
579
580
  }
580
581
  }
581
582
 
583
+ export class DepositAmountGreaterThanRequestedAmount extends Error {
584
+ static readonly code = 7048
585
+ readonly code = 7048
586
+ readonly name = "DepositAmountGreaterThanRequestedAmount"
587
+ readonly msg = "Deposit amount is greater than requested amount"
588
+
589
+ constructor(readonly logs?: string[]) {
590
+ super("7048: Deposit amount is greater than requested amount")
591
+ }
592
+ }
593
+
582
594
  export function fromCode(code: number, logs?: string[]): CustomError | null {
583
595
  switch (code) {
584
596
  case 7000:
@@ -677,6 +689,8 @@ export function fromCode(code: number, logs?: string[]): CustomError | null {
677
689
  return new WrongAdminOrAllocationAdmin(logs)
678
690
  case 7047:
679
691
  return new ReserveHasNonZeroAllocationOrCTokens(logs)
692
+ case 7048:
693
+ return new DepositAmountGreaterThanRequestedAmount(logs)
680
694
  }
681
695
 
682
696
  return null
@@ -280,6 +280,52 @@ export class AllocationAdmin {
280
280
  }
281
281
  }
282
282
 
283
+ export interface UnallocatedWeightJSON {
284
+ kind: "UnallocatedWeight"
285
+ }
286
+
287
+ export class UnallocatedWeight {
288
+ static readonly discriminator = 12
289
+ static readonly kind = "UnallocatedWeight"
290
+ readonly discriminator = 12
291
+ readonly kind = "UnallocatedWeight"
292
+
293
+ toJSON(): UnallocatedWeightJSON {
294
+ return {
295
+ kind: "UnallocatedWeight",
296
+ }
297
+ }
298
+
299
+ toEncodable() {
300
+ return {
301
+ UnallocatedWeight: {},
302
+ }
303
+ }
304
+ }
305
+
306
+ export interface UnallocatedTokensCapJSON {
307
+ kind: "UnallocatedTokensCap"
308
+ }
309
+
310
+ export class UnallocatedTokensCap {
311
+ static readonly discriminator = 13
312
+ static readonly kind = "UnallocatedTokensCap"
313
+ readonly discriminator = 13
314
+ readonly kind = "UnallocatedTokensCap"
315
+
316
+ toJSON(): UnallocatedTokensCapJSON {
317
+ return {
318
+ kind: "UnallocatedTokensCap",
319
+ }
320
+ }
321
+
322
+ toEncodable() {
323
+ return {
324
+ UnallocatedTokensCap: {},
325
+ }
326
+ }
327
+ }
328
+
283
329
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
284
330
  export function fromDecoded(obj: any): types.VaultConfigFieldKind {
285
331
  if (typeof obj !== "object") {
@@ -322,6 +368,12 @@ export function fromDecoded(obj: any): types.VaultConfigFieldKind {
322
368
  if ("AllocationAdmin" in obj) {
323
369
  return new AllocationAdmin()
324
370
  }
371
+ if ("UnallocatedWeight" in obj) {
372
+ return new UnallocatedWeight()
373
+ }
374
+ if ("UnallocatedTokensCap" in obj) {
375
+ return new UnallocatedTokensCap()
376
+ }
325
377
 
326
378
  throw new Error("Invalid enum object")
327
379
  }
@@ -366,6 +418,12 @@ export function fromJSON(
366
418
  case "AllocationAdmin": {
367
419
  return new AllocationAdmin()
368
420
  }
421
+ case "UnallocatedWeight": {
422
+ return new UnallocatedWeight()
423
+ }
424
+ case "UnallocatedTokensCap": {
425
+ return new UnallocatedTokensCap()
426
+ }
369
427
  }
370
428
  }
371
429
 
@@ -383,6 +441,8 @@ export function layout(property?: string) {
383
441
  borsh.struct([], "LookupTable"),
384
442
  borsh.struct([], "Farm"),
385
443
  borsh.struct([], "AllocationAdmin"),
444
+ borsh.struct([], "UnallocatedWeight"),
445
+ borsh.struct([], "UnallocatedTokensCap"),
386
446
  ])
387
447
  if (property !== undefined) {
388
448
  return ret.replicate(property)
@@ -64,6 +64,8 @@ export type VaultConfigFieldKind =
64
64
  | VaultConfigField.LookupTable
65
65
  | VaultConfigField.Farm
66
66
  | VaultConfigField.AllocationAdmin
67
+ | VaultConfigField.UnallocatedWeight
68
+ | VaultConfigField.UnallocatedTokensCap
67
69
  export type VaultConfigFieldJSON =
68
70
  | VaultConfigField.PerformanceFeeBpsJSON
69
71
  | VaultConfigField.ManagementFeeBpsJSON
@@ -77,6 +79,8 @@ export type VaultConfigFieldJSON =
77
79
  | VaultConfigField.LookupTableJSON
78
80
  | VaultConfigField.FarmJSON
79
81
  | VaultConfigField.AllocationAdminJSON
82
+ | VaultConfigField.UnallocatedWeightJSON
83
+ | VaultConfigField.UnallocatedTokensCapJSON
80
84
 
81
85
  export { VaultAllocation } from "./VaultAllocation"
82
86
  export type {
@@ -428,12 +428,12 @@ export class KaminoAction {
428
428
  return axn;
429
429
  }
430
430
 
431
- async addScopeRefreshIxs(scope: Scope, tokens: number[], feed: string = 'hubble') {
431
+ async addScopeRefreshIxs(scope: Scope, tokens: number[], scopeConfig: Address) {
432
432
  this.setupIxsLabels.unshift(`refreshScopePrices`);
433
433
  this.setupIxs.unshift(
434
434
  await scope.refreshPriceListIx(
435
435
  {
436
- feed: feed,
436
+ config: scopeConfig,
437
437
  },
438
438
  tokens
439
439
  )
@@ -732,10 +732,15 @@ export class KaminoAction {
732
732
  ...(axn.preLoadedDepositReservesSameTx ? axn.preLoadedDepositReservesSameTx : []),
733
733
  ]),
734
734
  ];
735
- const tokenIds = getTokenIdsForScopeRefresh(axn.kaminoMarket, allReserves);
735
+ const scopeTokensMap = getTokenIdsForScopeRefresh(axn.kaminoMarket, allReserves);
736
736
 
737
- if (tokenIds.length > 0 && scopeRefreshConfig) {
738
- await axn.addScopeRefreshIxs(scopeRefreshConfig.scope, tokenIds, scopeRefreshConfig.scopeFeed);
737
+ if (scopeTokensMap.size > 0 && scopeRefreshConfig) {
738
+ for (const [configPubkey, config] of scopeRefreshConfig.scopeConfigurations) {
739
+ const tokenIds = scopeTokensMap.get(config.oraclePrices);
740
+ if (tokenIds && tokenIds.length > 0) {
741
+ await axn.addScopeRefreshIxs(scopeRefreshConfig.scope, tokenIds, configPubkey);
742
+ }
743
+ }
739
744
  }
740
745
  return axn;
741
746
  }
@@ -924,10 +929,15 @@ export class KaminoAction {
924
929
  ...(axn.preLoadedDepositReservesSameTx ? axn.preLoadedDepositReservesSameTx : []),
925
930
  ]),
926
931
  ];
927
- const tokenIds = getTokenIdsForScopeRefresh(axn.kaminoMarket, allReserves);
932
+ const scopeTokensMap = getTokenIdsForScopeRefresh(axn.kaminoMarket, allReserves);
928
933
 
929
- if (tokenIds.length > 0 && scopeRefreshConfig) {
930
- await axn.addScopeRefreshIxs(scopeRefreshConfig.scope, tokenIds, scopeRefreshConfig.scopeFeed);
934
+ if (scopeTokensMap.size > 0 && scopeRefreshConfig) {
935
+ for (const [configPubkey, config] of scopeRefreshConfig.scopeConfigurations) {
936
+ const tokenIds = scopeTokensMap.get(config.oraclePrices);
937
+ if (tokenIds && tokenIds.length > 0) {
938
+ await axn.addScopeRefreshIxs(scopeRefreshConfig.scope, tokenIds, configPubkey);
939
+ }
940
+ }
931
941
  }
932
942
  return axn;
933
943
  }
@@ -2623,10 +2633,15 @@ export class KaminoAction {
2623
2633
  ...(this.preLoadedDepositReservesSameTx ? this.preLoadedDepositReservesSameTx : []),
2624
2634
  ]),
2625
2635
  ];
2626
- const tokenIds = getTokenIdsForScopeRefresh(this.kaminoMarket, allReserves);
2636
+ const scopeTokensMap = getTokenIdsForScopeRefresh(this.kaminoMarket, allReserves);
2627
2637
 
2628
- if (tokenIds.length > 0 && scopeRefreshConfig) {
2629
- await this.addScopeRefreshIxs(scopeRefreshConfig.scope, tokenIds, scopeRefreshConfig.scopeFeed);
2638
+ if (scopeTokensMap.size > 0 && scopeRefreshConfig) {
2639
+ for (const [configPubkey, config] of scopeRefreshConfig.scopeConfigurations) {
2640
+ const tokenIds = scopeTokensMap.get(config.oraclePrices);
2641
+ if (tokenIds && tokenIds.length > 0) {
2642
+ await this.addScopeRefreshIxs(scopeRefreshConfig.scope, tokenIds, configPubkey);
2643
+ }
2644
+ }
2630
2645
  }
2631
2646
  }
2632
2647
 
@@ -57,6 +57,7 @@ import {
57
57
  Reserve,
58
58
  ReserveWithAddress,
59
59
  ScopeOracleConfig,
60
+ setOrAppend,
60
61
  updateEntireReserveConfigIx,
61
62
  updateLendingMarket,
62
63
  UpdateLendingMarketAccounts,
@@ -77,12 +78,14 @@ import {
77
78
  AcceptVaultOwnershipIxs,
78
79
  APYs,
79
80
  DepositIxs,
81
+ DisinvestAllReservesIxs,
80
82
  InitVaultIxs,
81
83
  ReserveAllocationOverview,
82
84
  SyncVaultLUTIxs,
83
85
  UpdateReserveAllocationIxs,
84
86
  UpdateVaultConfigIxs,
85
87
  UserSharesForVault,
88
+ VaultComputedAllocation,
86
89
  WithdrawAndBlockReserveIxs,
87
90
  WithdrawIxs,
88
91
  } from './vault_types';
@@ -96,6 +99,7 @@ import { TOKEN_PROGRAM_ADDRESS } from '@solana-program/token';
96
99
  import type { AccountInfoBase, AccountInfoWithJsonData, AccountInfoWithPubkey } from '@solana/rpc-types';
97
100
  import { arrayElementConfigItems, ConfigUpdater } from './configItems';
98
101
  import { getFarmIncentives, ReserveIncentives } from '@kamino-finance/farms-sdk/dist/utils/apy';
102
+ import { OracleMappings } from '@kamino-finance/scope-sdk/dist/@codegen/scope/accounts';
99
103
 
100
104
  const base58Decoder = getBase58Decoder();
101
105
 
@@ -267,6 +271,28 @@ export class KaminoManager {
267
271
  return this._vaultClient.updateReserveAllocationIxs(vault, reserveAllocationConfig, signer);
268
272
  }
269
273
 
274
+ /**
275
+ * This method updates the unallocated weight and cap of a vault (both are optional, if not provided the current values will be used)
276
+ * @param vault - the vault to update the unallocated weight and cap for
277
+ * @param [vaultAdminAuthority] - vault admin - a noop vaultAdminAuthority is provided when absent for multisigs
278
+ * @param [unallocatedWeight] - the new unallocated weight to set. If not provided, the current unallocated weight will be used
279
+ * @param [unallocatedCap] - the new unallocated cap to set. If not provided, the current unallocated cap will be used
280
+ * @returns - a list of instructions to update the unallocated weight and cap
281
+ */
282
+ async updateVaultUnallocatedWeightAndCapIxs(
283
+ vault: KaminoVault,
284
+ vaultAdminAuthority?: TransactionSigner,
285
+ unallocatedWeight?: BN,
286
+ unallocatedCap?: BN
287
+ ): Promise<IInstruction[]> {
288
+ return this._vaultClient.updateVaultUnallocatedWeightAndCapIxs(
289
+ vault,
290
+ vaultAdminAuthority,
291
+ unallocatedWeight,
292
+ unallocatedCap
293
+ );
294
+ }
295
+
270
296
  /**
271
297
  * This method removes a reserve from the vault allocation strategy if already part of the allocation strategy
272
298
  * @param vault - vault to remove the reserve from
@@ -376,6 +402,21 @@ export class KaminoManager {
376
402
  return this._vaultClient.withdrawEverythingFromAllReservesAndBlockInvest(vault, vaultReservesMap, payer);
377
403
  }
378
404
 
405
+ /**
406
+ * This method disinvests all the funds from all the reserves and set their weight to 0; for vaults that are managed by external bot/crank, the bot can change the weight and invest in the reserves again
407
+ * @param vault - the vault to disinvest the invested funds from
408
+ * @param [vaultReservesMap] - optional parameter to pass a map of the vault reserves. If not provided, the reserves will be loaded from the vault
409
+ * @param [payer] - optional parameter to pass a different payer for the transaction. If not provided, the admin of the vault will be used; this is the payer for the invest ixs and it should have an ATA and some lamports (2x no_of_reserves) of the token vault
410
+ * @returns - a struct with an instruction to update the reserve allocations to 0 weight and a list of instructions to disinvest the funds in the reserves
411
+ */
412
+ async disinvestAllReservesIxs(
413
+ vault: KaminoVault,
414
+ vaultReservesMap?: Map<Address, KaminoReserve>,
415
+ payer?: TransactionSigner
416
+ ): Promise<DisinvestAllReservesIxs> {
417
+ return this._vaultClient.disinvestAllReservesIxs(vault, vaultReservesMap, payer);
418
+ }
419
+
379
420
  // async closeVault(vault: KaminoVault): Promise<TransactionInstruction> {
380
421
  // return this._vaultClient.closeVaultIx(vault);
381
422
  // }
@@ -398,6 +439,7 @@ export class KaminoManager {
398
439
  * @param lendingMarketOwner - market admin
399
440
  * @param market - lending market which owns the reserve
400
441
  * @param reserve - reserve which to be updated
442
+ * @param oraclePrices - scope OraclePrices account pubkey
401
443
  * @param scopeOracleConfig - new scope oracle config
402
444
  * @param scopeTwapConfig - new scope twap config
403
445
  * @param maxAgeBufferSeconds - buffer to be added to onchain max_age - if oracle price is older than that, txns interacting with the reserve will fail
@@ -407,6 +449,7 @@ export class KaminoManager {
407
449
  lendingMarketOwner: TransactionSigner,
408
450
  market: MarketWithAddress,
409
451
  reserve: ReserveWithAddress,
452
+ oraclePrices: Address,
410
453
  scopeOracleConfig: ScopeOracleConfig,
411
454
  scopeTwapConfig?: ScopeOracleConfig,
412
455
  maxAgeBufferSeconds: number = 20
@@ -423,7 +466,7 @@ export class KaminoManager {
423
466
  }
424
467
 
425
468
  const { scopeConfiguration } = getReserveOracleConfigs({
426
- scopePriceConfigAddress: scopeOracleConfig.scopePriceConfigAddress,
469
+ scopePriceConfigAddress: oraclePrices,
427
470
  scopeChain: [scopeOracleConfig.oracleId],
428
471
  scopeTwapChain: [scopeTwapId],
429
472
  });
@@ -1112,7 +1155,7 @@ export class KaminoManager {
1112
1155
  slot?: Slot,
1113
1156
  vaultReserves?: Map<Address, KaminoReserve>,
1114
1157
  currentSlot?: Slot
1115
- ): Promise<Map<Address, Decimal>> {
1158
+ ): Promise<VaultComputedAllocation> {
1116
1159
  return this._vaultClient.getVaultComputedReservesAllocation(vaultState, slot, vaultReserves, currentSlot);
1117
1160
  }
1118
1161
 
@@ -1325,43 +1368,62 @@ export class KaminoManager {
1325
1368
 
1326
1369
  /**
1327
1370
  * This returns an array of scope oracle configs to be used to set the scope price and twap oracles for a reserve
1328
- * @param feed - scope feed to fetch prices from
1371
+ * @param market kamino market
1329
1372
  * @param cluster - cluster to fetch from, this should be left unchanged unless working on devnet or locally
1330
- * @returns - an array of scope oracle configs
1373
+ * @returns - a map with keys as scope OraclePrices pubkeys and values of scope oracle configs
1331
1374
  */
1332
1375
  async getScopeOracleConfigs(
1333
- feed: string = 'hubble',
1376
+ market: KaminoMarket,
1334
1377
  cluster: ENV = 'mainnet-beta'
1335
- ): Promise<Array<ScopeOracleConfig>> {
1336
- const scopeOracleConfigs: Array<ScopeOracleConfig> = [];
1378
+ ): Promise<Map<Address, ScopeOracleConfig[]>> {
1379
+ const scopeOracleConfigs = new Map<Address, ScopeOracleConfig[]>();
1337
1380
 
1338
1381
  const scope = new Scope(cluster, this._rpc);
1339
- const oracleMappings = await scope.getOracleMappings({ feed: feed });
1340
- const [, feedConfig] = await scope.getFeedConfiguration({ feed: feed });
1341
- const tokenMetadatas = await TokenMetadatas.fetch(this._rpc, feedConfig.tokensMetadata);
1342
- const decoder = new TextDecoder('utf-8');
1382
+ const configs = (await scope.getAllConfigurations()).filter(([_, config]) =>
1383
+ market.scopeFeeds.has(config.oraclePrices)
1384
+ );
1385
+ if (!configs || configs.length === 0) {
1386
+ return scopeOracleConfigs;
1387
+ }
1388
+ const configOracleMappings = await OracleMappings.fetchMultiple(
1389
+ this._rpc,
1390
+ configs.map(([_, config]) => config.oracleMappings),
1391
+ scope.config.programId
1392
+ );
1343
1393
 
1344
- console.log('feedConfig.tokensMetadata', feedConfig.tokensMetadata);
1394
+ const configTokenMetadatas = await TokenMetadatas.fetchMultiple(
1395
+ this._rpc,
1396
+ configs.map(([_, config]) => config.tokensMetadata),
1397
+ scope.config.programId
1398
+ );
1345
1399
 
1346
- if (tokenMetadatas === null) {
1347
- throw new Error('TokenMetadatas not found');
1348
- }
1400
+ const decoder = new TextDecoder('utf-8');
1349
1401
 
1350
- for (let index = 0; index < oracleMappings.priceInfoAccounts.length; index++) {
1351
- if (oracleMappings.priceInfoAccounts[index] !== DEFAULT_PUBLIC_KEY) {
1352
- const name = decoder.decode(Uint8Array.from(tokenMetadatas.metadatasArray[index].name)).replace(/\0/g, '');
1353
- const oracleType = parseOracleType(oracleMappings.priceTypes[index]);
1354
-
1355
- scopeOracleConfigs.push({
1356
- scopePriceConfigAddress: feedConfig.oraclePrices,
1357
- name: name,
1358
- oracleType: oracleType,
1359
- oracleId: index,
1360
- oracleAccount: oracleMappings.priceInfoAccounts[index],
1361
- twapEnabled: oracleMappings.twapEnabled[index] === 1,
1362
- twapSourceId: oracleMappings.twapSource[index],
1363
- max_age: tokenMetadatas.metadatasArray[index].maxAgePriceSlots.toNumber(),
1364
- });
1402
+ for (let i = 0; i < configs.length; i++) {
1403
+ const [configPubkey, config] = configs[i];
1404
+ const oracleMappings = configOracleMappings[i];
1405
+ const tokenMetadatas = configTokenMetadatas[i];
1406
+ if (!oracleMappings) {
1407
+ throw new Error(`OracleMappings account not found for config ${configPubkey}`);
1408
+ }
1409
+ if (!tokenMetadatas) {
1410
+ throw new Error(`TokenMetadatas account not found for config ${configPubkey}`);
1411
+ }
1412
+
1413
+ for (let j = 0; j < oracleMappings.priceInfoAccounts.length; j++) {
1414
+ if (oracleMappings.priceInfoAccounts[j] !== DEFAULT_PUBLIC_KEY) {
1415
+ const name = decoder.decode(Uint8Array.from(tokenMetadatas.metadatasArray[j].name)).replace(/\0/g, '');
1416
+ const oracleType = parseOracleType(oracleMappings.priceTypes[j]);
1417
+ setOrAppend(scopeOracleConfigs, config.oraclePrices, {
1418
+ name: name,
1419
+ oracleType: oracleType,
1420
+ oracleId: j,
1421
+ oracleAccount: oracleMappings.priceInfoAccounts[j],
1422
+ twapEnabled: oracleMappings.twapEnabled[j] === 1,
1423
+ twapSourceId: oracleMappings.twapSource[j],
1424
+ max_age: tokenMetadatas.metadatasArray[j].maxAgePriceSlots.toNumber(),
1425
+ });
1426
+ }
1365
1427
  }
1366
1428
  }
1367
1429
 
@@ -37,6 +37,7 @@ import {
37
37
  ObligationType,
38
38
  PythPrices,
39
39
  referrerTokenStatePda,
40
+ setOrAppend,
40
41
  userMetadataPda,
41
42
  VanillaObligation,
42
43
  } from '../utils';
@@ -88,7 +89,7 @@ export class KaminoMarket {
88
89
  private readonly recentSlotDurationMs: number;
89
90
 
90
91
  // scope feeds used by all market reserves
91
- private readonly scopeFeeds: Set<Address>;
92
+ readonly scopeFeeds: Set<Address>;
92
93
 
93
94
  private constructor(
94
95
  rpc: Rpc<KaminoMarketRpcApi>,
@@ -1578,26 +1579,31 @@ export function getReservesActive(reserves: Map<Address, KaminoReserve>): Map<Ad
1578
1579
  return reservesActive;
1579
1580
  }
1580
1581
 
1581
- export function getTokenIdsForScopeRefresh(kaminoMarket: KaminoMarket, reserves: Address[]): number[] {
1582
- const tokenIds: number[] = [];
1582
+ /**
1583
+ *
1584
+ * @param kaminoMarket
1585
+ * @param reserves
1586
+ */
1587
+ export function getTokenIdsForScopeRefresh(kaminoMarket: KaminoMarket, reserves: Address[]): Map<Address, number[]> {
1588
+ const tokenIds = new Map<Address, number[]>();
1583
1589
 
1584
1590
  for (const reserveAddress of reserves) {
1585
1591
  const reserve = kaminoMarket.getReserveByAddress(reserveAddress);
1586
1592
  if (!reserve) {
1587
1593
  throw new Error(`Reserve not found for reserve ${reserveAddress}`);
1588
1594
  }
1589
-
1590
- if (reserve.state.config.tokenInfo.scopeConfiguration.priceFeed !== DEFAULT_PUBLIC_KEY) {
1595
+ const { scopeConfiguration } = reserve.state.config.tokenInfo;
1596
+ if (scopeConfiguration.priceFeed !== DEFAULT_PUBLIC_KEY) {
1591
1597
  let x = 0;
1592
1598
 
1593
- while (reserve.state.config.tokenInfo.scopeConfiguration.priceChain[x] !== U16_MAX) {
1594
- tokenIds.push(reserve.state.config.tokenInfo.scopeConfiguration.priceChain[x]);
1599
+ while (scopeConfiguration.priceChain[x] !== U16_MAX) {
1600
+ setOrAppend(tokenIds, scopeConfiguration.priceFeed, scopeConfiguration.priceChain[x]);
1595
1601
  x++;
1596
1602
  }
1597
1603
 
1598
1604
  x = 0;
1599
- while (reserve.state.config.tokenInfo.scopeConfiguration.twapChain[x] !== U16_MAX) {
1600
- tokenIds.push(reserve.state.config.tokenInfo.scopeConfiguration.twapChain[x]);
1605
+ while (scopeConfiguration.twapChain[x] !== U16_MAX) {
1606
+ setOrAppend(tokenIds, scopeConfiguration.priceFeed, scopeConfiguration.twapChain[x]);
1601
1607
  x++;
1602
1608
  }
1603
1609
  }