@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.
- package/dist/@codegen/kvault/accounts/Reserve.js +1 -1
- package/dist/@codegen/kvault/accounts/VaultState.d.ts +6 -6
- package/dist/@codegen/kvault/accounts/VaultState.d.ts.map +1 -1
- package/dist/@codegen/kvault/accounts/VaultState.js +12 -12
- package/dist/@codegen/kvault/accounts/VaultState.js.map +1 -1
- package/dist/@codegen/kvault/errors/custom.d.ts +9 -1
- package/dist/@codegen/kvault/errors/custom.d.ts.map +1 -1
- package/dist/@codegen/kvault/errors/custom.js +15 -1
- package/dist/@codegen/kvault/errors/custom.js.map +1 -1
- package/dist/@codegen/kvault/types/VaultConfigField.d.ts +26 -0
- package/dist/@codegen/kvault/types/VaultConfigField.d.ts.map +1 -1
- package/dist/@codegen/kvault/types/VaultConfigField.js +49 -1
- package/dist/@codegen/kvault/types/VaultConfigField.js.map +1 -1
- package/dist/@codegen/kvault/types/index.d.ts +2 -2
- package/dist/@codegen/kvault/types/index.d.ts.map +1 -1
- package/dist/@codegen/kvault/types/index.js.map +1 -1
- package/dist/classes/action.d.ts +1 -1
- package/dist/classes/action.d.ts.map +1 -1
- package/dist/classes/action.js +26 -11
- package/dist/classes/action.js.map +1 -1
- package/dist/classes/manager.d.ts +25 -6
- package/dist/classes/manager.d.ts.map +1 -1
- package/dist/classes/manager.js +59 -27
- package/dist/classes/manager.js.map +1 -1
- package/dist/classes/market.d.ts +7 -2
- package/dist/classes/market.d.ts.map +1 -1
- package/dist/classes/market.js +12 -6
- package/dist/classes/market.js.map +1 -1
- package/dist/classes/vault.d.ts +22 -3
- package/dist/classes/vault.d.ts.map +1 -1
- package/dist/classes/vault.js +73 -40
- package/dist/classes/vault.js.map +1 -1
- package/dist/classes/vault_types.d.ts +9 -1
- package/dist/classes/vault_types.d.ts.map +1 -1
- package/dist/client/commands/borrow.d.ts.map +1 -1
- package/dist/client/commands/borrow.js +2 -1
- package/dist/client/commands/borrow.js.map +1 -1
- package/dist/client/commands/deposit.d.ts.map +1 -1
- package/dist/client/commands/deposit.js +2 -1
- package/dist/client/commands/deposit.js.map +1 -1
- package/dist/client/commands/repay.d.ts.map +1 -1
- package/dist/client/commands/repay.js +2 -1
- package/dist/client/commands/repay.js.map +1 -1
- package/dist/client/commands/withdraw.d.ts.map +1 -1
- package/dist/client/commands/withdraw.js +2 -1
- package/dist/client/commands/withdraw.js.map +1 -1
- package/dist/leverage/operations.d.ts.map +1 -1
- package/dist/leverage/operations.js +8 -5
- package/dist/leverage/operations.js.map +1 -1
- package/dist/manager/client_kamino_manager.js +10 -3
- package/dist/manager/client_kamino_manager.js.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/managerTypes.d.ts +2 -3
- package/dist/utils/managerTypes.d.ts.map +1 -1
- package/dist/utils/managerTypes.js +37 -34
- package/dist/utils/managerTypes.js.map +1 -1
- package/dist/utils/map.d.ts +2 -0
- package/dist/utils/map.d.ts.map +1 -0
- package/dist/utils/map.js +13 -0
- package/dist/utils/map.js.map +1 -0
- package/dist/utils/oracle.d.ts +2 -1
- package/dist/utils/oracle.d.ts.map +1 -1
- package/dist/utils/oracle.js +4 -4
- package/dist/utils/oracle.js.map +1 -1
- package/dist/utils/vault.js +2 -2
- package/dist/utils/vault.js.map +1 -1
- package/dist/utils/vaultAllocation.d.ts +21 -0
- package/dist/utils/vaultAllocation.d.ts.map +1 -0
- package/dist/utils/vaultAllocation.js +71 -0
- package/dist/utils/vaultAllocation.js.map +1 -0
- package/package.json +2 -2
- package/src/@codegen/kvault/accounts/Reserve.ts +1 -1
- package/src/@codegen/kvault/accounts/VaultState.ts +16 -16
- package/src/@codegen/kvault/errors/custom.ts +14 -0
- package/src/@codegen/kvault/types/VaultConfigField.ts +60 -0
- package/src/@codegen/kvault/types/index.ts +4 -0
- package/src/classes/action.ts +26 -11
- package/src/classes/manager.ts +92 -30
- package/src/classes/market.ts +15 -9
- package/src/classes/vault.ts +125 -42
- package/src/classes/vault_types.ts +11 -1
- package/src/client/commands/borrow.ts +2 -1
- package/src/client/commands/deposit.ts +2 -1
- package/src/client/commands/repay.ts +2 -1
- package/src/client/commands/withdraw.ts +2 -1
- package/src/idl/kvault.json +34 -12
- package/src/leverage/operations.ts +9 -10
- package/src/manager/client_kamino_manager.ts +15 -3
- package/src/utils/index.ts +1 -0
- package/src/utils/managerTypes.ts +29 -28
- package/src/utils/map.ts +8 -0
- package/src/utils/oracle.ts +4 -3
- package/src/utils/vault.ts +2 -2
- package/src/utils/vaultAllocation.ts +93 -0
package/src/classes/vault.ts
CHANGED
|
@@ -87,12 +87,14 @@ import {
|
|
|
87
87
|
AcceptVaultOwnershipIxs,
|
|
88
88
|
APYs,
|
|
89
89
|
DepositIxs,
|
|
90
|
+
DisinvestAllReservesIxs,
|
|
90
91
|
InitVaultIxs,
|
|
91
92
|
ReserveAllocationOverview,
|
|
92
93
|
SyncVaultLUTIxs,
|
|
93
94
|
UpdateReserveAllocationIxs,
|
|
94
95
|
UpdateVaultConfigIxs,
|
|
95
96
|
UserSharesForVault,
|
|
97
|
+
VaultComputedAllocation,
|
|
96
98
|
WithdrawAndBlockReserveIxs,
|
|
97
99
|
WithdrawIxs,
|
|
98
100
|
} from './vault_types';
|
|
@@ -121,6 +123,7 @@ import { noopSigner } from '../utils/signer';
|
|
|
121
123
|
import { getExtendLookupTableInstruction } from '@solana-program/address-lookup-table';
|
|
122
124
|
import { Farms } from '@kamino-finance/farms-sdk';
|
|
123
125
|
import { getFarmIncentives } from '@kamino-finance/farms-sdk/dist/utils/apy';
|
|
126
|
+
import { computeReservesAllocation } from '../utils/vaultAllocation';
|
|
124
127
|
|
|
125
128
|
export const kaminoVaultId = address('KvauGMspG5k6rtzrqqn7WNn3oZdyKqLKwK2XWQ8FLjd');
|
|
126
129
|
export const kaminoVaultStagingId = address('stKvQfwRsQiKnLtMNVLHKS3exFJmZFsgfzBPWHECUYK');
|
|
@@ -453,6 +456,50 @@ export class KaminoVaultClient {
|
|
|
453
456
|
return updateReserveAllocationIxs;
|
|
454
457
|
}
|
|
455
458
|
|
|
459
|
+
/**
|
|
460
|
+
* This method updates the unallocated weight and cap of a vault (both are optional, if not provided the current values will be used)
|
|
461
|
+
* @param vault - the vault to update the unallocated weight and cap for
|
|
462
|
+
* @param [vaultAdminAuthority] - vault admin - a noop vaultAdminAuthority is provided when absent for multisigs
|
|
463
|
+
* @param [unallocatedWeight] - the new unallocated weight to set. If not provided, the current unallocated weight will be used
|
|
464
|
+
* @param [unallocatedCap] - the new unallocated cap to set. If not provided, the current unallocated cap will be used
|
|
465
|
+
* @returns - a list of instructions to update the unallocated weight and cap
|
|
466
|
+
*/
|
|
467
|
+
async updateVaultUnallocatedWeightAndCapIxs(
|
|
468
|
+
vault: KaminoVault,
|
|
469
|
+
vaultAdminAuthority?: TransactionSigner,
|
|
470
|
+
unallocatedWeight?: BN,
|
|
471
|
+
unallocatedCap?: BN
|
|
472
|
+
) {
|
|
473
|
+
const vaultState = await vault.getState(this.getConnection());
|
|
474
|
+
|
|
475
|
+
const unallocatedWeightToUse = unallocatedWeight ? unallocatedWeight : vaultState.unallocatedWeight;
|
|
476
|
+
const unallocatedCapToUse = unallocatedCap ? unallocatedCap : vaultState.unallocatedTokensCap;
|
|
477
|
+
|
|
478
|
+
const ixs: IInstruction[] = [];
|
|
479
|
+
|
|
480
|
+
if (!unallocatedWeightToUse.eq(vaultState.unallocatedWeight)) {
|
|
481
|
+
const updateVaultUnallocatedWeightIx = await this.updateVaultConfigIxs(
|
|
482
|
+
vault,
|
|
483
|
+
new VaultConfigField.UnallocatedWeight(),
|
|
484
|
+
unallocatedWeightToUse.toString(),
|
|
485
|
+
vaultAdminAuthority
|
|
486
|
+
);
|
|
487
|
+
ixs.push(updateVaultUnallocatedWeightIx.updateVaultConfigIx);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
if (!unallocatedCapToUse.eq(vaultState.unallocatedTokensCap)) {
|
|
491
|
+
const updateVaultUnallocatedCapIx = await this.updateVaultConfigIxs(
|
|
492
|
+
vault,
|
|
493
|
+
new VaultConfigField.UnallocatedTokensCap(),
|
|
494
|
+
unallocatedCapToUse.toString(),
|
|
495
|
+
vaultAdminAuthority
|
|
496
|
+
);
|
|
497
|
+
ixs.push(updateVaultUnallocatedCapIx.updateVaultConfigIx);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
return ixs;
|
|
501
|
+
}
|
|
502
|
+
|
|
456
503
|
/**
|
|
457
504
|
* This method withdraws all the funds from a reserve and blocks it from being invested by setting its weight and ctoken allocation to 0
|
|
458
505
|
* @param vault - the vault to withdraw the funds from
|
|
@@ -506,7 +553,7 @@ export class KaminoVaultClient {
|
|
|
506
553
|
* @param vault - the vault to withdraw the invested funds from
|
|
507
554
|
* @param [vaultReservesMap] - optional parameter to pass a map of the vault reserves. If not provided, the reserves will be loaded from the vault
|
|
508
555
|
* @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
|
|
509
|
-
* @returns - a struct with an instruction to update the reserve allocation and an
|
|
556
|
+
* @returns - a struct with an instruction to update the reserve allocations (set weight and ctoken allocation to 0) and an a list of instructions to disinvest the funds in the reserves
|
|
510
557
|
*/
|
|
511
558
|
async withdrawEverythingFromAllReservesAndBlockInvest(
|
|
512
559
|
vault: KaminoVault,
|
|
@@ -544,6 +591,59 @@ export class KaminoVaultClient {
|
|
|
544
591
|
return withdrawAndBlockReserveIxs;
|
|
545
592
|
}
|
|
546
593
|
|
|
594
|
+
/**
|
|
595
|
+
* 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
|
|
596
|
+
* @param vault - the vault to disinvest the invested funds from
|
|
597
|
+
* @param [vaultReservesMap] - optional parameter to pass a map of the vault reserves. If not provided, the reserves will be loaded from the vault
|
|
598
|
+
* @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
|
|
599
|
+
* @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
|
|
600
|
+
*/
|
|
601
|
+
async disinvestAllReservesIxs(
|
|
602
|
+
vault: KaminoVault,
|
|
603
|
+
vaultReservesMap?: Map<Address, KaminoReserve>,
|
|
604
|
+
payer?: TransactionSigner
|
|
605
|
+
): Promise<DisinvestAllReservesIxs> {
|
|
606
|
+
const vaultState = await vault.getState(this.getConnection());
|
|
607
|
+
|
|
608
|
+
const reserves = this.getVaultReserves(vaultState);
|
|
609
|
+
const disinvestAllReservesIxs: DisinvestAllReservesIxs = {
|
|
610
|
+
updateReserveAllocationIxs: [],
|
|
611
|
+
investIxs: [],
|
|
612
|
+
};
|
|
613
|
+
|
|
614
|
+
if (!vaultReservesMap) {
|
|
615
|
+
vaultReservesMap = await this.loadVaultReserves(vaultState);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
for (const reserve of reserves) {
|
|
619
|
+
const reserveWithAddress: ReserveWithAddress = {
|
|
620
|
+
address: reserve,
|
|
621
|
+
state: vaultReservesMap.get(reserve)!.state,
|
|
622
|
+
};
|
|
623
|
+
const existingReserveAllocation = vaultState.vaultAllocationStrategy.find(
|
|
624
|
+
(allocation) => allocation.reserve === reserve
|
|
625
|
+
);
|
|
626
|
+
if (!existingReserveAllocation) {
|
|
627
|
+
continue;
|
|
628
|
+
}
|
|
629
|
+
const reserveAllocationConfig = new ReserveAllocationConfig(
|
|
630
|
+
reserveWithAddress,
|
|
631
|
+
0,
|
|
632
|
+
new Decimal(existingReserveAllocation.tokenAllocationCap.toString())
|
|
633
|
+
);
|
|
634
|
+
|
|
635
|
+
// update allocation to have 0 weight and 0 cap
|
|
636
|
+
const updateAllocIxs = await this.updateReserveAllocationIxs(vault, reserveAllocationConfig, payer);
|
|
637
|
+
disinvestAllReservesIxs.updateReserveAllocationIxs.push(updateAllocIxs.updateReserveAllocationIx);
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
const investPayer = payer ? payer : noopSigner(vaultState.vaultAdminAuthority);
|
|
641
|
+
const investIxs = await this.investAllReservesIxs(investPayer, vault);
|
|
642
|
+
disinvestAllReservesIxs.investIxs = investIxs;
|
|
643
|
+
|
|
644
|
+
return disinvestAllReservesIxs;
|
|
645
|
+
}
|
|
646
|
+
|
|
547
647
|
/**
|
|
548
648
|
* This method removes a reserve from the vault allocation strategy if already part of the allocation strategy
|
|
549
649
|
* @param vault - vault to remove the reserve from
|
|
@@ -1354,7 +1454,7 @@ export class KaminoVaultClient {
|
|
|
1354
1454
|
for (let index = 0; index < allReserves.length; index++) {
|
|
1355
1455
|
const reservePubkey = allReserves[index];
|
|
1356
1456
|
const reserveState = allReservesStateMap.get(reservePubkey)!;
|
|
1357
|
-
const computedAllocation = computedReservesAllocation.get(reservePubkey)!;
|
|
1457
|
+
const computedAllocation = computedReservesAllocation.targetReservesAllocation.get(reservePubkey)!;
|
|
1358
1458
|
const currentCTokenAllocation = curentVaultAllocations.get(reservePubkey)!.ctokenAllocation;
|
|
1359
1459
|
const currentAllocationCap = curentVaultAllocations.get(reservePubkey)!.tokenAllocationCap;
|
|
1360
1460
|
|
|
@@ -1790,7 +1890,10 @@ export class KaminoVaultClient {
|
|
|
1790
1890
|
slot?: Slot,
|
|
1791
1891
|
vaultReserves?: Map<Address, KaminoReserve>,
|
|
1792
1892
|
currentSlot?: Slot
|
|
1793
|
-
): Promise<
|
|
1893
|
+
): Promise<VaultComputedAllocation> {
|
|
1894
|
+
// 1. Read the states
|
|
1895
|
+
const holdings = await this.getVaultHoldings(vaultState, slot, vaultReserves, currentSlot);
|
|
1896
|
+
|
|
1794
1897
|
// if there are no vault reserves or all have weight 0 everything has to be in Available
|
|
1795
1898
|
const allReservesPubkeys = this.getVaultReserves(vaultState);
|
|
1796
1899
|
const reservesAllocations = this.getVaultAllocations(vaultState);
|
|
@@ -1803,50 +1906,30 @@ export class KaminoVaultClient {
|
|
|
1803
1906
|
allReservesPubkeys.forEach((reserve) => {
|
|
1804
1907
|
computedHoldings.set(reserve, new Decimal(0));
|
|
1805
1908
|
});
|
|
1806
|
-
return
|
|
1909
|
+
return {
|
|
1910
|
+
targetUnallocatedAmount: holdings.totalAUMIncludingFees.sub(holdings.pendingFees),
|
|
1911
|
+
targetReservesAllocation: computedHoldings,
|
|
1912
|
+
};
|
|
1807
1913
|
}
|
|
1808
1914
|
|
|
1809
|
-
const holdings = await this.getVaultHoldings(vaultState, slot, vaultReserves, currentSlot);
|
|
1810
1915
|
const initialVaultAllocations = this.getVaultAllocations(vaultState);
|
|
1811
1916
|
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
expectedHoldingsDistribution.set(reserve, new Decimal(0));
|
|
1821
|
-
});
|
|
1822
|
-
|
|
1823
|
-
let totalLeftToInvest = holdings.totalAUMIncludingFees.sub(holdings.pendingFees);
|
|
1824
|
-
let currentAllocationSum = totalAllocation;
|
|
1825
|
-
const ONE = new Decimal(1);
|
|
1826
|
-
while (totalLeftToInvest.gt(ONE)) {
|
|
1827
|
-
const totalLeftover = totalLeftToInvest;
|
|
1828
|
-
for (const reserve of allReserves) {
|
|
1829
|
-
const reserveWithWeight = initialVaultAllocations.get(reserve);
|
|
1830
|
-
const targetAllocation = reserveWithWeight!.targetWeight.mul(totalLeftover).div(currentAllocationSum);
|
|
1831
|
-
const reserveCap = reserveWithWeight!.tokenAllocationCap;
|
|
1832
|
-
let amountToInvest = Decimal.min(targetAllocation, totalLeftToInvest);
|
|
1833
|
-
if (reserveCap.gt(ZERO)) {
|
|
1834
|
-
amountToInvest = Decimal.min(amountToInvest, reserveCap);
|
|
1835
|
-
}
|
|
1836
|
-
totalLeftToInvest = totalLeftToInvest.sub(amountToInvest);
|
|
1837
|
-
if (amountToInvest.eq(reserveCap) && reserveCap.gt(ZERO)) {
|
|
1838
|
-
currentAllocationSum = currentAllocationSum.sub(reserveWithWeight!.targetWeight);
|
|
1839
|
-
}
|
|
1840
|
-
const reserveHasPreallocation = expectedHoldingsDistribution.has(reserve);
|
|
1841
|
-
if (reserveHasPreallocation) {
|
|
1842
|
-
expectedHoldingsDistribution.set(reserve, expectedHoldingsDistribution.get(reserve)!.add(amountToInvest));
|
|
1843
|
-
} else {
|
|
1844
|
-
expectedHoldingsDistribution.set(reserve, amountToInvest);
|
|
1845
|
-
}
|
|
1846
|
-
}
|
|
1847
|
-
}
|
|
1917
|
+
// 2. Compute the allocation
|
|
1918
|
+
return this.computeReservesAllocation(
|
|
1919
|
+
holdings.totalAUMIncludingFees.sub(holdings.pendingFees),
|
|
1920
|
+
new Decimal(vaultState.unallocatedWeight.toString()),
|
|
1921
|
+
new Decimal(vaultState.unallocatedTokensCap.toString()),
|
|
1922
|
+
initialVaultAllocations
|
|
1923
|
+
);
|
|
1924
|
+
}
|
|
1848
1925
|
|
|
1849
|
-
|
|
1926
|
+
private computeReservesAllocation(
|
|
1927
|
+
vaultAUM: Decimal,
|
|
1928
|
+
vaultUnallocatedWeight: Decimal,
|
|
1929
|
+
vaultUnallocatedCap: Decimal,
|
|
1930
|
+
initialVaultAllocations: Map<Address, ReserveAllocationOverview>
|
|
1931
|
+
) {
|
|
1932
|
+
return computeReservesAllocation(vaultAUM, vaultUnallocatedWeight, vaultUnallocatedCap, initialVaultAllocations);
|
|
1850
1933
|
}
|
|
1851
1934
|
|
|
1852
1935
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IInstruction } from '@solana/kit';
|
|
1
|
+
import { Address, IInstruction } from '@solana/kit';
|
|
2
2
|
import Decimal from 'decimal.js/decimal';
|
|
3
3
|
|
|
4
4
|
/** the populateLUTIxs should be executed in a separate transaction as we cannot create and populate a lookup table in the same tx */
|
|
@@ -27,11 +27,21 @@ export type WithdrawAndBlockReserveIxs = {
|
|
|
27
27
|
investIxs: IInstruction[];
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
+
export type DisinvestAllReservesIxs = {
|
|
31
|
+
updateReserveAllocationIxs: IInstruction[];
|
|
32
|
+
investIxs: IInstruction[];
|
|
33
|
+
};
|
|
34
|
+
|
|
30
35
|
export type UpdateVaultConfigIxs = {
|
|
31
36
|
updateVaultConfigIx: IInstruction;
|
|
32
37
|
updateLUTIxs: IInstruction[];
|
|
33
38
|
};
|
|
34
39
|
|
|
40
|
+
export type VaultComputedAllocation = {
|
|
41
|
+
targetUnallocatedAmount: Decimal;
|
|
42
|
+
targetReservesAllocation: Map<Address, Decimal>;
|
|
43
|
+
};
|
|
44
|
+
|
|
35
45
|
/** If there are ixs to setup the LUT it means it doesn't already exist and it needs to be created in a separate tx before inserting into it */
|
|
36
46
|
export type SyncVaultLUTIxs = {
|
|
37
47
|
setupLUTIfNeededIxs: IInstruction[];
|
|
@@ -10,6 +10,7 @@ export async function borrow(env: CliEnv, mode: SendTxMode, token: string, borro
|
|
|
10
10
|
const signer = await env.getSigner();
|
|
11
11
|
const programId = getProgramId('staging');
|
|
12
12
|
const kaminoMarket = await getMarket(env.c.rpc, programId);
|
|
13
|
+
const scope = new Scope('mainnet-beta', env.c.rpc);
|
|
13
14
|
const kaminoAction = await KaminoAction.buildBorrowTxns(
|
|
14
15
|
kaminoMarket,
|
|
15
16
|
borrowAmount,
|
|
@@ -17,7 +18,7 @@ export async function borrow(env: CliEnv, mode: SendTxMode, token: string, borro
|
|
|
17
18
|
signer,
|
|
18
19
|
new VanillaObligation(STAGING_LENDING_MARKET),
|
|
19
20
|
true,
|
|
20
|
-
{ scope:
|
|
21
|
+
{ scope, scopeConfigurations: await scope.getAllConfigurations() }
|
|
21
22
|
);
|
|
22
23
|
console.log('User obligation', await kaminoAction.getObligationPda());
|
|
23
24
|
|
|
@@ -10,6 +10,7 @@ export async function deposit(env: CliEnv, mode: SendTxMode, token: string, depo
|
|
|
10
10
|
const signer = await env.getSigner();
|
|
11
11
|
const programId = getProgramId('staging');
|
|
12
12
|
const kaminoMarket = await getMarket(env.c.rpc, programId);
|
|
13
|
+
const scope = new Scope('mainnet-beta', env.c.rpc);
|
|
13
14
|
const kaminoAction = await KaminoAction.buildDepositTxns(
|
|
14
15
|
kaminoMarket,
|
|
15
16
|
depositAmount,
|
|
@@ -17,7 +18,7 @@ export async function deposit(env: CliEnv, mode: SendTxMode, token: string, depo
|
|
|
17
18
|
signer,
|
|
18
19
|
new VanillaObligation(STAGING_LENDING_MARKET),
|
|
19
20
|
true,
|
|
20
|
-
{ scope:
|
|
21
|
+
{ scope, scopeConfigurations: await scope.getAllConfigurations() }
|
|
21
22
|
);
|
|
22
23
|
console.log('User obligation', await kaminoAction.getObligationPda());
|
|
23
24
|
|
|
@@ -10,6 +10,7 @@ export async function repay(env: CliEnv, mode: SendTxMode, token: string, borrow
|
|
|
10
10
|
const signer = await env.getSigner();
|
|
11
11
|
const programId = getProgramId('staging');
|
|
12
12
|
const kaminoMarket = await getMarket(env.c.rpc, programId);
|
|
13
|
+
const scope = new Scope('mainnet-beta', env.c.rpc);
|
|
13
14
|
const kaminoAction = await KaminoAction.buildRepayTxns(
|
|
14
15
|
kaminoMarket,
|
|
15
16
|
borrowAmount,
|
|
@@ -17,7 +18,7 @@ export async function repay(env: CliEnv, mode: SendTxMode, token: string, borrow
|
|
|
17
18
|
signer,
|
|
18
19
|
new VanillaObligation(STAGING_LENDING_MARKET),
|
|
19
20
|
true,
|
|
20
|
-
{ scope:
|
|
21
|
+
{ scope, scopeConfigurations: await scope.getAllConfigurations() },
|
|
21
22
|
await env.c.rpc.getSlot().send()
|
|
22
23
|
);
|
|
23
24
|
console.log('User obligation', await kaminoAction.getObligationPda());
|
|
@@ -10,6 +10,7 @@ export async function withdraw(env: CliEnv, mode: SendTxMode, token: string, dep
|
|
|
10
10
|
const signer = await env.getSigner();
|
|
11
11
|
const programId = getProgramId('staging');
|
|
12
12
|
const kaminoMarket = await getMarket(env.c.rpc, programId);
|
|
13
|
+
const scope = new Scope('mainnet-beta', env.c.rpc);
|
|
13
14
|
const kaminoAction = await KaminoAction.buildWithdrawTxns(
|
|
14
15
|
kaminoMarket,
|
|
15
16
|
depositAmount,
|
|
@@ -17,7 +18,7 @@ export async function withdraw(env: CliEnv, mode: SendTxMode, token: string, dep
|
|
|
17
18
|
signer,
|
|
18
19
|
new VanillaObligation(STAGING_LENDING_MARKET),
|
|
19
20
|
true,
|
|
20
|
-
{ scope:
|
|
21
|
+
{ scope, scopeConfigurations: await scope.getAllConfigurations() }
|
|
21
22
|
);
|
|
22
23
|
console.log('User obligation', await kaminoAction.getObligationPda());
|
|
23
24
|
|
package/src/idl/kvault.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "
|
|
2
|
+
"version": "1.0.0",
|
|
3
3
|
"name": "kamino_vault",
|
|
4
4
|
"instructions": [
|
|
5
5
|
{
|
|
@@ -880,7 +880,7 @@
|
|
|
880
880
|
"type": {
|
|
881
881
|
"array": [
|
|
882
882
|
"u64",
|
|
883
|
-
|
|
883
|
+
115
|
|
884
884
|
]
|
|
885
885
|
}
|
|
886
886
|
},
|
|
@@ -967,7 +967,7 @@
|
|
|
967
967
|
"type": "u64"
|
|
968
968
|
},
|
|
969
969
|
{
|
|
970
|
-
"name": "
|
|
970
|
+
"name": "unallocatedWeight",
|
|
971
971
|
"type": "u64"
|
|
972
972
|
},
|
|
973
973
|
{
|
|
@@ -1068,7 +1068,7 @@
|
|
|
1068
1068
|
"type": "u64"
|
|
1069
1069
|
},
|
|
1070
1070
|
{
|
|
1071
|
-
"name": "
|
|
1071
|
+
"name": "unallocatedTokensCap",
|
|
1072
1072
|
"type": "u64"
|
|
1073
1073
|
},
|
|
1074
1074
|
{
|
|
@@ -1236,7 +1236,7 @@
|
|
|
1236
1236
|
"type": "u16"
|
|
1237
1237
|
},
|
|
1238
1238
|
{
|
|
1239
|
-
"name": "
|
|
1239
|
+
"name": "reserved1",
|
|
1240
1240
|
"docs": [
|
|
1241
1241
|
"[DEPRECATED] Space that used to hold 2 fields:",
|
|
1242
1242
|
"- Boost for side (debt or collateral)",
|
|
@@ -1422,13 +1422,15 @@
|
|
|
1422
1422
|
"type": "u8"
|
|
1423
1423
|
},
|
|
1424
1424
|
{
|
|
1425
|
-
"name": "
|
|
1426
|
-
"
|
|
1427
|
-
"
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1425
|
+
"name": "proposerAuthorityLocked",
|
|
1426
|
+
"docs": [
|
|
1427
|
+
"Boolean flag indicating whether the reserve is locked for the proposer authority.",
|
|
1428
|
+
"",
|
|
1429
|
+
"Once the proposer have finished preparing the reserve, it must be locked to prevent",
|
|
1430
|
+
"further changes to the reserve configuration allowing review and voting on the proposal",
|
|
1431
|
+
"without alteration during the voting period."
|
|
1432
|
+
],
|
|
1433
|
+
"type": "u8"
|
|
1432
1434
|
},
|
|
1433
1435
|
{
|
|
1434
1436
|
"name": "borrowLimitOutsideElevationGroup",
|
|
@@ -1461,6 +1463,15 @@
|
|
|
1461
1463
|
"Only relevant when `autodeleverage_enabled == 1`, and must not be 0 in such case."
|
|
1462
1464
|
],
|
|
1463
1465
|
"type": "u64"
|
|
1466
|
+
},
|
|
1467
|
+
{
|
|
1468
|
+
"name": "debtMaturityTimestamp",
|
|
1469
|
+
"docs": [
|
|
1470
|
+
"The timestamp at which all [Obligation::borrows] using this reserve become liquidatable",
|
|
1471
|
+
"(on the same terms as reserve-wide deleveraging).",
|
|
1472
|
+
"Inactive when zeroed (i.e. debt never matures)."
|
|
1473
|
+
],
|
|
1474
|
+
"type": "u64"
|
|
1464
1475
|
}
|
|
1465
1476
|
]
|
|
1466
1477
|
}
|
|
@@ -1954,6 +1965,12 @@
|
|
|
1954
1965
|
},
|
|
1955
1966
|
{
|
|
1956
1967
|
"name": "AllocationAdmin"
|
|
1968
|
+
},
|
|
1969
|
+
{
|
|
1970
|
+
"name": "UnallocatedWeight"
|
|
1971
|
+
},
|
|
1972
|
+
{
|
|
1973
|
+
"name": "UnallocatedTokensCap"
|
|
1957
1974
|
}
|
|
1958
1975
|
]
|
|
1959
1976
|
}
|
|
@@ -2332,6 +2349,11 @@
|
|
|
2332
2349
|
"code": 7047,
|
|
2333
2350
|
"name": "ReserveHasNonZeroAllocationOrCTokens",
|
|
2334
2351
|
"msg": "Reserve has non-zero allocation or ctokens so cannot be removed"
|
|
2352
|
+
},
|
|
2353
|
+
{
|
|
2354
|
+
"code": 7048,
|
|
2355
|
+
"name": "DepositAmountGreaterThanRequestedAmount",
|
|
2356
|
+
"msg": "Deposit amount is greater than requested amount"
|
|
2335
2357
|
}
|
|
2336
2358
|
]
|
|
2337
2359
|
}
|
|
@@ -1676,18 +1676,17 @@ export const getScopeRefreshIx = async (
|
|
|
1676
1676
|
]),
|
|
1677
1677
|
]
|
|
1678
1678
|
: [...new Set<Address>([collReserve.address, debtReserve.address])];
|
|
1679
|
-
const tokenIds = getTokenIdsForScopeRefresh(market, allReserves);
|
|
1680
1679
|
|
|
1681
1680
|
const scopeRefreshIxs: IInstruction[] = [];
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
tokenIds
|
|
1689
|
-
|
|
1690
|
-
|
|
1681
|
+
const scopeTokensMap = getTokenIdsForScopeRefresh(market, allReserves);
|
|
1682
|
+
|
|
1683
|
+
if (scopeTokensMap.size > 0 && scopeRefreshConfig) {
|
|
1684
|
+
for (const [configPubkey, config] of scopeRefreshConfig.scopeConfigurations) {
|
|
1685
|
+
const tokenIds = scopeTokensMap.get(config.oraclePrices);
|
|
1686
|
+
if (tokenIds && tokenIds.length > 0) {
|
|
1687
|
+
scopeRefreshIxs.push(await scopeRefreshConfig.scope.refreshPriceListIx({ config: configPubkey }, tokenIds));
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1691
1690
|
}
|
|
1692
1691
|
|
|
1693
1692
|
return scopeRefreshIxs;
|
|
@@ -1502,8 +1502,9 @@ async function main() {
|
|
|
1502
1502
|
|
|
1503
1503
|
commands
|
|
1504
1504
|
.command('get-oracle-mappings')
|
|
1505
|
+
.requiredOption('--lending-market <string>', 'Lending Market Address')
|
|
1505
1506
|
.option(`--staging`, 'If true, will use the staging programs')
|
|
1506
|
-
.action(async ({ staging }) => {
|
|
1507
|
+
.action(async ({ staging, lendingMarket }) => {
|
|
1507
1508
|
const env = await initEnv(staging);
|
|
1508
1509
|
const kaminoManager = new KaminoManager(
|
|
1509
1510
|
env.c.rpc,
|
|
@@ -1511,10 +1512,21 @@ async function main() {
|
|
|
1511
1512
|
env.klendProgramId,
|
|
1512
1513
|
env.kvaultProgramId
|
|
1513
1514
|
);
|
|
1515
|
+
const market = await KaminoMarket.load(
|
|
1516
|
+
env.c.rpc,
|
|
1517
|
+
address(lendingMarket),
|
|
1518
|
+
DEFAULT_RECENT_SLOT_DURATION_MS,
|
|
1519
|
+
env.klendProgramId
|
|
1520
|
+
);
|
|
1521
|
+
if (!market) {
|
|
1522
|
+
throw Error(`Lending market ${lendingMarket} not found`);
|
|
1523
|
+
}
|
|
1514
1524
|
|
|
1515
1525
|
console.log('Getting oracle mappings');
|
|
1516
|
-
const oracleConfigs = await kaminoManager.getScopeOracleConfigs();
|
|
1517
|
-
|
|
1526
|
+
const oracleConfigs = await kaminoManager.getScopeOracleConfigs(market);
|
|
1527
|
+
for (const [oraclePrices, configs] of oracleConfigs.entries()) {
|
|
1528
|
+
console.log(`OraclePrices pubkey: ${oraclePrices}`, 'Configs:', JSON.parse(JSON.stringify(configs)));
|
|
1529
|
+
}
|
|
1518
1530
|
});
|
|
1519
1531
|
|
|
1520
1532
|
commands
|
package/src/utils/index.ts
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
WithdrawalCaps,
|
|
14
14
|
} from '../@codegen/klend/types';
|
|
15
15
|
import Decimal from 'decimal.js';
|
|
16
|
-
import { Fraction, ZERO_FRACTION } from '../classes
|
|
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';
|
|
@@ -22,7 +22,6 @@ import { OracleType } from '@kamino-finance/scope-sdk/dist/@codegen/scope/types'
|
|
|
22
22
|
import { LendingMarket } from '../lib';
|
|
23
23
|
|
|
24
24
|
export type ScopeOracleConfig = {
|
|
25
|
-
scopePriceConfigAddress: Address;
|
|
26
25
|
name: string;
|
|
27
26
|
oracleType: string;
|
|
28
27
|
oracleId: number;
|
|
@@ -80,7 +79,7 @@ export class AssetReserveConfig implements AssetConfig {
|
|
|
80
79
|
this.mintTokenProgram = fields.mintTokenProgram;
|
|
81
80
|
|
|
82
81
|
// TODO: verify defaults and ensure opinionated
|
|
83
|
-
this.assetReserveConfigParams =
|
|
82
|
+
this.assetReserveConfigParams = getDefaultConfigParams();
|
|
84
83
|
this.assetReserveConfigParams.priceFeed = fields.priceFeed;
|
|
85
84
|
this.assetReserveConfigParams.loanToValuePct = fields.loanToValuePct;
|
|
86
85
|
this.assetReserveConfigParams.liquidationThresholdPct = fields.liquidationThresholdPct;
|
|
@@ -114,7 +113,7 @@ export class AssetReserveConfigCli implements AssetConfig {
|
|
|
114
113
|
this.reserveConfig = reserveConfig;
|
|
115
114
|
this.tokenName = '';
|
|
116
115
|
this.mintDecimals = 0;
|
|
117
|
-
this.assetReserveConfigParams =
|
|
116
|
+
this.assetReserveConfigParams = getDefaultConfigParams();
|
|
118
117
|
this.mint = mint;
|
|
119
118
|
this.mintTokenProgram = mintTokenProgram;
|
|
120
119
|
}
|
|
@@ -160,7 +159,7 @@ export class CollateralConfig implements AssetConfig {
|
|
|
160
159
|
this.mintTokenProgram = fields.mintTokenProgram;
|
|
161
160
|
|
|
162
161
|
// TODO: verify defaults and ensure opinionated
|
|
163
|
-
this.assetReserveConfigParams =
|
|
162
|
+
this.assetReserveConfigParams = getDefaultConfigParams();
|
|
164
163
|
this.assetReserveConfigParams.priceFeed = fields.priceFeed;
|
|
165
164
|
this.assetReserveConfigParams.loanToValuePct = fields.loanToValuePct;
|
|
166
165
|
this.assetReserveConfigParams.liquidationThresholdPct = fields.liquidationThresholdPct;
|
|
@@ -207,7 +206,7 @@ export class DebtConfig implements AssetConfig {
|
|
|
207
206
|
this.debtWithdrawalCapConfigCapacity = fields.debtWithdrawalCapConfigCapacity;
|
|
208
207
|
|
|
209
208
|
// TODO: verify defaults and ensure opinionated
|
|
210
|
-
this.assetReserveConfigParams =
|
|
209
|
+
this.assetReserveConfigParams = getDefaultConfigParams();
|
|
211
210
|
this.assetReserveConfigParams.priceFeed = fields.priceFeed;
|
|
212
211
|
this.assetReserveConfigParams.borrowRateCurve = fields.borrowRateCurve;
|
|
213
212
|
}
|
|
@@ -254,28 +253,30 @@ export type AssetReserveConfigParams = {
|
|
|
254
253
|
borrowRateCurve: BorrowRateCurve;
|
|
255
254
|
};
|
|
256
255
|
|
|
257
|
-
export const
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
256
|
+
export const getDefaultConfigParams = (): AssetReserveConfigParams => {
|
|
257
|
+
return {
|
|
258
|
+
loanToValuePct: 70,
|
|
259
|
+
maxLiquidationBonusBps: 500,
|
|
260
|
+
minLiquidationBonusBps: 200,
|
|
261
|
+
badDebtLiquidationBonusBps: 10,
|
|
262
|
+
liquidationThresholdPct: 75,
|
|
263
|
+
borrowFeeSf: ZERO_FRACTION,
|
|
264
|
+
flashLoanFeeSf: ZERO_FRACTION,
|
|
265
|
+
protocolTakeRate: 0,
|
|
266
|
+
elevationGroups: new Array(20).fill(0),
|
|
267
|
+
priceFeed: null,
|
|
268
|
+
borrowLimit: new Decimal(1000.0),
|
|
269
|
+
depositLimit: new Decimal(1000.0),
|
|
270
|
+
borrowRateCurve: new BorrowRateCurve({
|
|
271
|
+
points: [
|
|
272
|
+
new CurvePoint({ utilizationRateBps: 0, borrowRateBps: 1000 }),
|
|
273
|
+
new CurvePoint({ utilizationRateBps: 10000, borrowRateBps: 1000 }),
|
|
274
|
+
...Array(9).fill(new CurvePoint({ utilizationRateBps: 10000, borrowRateBps: 1000 })),
|
|
275
|
+
],
|
|
276
|
+
} as BorrowRateCurveFields),
|
|
277
|
+
maxAgePriceSeconds: 180,
|
|
278
|
+
maxAgeTwapSeconds: 240,
|
|
279
|
+
};
|
|
279
280
|
};
|
|
280
281
|
|
|
281
282
|
export const encodeTokenName = (tokenName: string): number[] => {
|
package/src/utils/map.ts
ADDED
package/src/utils/oracle.ts
CHANGED
|
@@ -7,11 +7,12 @@ import { parseTokenSymbol } from '../classes';
|
|
|
7
7
|
import { Reserve } from '../lib';
|
|
8
8
|
import { batchFetch } from '@kamino-finance/kliquidity-sdk';
|
|
9
9
|
import BN from 'bn.js';
|
|
10
|
-
import { priceUpdateV2 } from '../@codegen/pyth_rec/accounts
|
|
11
|
-
import { AggregatorAccountData } from '../@codegen/switchboard_v2/accounts
|
|
10
|
+
import { priceUpdateV2 } from '../@codegen/pyth_rec/accounts';
|
|
11
|
+
import { AggregatorAccountData } from '../@codegen/switchboard_v2/accounts';
|
|
12
12
|
import { Buffer } from 'buffer';
|
|
13
13
|
import { getLatestAggregatorValue } from './switchboard';
|
|
14
14
|
import { PROGRAM_ID as SWITCHBOARD_V2_PROGRAM_ID } from '../@codegen/switchboard_v2/programId';
|
|
15
|
+
import { Configuration } from '@kamino-finance/scope-sdk/dist/@codegen/scope/accounts/Configuration';
|
|
15
16
|
|
|
16
17
|
// validate price confidence - confidence/price ratio should be less than 2%
|
|
17
18
|
export const MAX_CONFIDENCE_PERCENTAGE: Decimal = new Decimal('2');
|
|
@@ -39,7 +40,7 @@ export type CandidatePrice = {
|
|
|
39
40
|
|
|
40
41
|
export type ScopePriceRefreshConfig = {
|
|
41
42
|
scope: Scope;
|
|
42
|
-
|
|
43
|
+
scopeConfigurations: [Address, Configuration][];
|
|
43
44
|
};
|
|
44
45
|
|
|
45
46
|
export function getTokenOracleDataSync(allOracleAccounts: AllOracleAccounts, reserves: Reserve[]) {
|
package/src/utils/vault.ts
CHANGED
|
@@ -21,7 +21,8 @@ export function decodeVaultState(data: Buffer): VaultState {
|
|
|
21
21
|
tokenAvailable: dec.tokenAvailable,
|
|
22
22
|
sharesIssued: dec.sharesIssued,
|
|
23
23
|
availableCrankFunds: dec.availableCrankFunds,
|
|
24
|
-
|
|
24
|
+
unallocatedWeight: dec.unallocatedWeight,
|
|
25
|
+
unallocatedTokensCap: dec.unallocatedTokensCap,
|
|
25
26
|
performanceFeeBps: dec.performanceFeeBps,
|
|
26
27
|
managementFeeBps: dec.managementFeeBps,
|
|
27
28
|
lastFeeChargeTimestamp: dec.lastFeeChargeTimestamp,
|
|
@@ -44,7 +45,6 @@ export function decodeVaultState(data: Buffer): VaultState {
|
|
|
44
45
|
vaultLookupTable: dec.vaultLookupTable,
|
|
45
46
|
vaultFarm: dec.vaultFarm,
|
|
46
47
|
creationTimestamp: dec.creationTimestamp,
|
|
47
|
-
padding2: dec.padding2,
|
|
48
48
|
allocationAdmin: dec.allocationAdmin,
|
|
49
49
|
padding3: dec.padding3,
|
|
50
50
|
});
|