@kamino-finance/klend-sdk 6.0.0 → 6.0.2-beta.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/classes/manager.d.ts +20 -2
- package/dist/classes/manager.d.ts.map +1 -1
- package/dist/classes/manager.js +63 -3
- package/dist/classes/manager.js.map +1 -1
- package/dist/classes/market.d.ts +2 -4
- package/dist/classes/market.d.ts.map +1 -1
- package/dist/classes/market.js +10 -19
- package/dist/classes/market.js.map +1 -1
- package/dist/classes/vault.d.ts +12 -1
- package/dist/classes/vault.d.ts.map +1 -1
- package/dist/classes/vault.js +28 -3
- package/dist/classes/vault.js.map +1 -1
- package/dist/client/tx/multisig.d.ts.map +1 -1
- package/dist/client/tx/multisig.js +2 -5
- package/dist/client/tx/multisig.js.map +1 -1
- package/dist/manager/client_kamino_manager.js +25 -0
- package/dist/manager/client_kamino_manager.js.map +1 -1
- package/dist/manager/tx/multisig.d.ts.map +1 -1
- package/dist/manager/tx/multisig.js +2 -5
- package/dist/manager/tx/multisig.js.map +1 -1
- package/dist/utils/accountListing.d.ts.map +1 -1
- package/dist/utils/accountListing.js +6 -8
- package/dist/utils/accountListing.js.map +1 -1
- package/dist/utils/managerTypes.d.ts +1 -0
- package/dist/utils/managerTypes.d.ts.map +1 -1
- package/dist/utils/managerTypes.js +2 -1
- package/dist/utils/managerTypes.js.map +1 -1
- package/package.json +1 -4
- package/src/classes/manager.ts +89 -4
- package/src/classes/market.ts +11 -22
- package/src/classes/vault.ts +33 -4
- package/src/client/tx/multisig.ts +4 -2
- package/src/manager/client_kamino_manager.ts +31 -0
- package/src/manager/tx/multisig.ts +4 -2
- package/src/utils/accountListing.ts +7 -6
- package/src/utils/managerTypes.ts +3 -1
package/src/classes/manager.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
GetProgramAccountsMemcmpFilter,
|
|
13
13
|
ProgramDerivedAddress,
|
|
14
14
|
Base58EncodedBytes,
|
|
15
|
+
getBase58Decoder,
|
|
15
16
|
} from '@solana/kit';
|
|
16
17
|
import {
|
|
17
18
|
KaminoVault,
|
|
@@ -70,7 +71,6 @@ import BN from 'bn.js';
|
|
|
70
71
|
import { ReserveConfig, UpdateLendingMarketMode, UpdateLendingMarketModeKind } from '../@codegen/klend/types';
|
|
71
72
|
import Decimal from 'decimal.js';
|
|
72
73
|
import { VaultState } from '../@codegen/kvault/accounts';
|
|
73
|
-
import bs58 from 'bs58';
|
|
74
74
|
import { getProgramAccounts } from '../utils/rpc';
|
|
75
75
|
import { VaultConfigField, VaultConfigFieldKind } from '../@codegen/kvault/types';
|
|
76
76
|
import {
|
|
@@ -86,7 +86,7 @@ import {
|
|
|
86
86
|
WithdrawAndBlockReserveIxs,
|
|
87
87
|
WithdrawIxs,
|
|
88
88
|
} from './vault_types';
|
|
89
|
-
import { FarmState } from '@kamino-finance/farms-sdk/dist';
|
|
89
|
+
import { FarmIncentives, Farms, FarmState } from '@kamino-finance/farms-sdk/dist';
|
|
90
90
|
import { getSquadsMultisigAdminsAndThreshold, walletIsSquadsMultisig, WalletType } from '../utils/multisig';
|
|
91
91
|
import { decodeVaultState } from '../utils/vault';
|
|
92
92
|
import { noopSigner } from '../utils/signer';
|
|
@@ -95,6 +95,9 @@ import { SYSVAR_RENT_ADDRESS } from '@solana/sysvars';
|
|
|
95
95
|
import { TOKEN_PROGRAM_ADDRESS } from '@solana-program/token';
|
|
96
96
|
import type { AccountInfoBase, AccountInfoWithJsonData, AccountInfoWithPubkey } from '@solana/rpc-types';
|
|
97
97
|
import { arrayElementConfigItems, ConfigUpdater } from './configItems';
|
|
98
|
+
import { getFarmIncentives, ReserveIncentives } from '@kamino-finance/farms-sdk/dist/utils/apy';
|
|
99
|
+
|
|
100
|
+
const base58Decoder = getBase58Decoder();
|
|
98
101
|
|
|
99
102
|
/**
|
|
100
103
|
* KaminoManager is a class that provides a high-level interface to interact with the Kamino Lend and Kamino Vault programs, in order to create and manage a market, as well as vaults
|
|
@@ -768,7 +771,7 @@ export class KaminoManager {
|
|
|
768
771
|
{
|
|
769
772
|
memcmp: {
|
|
770
773
|
offset: 0n,
|
|
771
|
-
bytes:
|
|
774
|
+
bytes: base58Decoder.decode(VaultState.discriminator) as Base58EncodedBytes,
|
|
772
775
|
encoding: 'base58',
|
|
773
776
|
},
|
|
774
777
|
},
|
|
@@ -1065,7 +1068,7 @@ export class KaminoManager {
|
|
|
1065
1068
|
}
|
|
1066
1069
|
|
|
1067
1070
|
/**
|
|
1068
|
-
* This will compute the PDA that is used as delegatee in Farms program to compute the user state PDA
|
|
1071
|
+
* This will compute the PDA that is used as delegatee in Farms program to compute the user state PDA for vault depositor investing in vault with reserve having a supply farm
|
|
1069
1072
|
*/
|
|
1070
1073
|
computeUserFarmStateForUserInVault(
|
|
1071
1074
|
farmsProgramId: Address,
|
|
@@ -1076,6 +1079,88 @@ export class KaminoManager {
|
|
|
1076
1079
|
return this._vaultClient.computeUserFarmStateDelegateePDAForUserInVault(farmsProgramId, reserve, vault, user);
|
|
1077
1080
|
}
|
|
1078
1081
|
|
|
1082
|
+
/**
|
|
1083
|
+
* Read the APY of the farm built on top of the vault (farm in vaultState.vaultFarm)
|
|
1084
|
+
* @param vault - the vault to read the farm APY for
|
|
1085
|
+
* @param vaultTokenPrice - the price of the vault token in USD (e.g. 1.0 for USDC)
|
|
1086
|
+
* @param [slot] - the slot to read the farm APY for. Optional. If not provided, the function will read the current slot
|
|
1087
|
+
* @returns the APY of the farm built on top of the vault
|
|
1088
|
+
*/
|
|
1089
|
+
async getVaultFarmRewardsAPY(vault: KaminoVault, vaultTokenPrice: Decimal, slot?: Slot): Promise<FarmIncentives> {
|
|
1090
|
+
return this._vaultClient.getVaultRewardsAPY(vault, vaultTokenPrice, slot);
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
/**
|
|
1094
|
+
* This will return the APY of the reserve farms (debt and supply)
|
|
1095
|
+
* @param reserve - the reserve to get the farms APY for
|
|
1096
|
+
* @param reserveTokenPrice - the price of the reserve token in USD (e.g. 1.0 for USDC)
|
|
1097
|
+
* @param [reserveState] - the reserve state. Optional. If not provided, the function will fetch the reserve state
|
|
1098
|
+
* @param [kaminoMarket] - the kamino market. Optional. If not provided, the function will fetch the kamino market
|
|
1099
|
+
* @returns the APY of the farm built on top of the reserve
|
|
1100
|
+
*/
|
|
1101
|
+
async getReserveFarmRewardsAPY(
|
|
1102
|
+
reserve: Address,
|
|
1103
|
+
reserveTokenPrice: Decimal,
|
|
1104
|
+
reserveState?: Reserve,
|
|
1105
|
+
kaminoMarket?: KaminoMarket
|
|
1106
|
+
): Promise<ReserveIncentives> {
|
|
1107
|
+
const reserveIncentives: ReserveIncentives = {
|
|
1108
|
+
collateralFarmIncentives: null,
|
|
1109
|
+
debtFarmIncentives: null,
|
|
1110
|
+
};
|
|
1111
|
+
|
|
1112
|
+
console.log("this._kaminoLendProgramId", this._kaminoLendProgramId.toString());
|
|
1113
|
+
const reserveAccount = reserveState
|
|
1114
|
+
? reserveState
|
|
1115
|
+
: await Reserve.fetch(this._rpc, reserve, this._kaminoLendProgramId);
|
|
1116
|
+
if (!reserveAccount) {
|
|
1117
|
+
throw new Error(`Reserve ${reserve} not found`);
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
let market = kaminoMarket;
|
|
1121
|
+
if (!market) {
|
|
1122
|
+
const fetckedMarket = await KaminoMarket.load(this._rpc, reserveAccount.lendingMarket, 450);
|
|
1123
|
+
if (!fetckedMarket) {
|
|
1124
|
+
throw new Error(`Market ${reserveAccount.lendingMarket} not found`);
|
|
1125
|
+
}
|
|
1126
|
+
market = fetckedMarket;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
const kaminoReserve = market.getReserveByAddress(reserve);
|
|
1130
|
+
if (!kaminoReserve) {
|
|
1131
|
+
throw new Error(`Strategy state not found for strategy: ${reserve}`);
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
const farmCollateral = kaminoReserve.state.farmCollateral;
|
|
1135
|
+
const farmDebt = kaminoReserve.state.farmDebt;
|
|
1136
|
+
|
|
1137
|
+
const stakedTokenMintDecimals = kaminoReserve.getMintDecimals();
|
|
1138
|
+
const reserveCtokenPrice = reserveTokenPrice.div(kaminoReserve.getCollateralExchangeRate());
|
|
1139
|
+
|
|
1140
|
+
const farmsClient = new Farms(this._rpc);
|
|
1141
|
+
if (farmCollateral !== DEFAULT_PUBLIC_KEY) {
|
|
1142
|
+
const farmIncentivesCollateral = await getFarmIncentives(
|
|
1143
|
+
farmsClient,
|
|
1144
|
+
farmCollateral,
|
|
1145
|
+
reserveCtokenPrice,
|
|
1146
|
+
6 // all cTokens have 6 decimals
|
|
1147
|
+
);
|
|
1148
|
+
reserveIncentives.collateralFarmIncentives = farmIncentivesCollateral;
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
if (farmDebt !== DEFAULT_PUBLIC_KEY) {
|
|
1152
|
+
const farmIncentivesDebt = await getFarmIncentives(
|
|
1153
|
+
farmsClient,
|
|
1154
|
+
farmDebt,
|
|
1155
|
+
reserveTokenPrice,
|
|
1156
|
+
stakedTokenMintDecimals
|
|
1157
|
+
);
|
|
1158
|
+
reserveIncentives.debtFarmIncentives = farmIncentivesDebt;
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
return reserveIncentives;
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1079
1164
|
/**
|
|
1080
1165
|
* This will load the onchain state for all the reserves that the vault has allocations for
|
|
1081
1166
|
* @param vaultState - the vault state to load reserves for
|
package/src/classes/market.ts
CHANGED
|
@@ -4,8 +4,8 @@ import {
|
|
|
4
4
|
Base58EncodedBytes,
|
|
5
5
|
Commitment,
|
|
6
6
|
GetAccountInfoApi,
|
|
7
|
-
getAddressEncoder,
|
|
8
7
|
GetBalanceApi,
|
|
8
|
+
getBase58Decoder,
|
|
9
9
|
GetMinimumBalanceForRentExemptionApi,
|
|
10
10
|
GetMultipleAccountsApi,
|
|
11
11
|
GetProgramAccountsApi,
|
|
@@ -40,8 +40,6 @@ import {
|
|
|
40
40
|
userMetadataPda,
|
|
41
41
|
VanillaObligation,
|
|
42
42
|
} from '../utils';
|
|
43
|
-
import base58 from 'bs58';
|
|
44
|
-
import bs58 from 'bs58';
|
|
45
43
|
import BN from 'bn.js';
|
|
46
44
|
import Decimal from 'decimal.js';
|
|
47
45
|
import { FarmState } from '@kamino-finance/farms-sdk';
|
|
@@ -63,7 +61,7 @@ export type KaminoMarketRpcApi = GetAccountInfoApi &
|
|
|
63
61
|
GetTokenAccountBalanceApi &
|
|
64
62
|
GetBalanceApi;
|
|
65
63
|
|
|
66
|
-
const
|
|
64
|
+
const base58Decoder = getBase58Decoder();
|
|
67
65
|
|
|
68
66
|
export interface ReserveRewardInfo {
|
|
69
67
|
rewardsPerSecond: Decimal; // not lamport
|
|
@@ -614,7 +612,7 @@ export class KaminoMarket {
|
|
|
614
612
|
filters.push({
|
|
615
613
|
memcmp: {
|
|
616
614
|
offset: 8n,
|
|
617
|
-
bytes:
|
|
615
|
+
bytes: base58Decoder.decode(new BN(tag).toBuffer()) as Base58EncodedBytes,
|
|
618
616
|
encoding: 'base58',
|
|
619
617
|
},
|
|
620
618
|
});
|
|
@@ -688,7 +686,7 @@ export class KaminoMarket {
|
|
|
688
686
|
filters.push({
|
|
689
687
|
memcmp: {
|
|
690
688
|
offset: 8n,
|
|
691
|
-
bytes:
|
|
689
|
+
bytes: base58Decoder.decode(new BN(tag).toBuffer()) as Base58EncodedBytes,
|
|
692
690
|
encoding: 'base58',
|
|
693
691
|
},
|
|
694
692
|
});
|
|
@@ -754,7 +752,7 @@ export class KaminoMarket {
|
|
|
754
752
|
{
|
|
755
753
|
memcmp: {
|
|
756
754
|
offset: 8n,
|
|
757
|
-
bytes:
|
|
755
|
+
bytes: base58Decoder.decode(new BN(tag).toBuffer()) as Base58EncodedBytes,
|
|
758
756
|
encoding: 'base58',
|
|
759
757
|
},
|
|
760
758
|
},
|
|
@@ -886,7 +884,7 @@ export class KaminoMarket {
|
|
|
886
884
|
{
|
|
887
885
|
memcmp: {
|
|
888
886
|
offset: 0n,
|
|
889
|
-
bytes:
|
|
887
|
+
bytes: base58Decoder.decode(Obligation.discriminator) as Base58EncodedBytes,
|
|
890
888
|
encoding: 'base58',
|
|
891
889
|
},
|
|
892
890
|
},
|
|
@@ -1046,7 +1044,7 @@ export class KaminoMarket {
|
|
|
1046
1044
|
{
|
|
1047
1045
|
memcmp: {
|
|
1048
1046
|
offset: 8n,
|
|
1049
|
-
bytes:
|
|
1047
|
+
bytes: base58Decoder.decode(new BN(tag).toBuffer()) as Base58EncodedBytes,
|
|
1050
1048
|
encoding: 'base58',
|
|
1051
1049
|
},
|
|
1052
1050
|
},
|
|
@@ -1215,21 +1213,12 @@ export class KaminoMarket {
|
|
|
1215
1213
|
return referrerFeesCumulativeForMints;
|
|
1216
1214
|
}
|
|
1217
1215
|
|
|
1218
|
-
|
|
1219
|
-
return baseUrl
|
|
1216
|
+
getReferrerUrl(baseUrl: string, referrer: Address) {
|
|
1217
|
+
return `${baseUrl}${referrer.toString()}`;
|
|
1220
1218
|
}
|
|
1221
1219
|
|
|
1222
|
-
|
|
1223
|
-
return
|
|
1224
|
-
}
|
|
1225
|
-
|
|
1226
|
-
async encodeReferrer(referrer: Address) {
|
|
1227
|
-
return bs58.encode(Buffer.from(addressEncoder.encode(referrer)));
|
|
1228
|
-
}
|
|
1229
|
-
|
|
1230
|
-
async decodeReferrer(encoded_referrer: string) {
|
|
1231
|
-
const referrer_buffer = bs58.decode(encoded_referrer);
|
|
1232
|
-
return address(referrer_buffer.toString());
|
|
1220
|
+
getReferrerFromUrl(baseUrl: string, url: string) {
|
|
1221
|
+
return address(url.split(baseUrl)[1]);
|
|
1233
1222
|
}
|
|
1234
1223
|
|
|
1235
1224
|
/**
|
package/src/classes/vault.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
generateKeyPairSigner,
|
|
10
10
|
GetAccountInfoApi,
|
|
11
11
|
getAddressEncoder,
|
|
12
|
+
getBase58Decoder,
|
|
12
13
|
GetProgramAccountsDatasizeFilter,
|
|
13
14
|
GetProgramAccountsMemcmpFilter,
|
|
14
15
|
getProgramDerivedAddress,
|
|
@@ -81,7 +82,6 @@ import {
|
|
|
81
82
|
U64_MAX,
|
|
82
83
|
VAULT_INITIAL_DEPOSIT,
|
|
83
84
|
} from '../utils';
|
|
84
|
-
import bs58 from 'bs58';
|
|
85
85
|
import { getAccountOwner, getProgramAccounts } from '../utils/rpc';
|
|
86
86
|
import {
|
|
87
87
|
AcceptVaultOwnershipIxs,
|
|
@@ -98,7 +98,7 @@ import {
|
|
|
98
98
|
} from './vault_types';
|
|
99
99
|
import { batchFetch, collToLamportsDecimal, ZERO } from '@kamino-finance/kliquidity-sdk';
|
|
100
100
|
import { FullBPSDecimal } from '@kamino-finance/kliquidity-sdk/dist/utils/CreationParameters';
|
|
101
|
-
import { FarmState } from '@kamino-finance/farms-sdk/dist';
|
|
101
|
+
import { FarmIncentives, FarmState } from '@kamino-finance/farms-sdk/dist';
|
|
102
102
|
import { getAccountsInLut, initLookupTableIx } from '../utils/lookupTable';
|
|
103
103
|
import {
|
|
104
104
|
getFarmStakeIxs,
|
|
@@ -120,6 +120,7 @@ import { SYSVAR_INSTRUCTIONS_ADDRESS, SYSVAR_RENT_ADDRESS } from '@solana/sysvar
|
|
|
120
120
|
import { noopSigner } from '../utils/signer';
|
|
121
121
|
import { getExtendLookupTableInstruction } from '@solana-program/address-lookup-table';
|
|
122
122
|
import { Farms } from '@kamino-finance/farms-sdk';
|
|
123
|
+
import { getFarmIncentives } from '@kamino-finance/farms-sdk/dist/utils/apy';
|
|
123
124
|
|
|
124
125
|
export const kaminoVaultId = address('KvauGMspG5k6rtzrqqn7WNn3oZdyKqLKwK2XWQ8FLjd');
|
|
125
126
|
export const kaminoVaultStagingId = address('stKvQfwRsQiKnLtMNVLHKS3exFJmZFsgfzBPWHECUYK');
|
|
@@ -136,6 +137,7 @@ export const METADATA_PROGRAM_ID: Address = address('metaqbxxUerdq28cj1RbAWkYQm3
|
|
|
136
137
|
export const INITIAL_DEPOSIT_LAMPORTS = 1000;
|
|
137
138
|
|
|
138
139
|
const addressEncoder = getAddressEncoder();
|
|
140
|
+
const base58Decoder = getBase58Decoder();
|
|
139
141
|
|
|
140
142
|
/**
|
|
141
143
|
* KaminoVaultClient is a class that provides a high-level interface to interact with the Kamino Vault program.
|
|
@@ -2043,7 +2045,7 @@ export class KaminoVaultClient {
|
|
|
2043
2045
|
{
|
|
2044
2046
|
memcmp: {
|
|
2045
2047
|
offset: 0n,
|
|
2046
|
-
bytes:
|
|
2048
|
+
bytes: base58Decoder.decode(VaultState.discriminator) as Base58EncodedBytes,
|
|
2047
2049
|
encoding: 'base58',
|
|
2048
2050
|
},
|
|
2049
2051
|
},
|
|
@@ -2065,7 +2067,7 @@ export class KaminoVaultClient {
|
|
|
2065
2067
|
{
|
|
2066
2068
|
memcmp: {
|
|
2067
2069
|
offset: 0n,
|
|
2068
|
-
bytes:
|
|
2070
|
+
bytes: base58Decoder.decode(VaultState.discriminator) as Base58EncodedBytes,
|
|
2069
2071
|
encoding: 'base58',
|
|
2070
2072
|
},
|
|
2071
2073
|
},
|
|
@@ -2917,6 +2919,9 @@ export class KaminoVaultClient {
|
|
|
2917
2919
|
};
|
|
2918
2920
|
}
|
|
2919
2921
|
|
|
2922
|
+
/**
|
|
2923
|
+
* This will compute the PDA that is used as delegatee in Farms program to compute the user state PDA for vault depositor investing in vault with reserve having a supply farm
|
|
2924
|
+
*/
|
|
2920
2925
|
computeUserFarmStateDelegateePDAForUserInVault(
|
|
2921
2926
|
farmsProgramId: Address,
|
|
2922
2927
|
vault: Address,
|
|
@@ -2929,6 +2934,30 @@ export class KaminoVaultClient {
|
|
|
2929
2934
|
});
|
|
2930
2935
|
}
|
|
2931
2936
|
|
|
2937
|
+
/**
|
|
2938
|
+
* Read the APY of the farm built on top of the vault (farm in vaultState.vaultFarm)
|
|
2939
|
+
* @param vault - the vault to read the farm APY for
|
|
2940
|
+
* @param vaultTokenPrice - the price of the vault token in USD (e.g. 1.0 for USDC)
|
|
2941
|
+
* @param [slot] - the slot to read the farm APY for. Optional. If not provided, the function will read the current slot
|
|
2942
|
+
* @returns the APY of the farm built on top of the vault
|
|
2943
|
+
*/
|
|
2944
|
+
async getVaultRewardsAPY(vault: KaminoVault, vaultTokenPrice: Decimal, slot?: Slot): Promise<FarmIncentives> {
|
|
2945
|
+
const vaultState = await vault.getState(this.getConnection());
|
|
2946
|
+
if (vaultState.vaultFarm === DEFAULT_PUBLIC_KEY) {
|
|
2947
|
+
return {
|
|
2948
|
+
incentivesStats: [],
|
|
2949
|
+
totalIncentivesApy: 0,
|
|
2950
|
+
};
|
|
2951
|
+
}
|
|
2952
|
+
|
|
2953
|
+
const tokensPerShare = await this.getTokensPerShareSingleVault(vault, slot);
|
|
2954
|
+
const sharePrice = tokensPerShare.mul(vaultTokenPrice);
|
|
2955
|
+
const stakedTokenMintDecimals = vaultState.sharesMintDecimals.toNumber();
|
|
2956
|
+
|
|
2957
|
+
const farmsClient = new Farms(this.getConnection());
|
|
2958
|
+
return getFarmIncentives(farmsClient, vaultState.vaultFarm, sharePrice, stakedTokenMintDecimals);
|
|
2959
|
+
}
|
|
2960
|
+
|
|
2932
2961
|
private appendRemainingAccountsForVaultReserves(
|
|
2933
2962
|
ix: IInstruction,
|
|
2934
2963
|
vaultReserves: Address[],
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
appendTransactionMessageInstructions,
|
|
5
5
|
compileTransactionMessage,
|
|
6
6
|
createTransactionMessage,
|
|
7
|
+
getBase58Decoder,
|
|
7
8
|
getCompiledTransactionMessageEncoder,
|
|
8
9
|
IInstruction,
|
|
9
10
|
pipe,
|
|
@@ -13,9 +14,10 @@ import {
|
|
|
13
14
|
} from '@solana/kit';
|
|
14
15
|
import { INVALID_BUT_SUFFICIENT_FOR_COMPILATION_BLOCKHASH } from './simulate';
|
|
15
16
|
import { AddressLookupTable } from '@solana-program/address-lookup-table';
|
|
16
|
-
import bs58 from 'bs58';
|
|
17
17
|
import { removeComputeBudgetProgramInstructions } from './priorityFee';
|
|
18
18
|
|
|
19
|
+
const base58Decoder = getBase58Decoder();
|
|
20
|
+
|
|
19
21
|
export async function printMultisigTx(
|
|
20
22
|
payer: TransactionSigner,
|
|
21
23
|
ixs: IInstruction[],
|
|
@@ -40,6 +42,6 @@ export async function printMultisigTx(
|
|
|
40
42
|
const compiled = compileTransactionMessage(transactionMessage);
|
|
41
43
|
const encodedMessageBytes = getCompiledTransactionMessageEncoder().encode(compiled);
|
|
42
44
|
|
|
43
|
-
const base58EncodedMessage =
|
|
45
|
+
const base58EncodedMessage = base58Decoder.decode(encodedMessageBytes);
|
|
44
46
|
console.log('Base58 encoded tx:', base58EncodedMessage);
|
|
45
47
|
}
|
|
@@ -1310,6 +1310,37 @@ async function main() {
|
|
|
1310
1310
|
console.log('vaultOverview', vaultOverview);
|
|
1311
1311
|
});
|
|
1312
1312
|
|
|
1313
|
+
commands
|
|
1314
|
+
.command('get-vault-farm-apy')
|
|
1315
|
+
.requiredOption('--vault <string>', 'Vault address')
|
|
1316
|
+
.requiredOption('--token-price <number>', 'Vault token price in USD')
|
|
1317
|
+
.option(`--staging`, 'If true, will use the staging programs')
|
|
1318
|
+
.action(async ({ vault, tokenPrice, staging }) => {
|
|
1319
|
+
const env = await initEnv(staging);
|
|
1320
|
+
const slotDuration = await getMedianSlotDurationInMsFromLastEpochs();
|
|
1321
|
+
|
|
1322
|
+
const kaminoManager = new KaminoManager(env.c.rpc, slotDuration, env.klendProgramId, env.kvaultProgramId);
|
|
1323
|
+
|
|
1324
|
+
const kaminoVault = new KaminoVault(address(vault));
|
|
1325
|
+
const farmAPY = await kaminoManager.getVaultFarmRewardsAPY(kaminoVault, new Decimal(tokenPrice));
|
|
1326
|
+
console.log('farmAPY', farmAPY);
|
|
1327
|
+
});
|
|
1328
|
+
|
|
1329
|
+
commands
|
|
1330
|
+
.command('get-reserve-farms-apy')
|
|
1331
|
+
.requiredOption('--reserve <string>', 'Reserve address')
|
|
1332
|
+
.requiredOption('--token-price <number>', 'Reserve token price in USD')
|
|
1333
|
+
.option(`--staging`, 'If true, will use the staging programs')
|
|
1334
|
+
.action(async ({ reserve, tokenPrice, staging }) => {
|
|
1335
|
+
const env = await initEnv(staging);
|
|
1336
|
+
const slotDuration = await getMedianSlotDurationInMsFromLastEpochs();
|
|
1337
|
+
|
|
1338
|
+
const kaminoManager = new KaminoManager(env.c.rpc, slotDuration, address("KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD"), env.kvaultProgramId);
|
|
1339
|
+
|
|
1340
|
+
const farmAPY = await kaminoManager.getReserveFarmRewardsAPY(address(reserve), new Decimal(tokenPrice));
|
|
1341
|
+
console.log('farmAPY', farmAPY);
|
|
1342
|
+
});
|
|
1343
|
+
|
|
1313
1344
|
commands
|
|
1314
1345
|
.command('get-vault-allocation-distribution')
|
|
1315
1346
|
.requiredOption('--vault <string>', 'Vault address')
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
appendTransactionMessageInstructions,
|
|
5
5
|
compileTransactionMessage,
|
|
6
6
|
createTransactionMessage,
|
|
7
|
+
getBase58Decoder,
|
|
7
8
|
getCompiledTransactionMessageEncoder,
|
|
8
9
|
IInstruction,
|
|
9
10
|
pipe,
|
|
@@ -13,9 +14,10 @@ import {
|
|
|
13
14
|
} from '@solana/kit';
|
|
14
15
|
import { INVALID_BUT_SUFFICIENT_FOR_COMPILATION_BLOCKHASH } from './simulate';
|
|
15
16
|
import { AddressLookupTable } from '@solana-program/address-lookup-table';
|
|
16
|
-
import bs58 from 'bs58';
|
|
17
17
|
import { removeComputeBudgetProgramInstructions } from './priorityFee';
|
|
18
18
|
|
|
19
|
+
const base58Decoder = getBase58Decoder();
|
|
20
|
+
|
|
19
21
|
export async function printMultisigTx(
|
|
20
22
|
payer: TransactionSigner,
|
|
21
23
|
ixs: IInstruction[],
|
|
@@ -40,6 +42,6 @@ export async function printMultisigTx(
|
|
|
40
42
|
const compiled = compileTransactionMessage(transactionMessage);
|
|
41
43
|
const encodedMessageBytes = getCompiledTransactionMessageEncoder().encode(compiled);
|
|
42
44
|
|
|
43
|
-
const base58EncodedMessage =
|
|
45
|
+
const base58EncodedMessage = base58Decoder.decode(encodedMessageBytes);
|
|
44
46
|
console.log('Base58 encoded tx:', base58EncodedMessage);
|
|
45
47
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { Address, Base58EncodedBytes, GetProgramAccountsApi, Rpc } from '@solana/kit';
|
|
1
|
+
import { Address, Base58EncodedBytes, getBase58Decoder, GetProgramAccountsApi, Rpc } from '@solana/kit';
|
|
2
2
|
import { LendingMarket, Obligation, Reserve } from '../@codegen/klend/accounts';
|
|
3
3
|
import { PROGRAM_ID } from '../@codegen/klend/programId';
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
const base58Decoder = getBase58Decoder();
|
|
5
6
|
|
|
6
7
|
export async function* getAllObligationAccounts(
|
|
7
8
|
connection: Rpc<GetProgramAccountsApi>
|
|
@@ -17,14 +18,14 @@ export async function* getAllObligationAccounts(
|
|
|
17
18
|
{
|
|
18
19
|
memcmp: {
|
|
19
20
|
offset: 0n,
|
|
20
|
-
bytes:
|
|
21
|
+
bytes: base58Decoder.decode(Obligation.discriminator) as Base58EncodedBytes,
|
|
21
22
|
encoding: 'base58',
|
|
22
23
|
},
|
|
23
24
|
},
|
|
24
25
|
{
|
|
25
26
|
memcmp: {
|
|
26
27
|
offset: 64n,
|
|
27
|
-
bytes:
|
|
28
|
+
bytes: base58Decoder.decode(Buffer.from([i])) as Base58EncodedBytes, // ...via sharding by userId's first byte (just as a source of randomness)
|
|
28
29
|
encoding: 'base58',
|
|
29
30
|
},
|
|
30
31
|
},
|
|
@@ -51,7 +52,7 @@ export async function* getAllReserveAccounts(
|
|
|
51
52
|
{
|
|
52
53
|
memcmp: {
|
|
53
54
|
offset: 0n,
|
|
54
|
-
bytes:
|
|
55
|
+
bytes: base58Decoder.decode(Reserve.discriminator) as Base58EncodedBytes,
|
|
55
56
|
encoding: 'base58',
|
|
56
57
|
},
|
|
57
58
|
},
|
|
@@ -78,7 +79,7 @@ export async function* getAllLendingMarketAccounts(
|
|
|
78
79
|
{
|
|
79
80
|
memcmp: {
|
|
80
81
|
offset: 0n,
|
|
81
|
-
bytes:
|
|
82
|
+
bytes: base58Decoder.decode(LendingMarket.discriminator) as Base58EncodedBytes,
|
|
82
83
|
encoding: 'base58',
|
|
83
84
|
},
|
|
84
85
|
},
|
|
@@ -252,6 +252,7 @@ export type AssetReserveConfigParams = {
|
|
|
252
252
|
maxAgePriceSeconds: number;
|
|
253
253
|
maxAgeTwapSeconds: number;
|
|
254
254
|
borrowRateCurve: BorrowRateCurve;
|
|
255
|
+
hostFixedInterestRateBps: number;
|
|
255
256
|
};
|
|
256
257
|
|
|
257
258
|
export const DefaultConfigParams: AssetReserveConfigParams = {
|
|
@@ -276,6 +277,7 @@ export const DefaultConfigParams: AssetReserveConfigParams = {
|
|
|
276
277
|
} as BorrowRateCurveFields),
|
|
277
278
|
maxAgePriceSeconds: 180,
|
|
278
279
|
maxAgeTwapSeconds: 240,
|
|
280
|
+
hostFixedInterestRateBps: 0,
|
|
279
281
|
};
|
|
280
282
|
|
|
281
283
|
export const encodeTokenName = (tokenName: string): number[] => {
|
|
@@ -359,7 +361,7 @@ function buildReserveConfig(fields: {
|
|
|
359
361
|
deleveragingThresholdDecreaseBpsPerDay: new BN(24),
|
|
360
362
|
disableUsageAsCollOutsideEmode: 0,
|
|
361
363
|
utilizationLimitBlockBorrowingAbovePct: 0,
|
|
362
|
-
hostFixedInterestRateBps:
|
|
364
|
+
hostFixedInterestRateBps: fields.configParams.hostFixedInterestRateBps,
|
|
363
365
|
autodeleverageEnabled: 0,
|
|
364
366
|
borrowLimitOutsideElevationGroup: new BN(
|
|
365
367
|
numberToLamportsDecimal(fields.borrowLimitOutsideElevationGroup ?? new Decimal(0), fields.mintDecimals)
|