@kamino-finance/klend-sdk 5.11.14 → 5.11.16
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 +1 -1
- package/dist/classes/manager.d.ts.map +1 -1
- package/dist/classes/manager.js +3 -3
- package/dist/classes/manager.js.map +1 -1
- package/dist/classes/market.d.ts.map +1 -1
- package/dist/classes/market.js +3 -0
- package/dist/classes/market.js.map +1 -1
- package/dist/classes/reserve.d.ts +7 -1
- package/dist/classes/reserve.d.ts.map +1 -1
- package/dist/classes/reserve.js +145 -255
- package/dist/classes/reserve.js.map +1 -1
- package/dist/classes/types.d.ts +2 -0
- package/dist/classes/types.d.ts.map +1 -1
- package/dist/classes/utils.d.ts +1 -1
- package/dist/classes/utils.d.ts.map +1 -1
- package/dist/classes/utils.js +8 -2
- package/dist/classes/utils.js.map +1 -1
- package/dist/classes/vault.d.ts +1 -1
- package/dist/classes/vault.d.ts.map +1 -1
- package/dist/classes/vault.js +24 -5
- package/dist/classes/vault.js.map +1 -1
- package/dist/client_kamino_manager.d.ts.map +1 -1
- package/dist/client_kamino_manager.js +99 -89
- package/dist/client_kamino_manager.js.map +1 -1
- package/dist/utils/ata.d.ts +15 -2
- package/dist/utils/ata.d.ts.map +1 -1
- package/dist/utils/ata.js +68 -3
- package/dist/utils/ata.js.map +1 -1
- package/dist/utils/constants.d.ts +1 -0
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/constants.js +2 -1
- package/dist/utils/constants.js.map +1 -1
- package/package.json +1 -1
- package/src/classes/manager.ts +5 -6
- package/src/classes/market.ts +4 -0
- package/src/classes/reserve.ts +178 -319
- package/src/classes/types.ts +3 -0
- package/src/classes/utils.ts +9 -3
- package/src/classes/vault.ts +44 -12
- package/src/client_kamino_manager.ts +225 -92
- package/src/utils/ata.ts +102 -4
- package/src/utils/constants.ts +2 -0
|
@@ -70,7 +70,7 @@ async function main() {
|
|
|
70
70
|
throw new Error('If using multisig mode, multisig pubkey is required');
|
|
71
71
|
}
|
|
72
72
|
const multisigPk = multisig ? new web3_js_1.PublicKey(multisig) : web3_js_1.PublicKey.default;
|
|
73
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
73
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
74
74
|
const { market: marketKp, ixns: createMarketIxns } = await kaminoManager.createMarketIxs({
|
|
75
75
|
admin: mode === 'multisig' ? multisigPk : env.payer.publicKey,
|
|
76
76
|
});
|
|
@@ -95,7 +95,7 @@ async function main() {
|
|
|
95
95
|
throw new Error('If using multisig mode, multisig is required');
|
|
96
96
|
}
|
|
97
97
|
const multisigPk = multisig ? new web3_js_1.PublicKey(multisig) : web3_js_1.PublicKey.default;
|
|
98
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
98
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
99
99
|
const reserveConfigFromFile = JSON.parse(fs.readFileSync(reserveConfigPath, 'utf8'));
|
|
100
100
|
const reserveConfig = parseReserveConfigFromFile(reserveConfigFromFile);
|
|
101
101
|
const assetConfig = new lib_1.AssetReserveConfigCli(tokenMint, tokenMintProgramId, reserveConfig);
|
|
@@ -140,7 +140,7 @@ async function main() {
|
|
|
140
140
|
if (mode === 'multisig' && !multisig) {
|
|
141
141
|
throw new Error('If using multisig mode, multisig is required');
|
|
142
142
|
}
|
|
143
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
143
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
144
144
|
const reserveConfigFromFile = JSON.parse(fs.readFileSync(reserveConfigPath, 'utf8'));
|
|
145
145
|
const reserveConfig = parseReserveConfigFromFile(reserveConfigFromFile);
|
|
146
146
|
const ixns = await kaminoManager.updateReserveIxs(marketWithAddress, reserveAddress, reserveConfig, reserveState, updateEntireConfig);
|
|
@@ -178,7 +178,7 @@ async function main() {
|
|
|
178
178
|
throw new Error('If using multisig mode, multisig is required');
|
|
179
179
|
}
|
|
180
180
|
const multisigPk = multisig ? new web3_js_1.PublicKey(multisig) : web3_js_1.PublicKey.default;
|
|
181
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
181
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
182
182
|
const tokenProgramID = await (0, rpc_1.getAccountOwner)(env.connection, tokenMint);
|
|
183
183
|
const kaminoVaultConfig = new lib_1.KaminoVaultConfig({
|
|
184
184
|
admin: mode === 'multisig' ? multisigPk : env.payer.publicKey,
|
|
@@ -207,7 +207,7 @@ async function main() {
|
|
|
207
207
|
if (mode === 'multisig' && !multisig) {
|
|
208
208
|
throw new Error('If using multisig mode, multisig is required');
|
|
209
209
|
}
|
|
210
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
210
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
211
211
|
const kaminoVault = new lib_1.KaminoVault(vaultAddress, undefined, env.kVaultProgramId);
|
|
212
212
|
const instructions = await kaminoManager.updateVaultConfigIxs(kaminoVault, new VaultConfigField_1.PendingVaultAdmin(), newAdmin);
|
|
213
213
|
const updateVaultPendingAdminSig = await processTxn(env.client, env.payer, [instructions.updateVaultConfigIx, ...instructions.updateLUTIxs], mode, 2500, []);
|
|
@@ -227,7 +227,7 @@ async function main() {
|
|
|
227
227
|
if (mode === 'multisig' && !multisig) {
|
|
228
228
|
throw new Error('If using multisig mode, multisig is required');
|
|
229
229
|
}
|
|
230
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
230
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
231
231
|
const kaminoVault = new lib_1.KaminoVault(vaultAddress, undefined, env.kVaultProgramId);
|
|
232
232
|
const instructions = await kaminoManager.updateVaultConfigIxs(kaminoVault, field, value);
|
|
233
233
|
const updateVaultPendingAdminSig = await processTxn(env.client, env.payer, [instructions.updateVaultConfigIx, ...instructions.updateLUTIxs], mode, 2500, []);
|
|
@@ -246,7 +246,7 @@ async function main() {
|
|
|
246
246
|
if (mode === 'multisig' && !multisig) {
|
|
247
247
|
throw new Error('If using multisig mode, multisig is required');
|
|
248
248
|
}
|
|
249
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
249
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
250
250
|
const kaminoVault = new lib_1.KaminoVault(vaultAddress, undefined, env.kVaultProgramId);
|
|
251
251
|
const instructions = await kaminoManager.updateVaultConfigIxs(kaminoVault, new VaultConfigField_1.ManagementFeeBps(), feeBps);
|
|
252
252
|
const updateVaultConfigSig = await processTxn(env.client, env.payer, [instructions.updateVaultConfigIx, ...instructions.updateLUTIxs], mode, 2500, []);
|
|
@@ -266,7 +266,7 @@ async function main() {
|
|
|
266
266
|
if (mode === 'multisig' && !multisig) {
|
|
267
267
|
throw new Error('If using multisig mode, multisig is required');
|
|
268
268
|
}
|
|
269
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
269
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
270
270
|
const instructions = await kaminoManager.insertIntoLUTIxs(env.payer.publicKey, lutAddress, addressesArr);
|
|
271
271
|
const updateVaultConfigSig = await processTxn(env.client, env.payer, instructions, mode, 2500, []);
|
|
272
272
|
mode === 'execute' && console.log('Management fee updated:', updateVaultConfigSig);
|
|
@@ -289,7 +289,7 @@ async function main() {
|
|
|
289
289
|
if (mode === 'multisig' && !multisig) {
|
|
290
290
|
throw new Error('If using multisig mode, multisig is required');
|
|
291
291
|
}
|
|
292
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
292
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
293
293
|
const kaminoVault = new lib_1.KaminoVault(vaultAddress, undefined, env.kVaultProgramId);
|
|
294
294
|
const syncLUTIxs = await kaminoManager.syncVaultLUTIxs(kaminoVault);
|
|
295
295
|
// if we need to create the LUT we have to do that in a separate tx and wait a little bit after
|
|
@@ -317,7 +317,7 @@ async function main() {
|
|
|
317
317
|
if (mode === 'multisig' && !multisig) {
|
|
318
318
|
throw new Error('If using multisig mode, multisig is required');
|
|
319
319
|
}
|
|
320
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
320
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
321
321
|
const kaminoVault = new lib_1.KaminoVault(vaultAddress, undefined, env.kVaultProgramId);
|
|
322
322
|
const instructions = await kaminoManager.updateVaultConfigIxs(kaminoVault, new VaultConfigField_1.PerformanceFeeBps(), feeBps);
|
|
323
323
|
const updateVaultPerfFeeSig = await processTxn(env.client, env.payer, [instructions.updateVaultConfigIx, ...instructions.updateLUTIxs], mode, 2500, []);
|
|
@@ -335,7 +335,7 @@ async function main() {
|
|
|
335
335
|
if (mode === 'multisig' && !multisig) {
|
|
336
336
|
throw new Error('If using multisig mode, multisig is required');
|
|
337
337
|
}
|
|
338
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
338
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
339
339
|
const kaminoVault = new lib_1.KaminoVault(vaultAddress, undefined, env.kVaultProgramId);
|
|
340
340
|
const instructions = await kaminoManager.acceptVaultOwnershipIxs(kaminoVault);
|
|
341
341
|
const acceptVaultOwnershipSig = await processTxn(env.client, env.payer, [instructions.acceptVaultOwnershipIx, ...instructions.updateLUTIxs], mode, 2500, []);
|
|
@@ -354,7 +354,7 @@ async function main() {
|
|
|
354
354
|
if (mode === 'multisig' && !multisig) {
|
|
355
355
|
throw new Error('If using multisig mode, multisig is required');
|
|
356
356
|
}
|
|
357
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
357
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
358
358
|
const kaminoVault = new lib_1.KaminoVault(vaultAddress, undefined, env.kVaultProgramId);
|
|
359
359
|
const instruction = await kaminoManager.giveUpPendingFeesIx(kaminoVault, new decimal_js_1.default(maxAmountToGiveUp));
|
|
360
360
|
const giveUpPendingFeesSig = await processTxn(env.client, env.payer, [instruction], mode, 2500, []);
|
|
@@ -372,7 +372,7 @@ async function main() {
|
|
|
372
372
|
if (mode === 'multisig' && !multisig) {
|
|
373
373
|
throw new Error('If using multisig mode, multisig is required');
|
|
374
374
|
}
|
|
375
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
375
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
376
376
|
const kaminoVault = new lib_1.KaminoVault(vaultAddress, undefined, env.kVaultProgramId);
|
|
377
377
|
const instructions = await kaminoManager.withdrawPendingFeesIxs(kaminoVault, await env.connection.getSlot('confirmed'));
|
|
378
378
|
const withdrawPendingFeesSig = await processTxn(env.client, env.payer, instructions, mode, 2500, []);
|
|
@@ -388,7 +388,7 @@ async function main() {
|
|
|
388
388
|
const env = initializeClient(mode === 'multisig', staging);
|
|
389
389
|
const vaultAddress = new web3_js_1.PublicKey(vault);
|
|
390
390
|
const kaminoVault = new lib_1.KaminoVault(vaultAddress, undefined, env.kVaultProgramId);
|
|
391
|
-
const stakeIxs = await new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId).stakeSharesIxs(env.payer.publicKey, kaminoVault);
|
|
391
|
+
const stakeIxs = await new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId).stakeSharesIxs(env.payer.publicKey, kaminoVault);
|
|
392
392
|
if (mode === 'multisig' && !multisig) {
|
|
393
393
|
throw new Error('If using multisig mode, multisig is required');
|
|
394
394
|
}
|
|
@@ -413,7 +413,7 @@ async function main() {
|
|
|
413
413
|
if (mode === 'multisig' && !multisig) {
|
|
414
414
|
throw new Error('If using multisig mode, multisig is required');
|
|
415
415
|
}
|
|
416
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
416
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
417
417
|
const reserveState = await lib_1.Reserve.fetch(env.connection, reserveAddress, env.kLendProgramId);
|
|
418
418
|
if (!reserveState) {
|
|
419
419
|
throw new Error('Reserve not found');
|
|
@@ -441,7 +441,7 @@ async function main() {
|
|
|
441
441
|
if (mode === 'multisig' && !multisig) {
|
|
442
442
|
throw new Error('If using multisig mode, multisig is required');
|
|
443
443
|
}
|
|
444
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
444
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
445
445
|
const kaminoVault = new lib_1.KaminoVault(vaultAddress, undefined, env.kVaultProgramId);
|
|
446
446
|
const depositInstructions = await kaminoManager.depositToVaultIxs(env.payer.publicKey, kaminoVault, amount);
|
|
447
447
|
const instructions = [...depositInstructions.depositIxs, ...depositInstructions.stakeInFarmIfNeededIxs];
|
|
@@ -461,7 +461,7 @@ async function main() {
|
|
|
461
461
|
if (mode === 'multisig' && !multisig) {
|
|
462
462
|
throw new Error('If using multisig mode, multisig is required');
|
|
463
463
|
}
|
|
464
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
464
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
465
465
|
const kaminoVault = new lib_1.KaminoVault(vaultAddress, undefined, env.kVaultProgramId);
|
|
466
466
|
const withdrawIxs = await kaminoManager.withdrawFromVaultIxs(env.payer.publicKey, kaminoVault, new decimal_js_1.default(amount), await env.connection.getSlot('confirmed'));
|
|
467
467
|
const depositSig = await processTxn(env.client, env.payer, [...withdrawIxs.unstakeFromFarmIfNeededIxs, ...withdrawIxs.withdrawIxs], mode, 2500, [], 800_000);
|
|
@@ -479,7 +479,7 @@ async function main() {
|
|
|
479
479
|
if (mode === 'multisig' && !multisig) {
|
|
480
480
|
throw new Error('If using multisig mode, multisig is required');
|
|
481
481
|
}
|
|
482
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
482
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
483
483
|
const kaminoVault = new lib_1.KaminoVault(vaultAddress, undefined, env.kVaultProgramId);
|
|
484
484
|
const instructions = await kaminoManager.investAllReservesIxs(env.payer.publicKey, kaminoVault);
|
|
485
485
|
for (let i = 0; i < instructions.length; i++) {
|
|
@@ -502,7 +502,7 @@ async function main() {
|
|
|
502
502
|
if (mode === 'multisig' && !multisig) {
|
|
503
503
|
throw new Error('If using multisig mode, multisig is required');
|
|
504
504
|
}
|
|
505
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
505
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
506
506
|
const kaminoVault = new lib_1.KaminoVault(vaultAddress, undefined, env.kVaultProgramId);
|
|
507
507
|
const reserveState = await lib_1.Reserve.fetch(env.connection, new web3_js_1.PublicKey(reserve), env.kLendProgramId);
|
|
508
508
|
if (!reserveState) {
|
|
@@ -534,7 +534,8 @@ async function main() {
|
|
|
534
534
|
.requiredOption('--vault <string>', 'Vault address')
|
|
535
535
|
.action(async ({ vault }) => {
|
|
536
536
|
const env = initializeClient(false, false);
|
|
537
|
-
const
|
|
537
|
+
const slotDuration = await (0, lib_1.getMedianSlotDurationInMsFromLastEpochs)();
|
|
538
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, slotDuration, env.kLendProgramId, env.kVaultProgramId);
|
|
538
539
|
const vaultAddress = new web3_js_1.PublicKey(vault);
|
|
539
540
|
const vaultState = await new lib_1.KaminoVault(vaultAddress, undefined, env.kVaultProgramId).getState(env.connection);
|
|
540
541
|
const vaultCollaterals = await kaminoManager.getVaultCollaterals(vaultState, await env.connection.getSlot('confirmed'));
|
|
@@ -550,7 +551,8 @@ async function main() {
|
|
|
550
551
|
.requiredOption('--vault <string>', 'Vault address')
|
|
551
552
|
.action(async ({ vault }) => {
|
|
552
553
|
const env = initializeClient(false, false);
|
|
553
|
-
const
|
|
554
|
+
const slotDuration = await (0, lib_1.getMedianSlotDurationInMsFromLastEpochs)();
|
|
555
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, slotDuration, env.kLendProgramId, env.kVaultProgramId);
|
|
554
556
|
const vaultAddress = new web3_js_1.PublicKey(vault);
|
|
555
557
|
const vaultState = await new lib_1.KaminoVault(vaultAddress, undefined, env.kVaultProgramId).getState(env.connection);
|
|
556
558
|
const vaultOverview = await kaminoManager.getVaultOverview(vaultState, new decimal_js_1.default(1.0), await env.connection.getSlot('confirmed'));
|
|
@@ -561,7 +563,8 @@ async function main() {
|
|
|
561
563
|
.requiredOption('--vault <string>', 'Vault address')
|
|
562
564
|
.action(async ({ vault }) => {
|
|
563
565
|
const env = initializeClient(false, false);
|
|
564
|
-
const
|
|
566
|
+
const slotDuration = await (0, lib_1.getMedianSlotDurationInMsFromLastEpochs)();
|
|
567
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, slotDuration, env.kLendProgramId, env.kVaultProgramId);
|
|
565
568
|
const vaultAddress = new web3_js_1.PublicKey(vault);
|
|
566
569
|
const vaultState = await new lib_1.KaminoVault(vaultAddress, undefined, env.kVaultProgramId).getState(env.connection);
|
|
567
570
|
const allocationDistribution = kaminoManager.getAllocationsDistribuionPct(vaultState);
|
|
@@ -576,7 +579,8 @@ async function main() {
|
|
|
576
579
|
.requiredOption('--wallet <string>', 'User wailt address')
|
|
577
580
|
.action(async ({ vault, wallet }) => {
|
|
578
581
|
const env = initializeClient(false, false);
|
|
579
|
-
const
|
|
582
|
+
const slotDuration = await (0, lib_1.getMedianSlotDurationInMsFromLastEpochs)();
|
|
583
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, slotDuration, env.kLendProgramId, env.kVaultProgramId);
|
|
580
584
|
const vaultAddress = new web3_js_1.PublicKey(vault);
|
|
581
585
|
const walletAddress = new web3_js_1.PublicKey(wallet);
|
|
582
586
|
const kaminoVault = new lib_1.KaminoVault(vaultAddress, undefined, env.kVaultProgramId);
|
|
@@ -588,7 +592,8 @@ async function main() {
|
|
|
588
592
|
.requiredOption('--wallet <string>', 'User wailt address')
|
|
589
593
|
.action(async ({ wallet }) => {
|
|
590
594
|
const env = initializeClient(false, false);
|
|
591
|
-
const
|
|
595
|
+
const slotDuration = await (0, lib_1.getMedianSlotDurationInMsFromLastEpochs)();
|
|
596
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, slotDuration, env.kLendProgramId, env.kVaultProgramId);
|
|
592
597
|
const walletAddress = new web3_js_1.PublicKey(wallet);
|
|
593
598
|
const userShares = await kaminoManager.getUserSharesBalanceAllVaults(walletAddress);
|
|
594
599
|
userShares.forEach((userShares, vaultAddress) => {
|
|
@@ -600,7 +605,8 @@ async function main() {
|
|
|
600
605
|
.requiredOption('--vault <string>', 'Vault address')
|
|
601
606
|
.action(async ({ vault }) => {
|
|
602
607
|
const env = initializeClient(false, false);
|
|
603
|
-
const
|
|
608
|
+
const slotDuration = await (0, lib_1.getMedianSlotDurationInMsFromLastEpochs)();
|
|
609
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, slotDuration, env.kLendProgramId, env.kVaultProgramId);
|
|
604
610
|
const vaultAddress = new web3_js_1.PublicKey(vault);
|
|
605
611
|
const kaminoVault = new lib_1.KaminoVault(vaultAddress, undefined, env.kVaultProgramId);
|
|
606
612
|
const tokensPerShare = await kaminoManager.getTokensPerShareSingleVault(kaminoVault, await env.connection.getSlot('confirmed'));
|
|
@@ -611,7 +617,8 @@ async function main() {
|
|
|
611
617
|
.requiredOption('--vault <string>', 'Vault address')
|
|
612
618
|
.action(async ({ vault }) => {
|
|
613
619
|
const env = initializeClient(false, false);
|
|
614
|
-
const
|
|
620
|
+
const slotDuration = await (0, lib_1.getMedianSlotDurationInMsFromLastEpochs)();
|
|
621
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, slotDuration, env.kLendProgramId, env.kVaultProgramId);
|
|
615
622
|
const vaultAddress = new web3_js_1.PublicKey(vault);
|
|
616
623
|
const kaminoVault = new lib_1.KaminoVault(vaultAddress, undefined, env.kVaultProgramId);
|
|
617
624
|
await kaminoVault.getState(env.connection);
|
|
@@ -628,20 +635,21 @@ async function main() {
|
|
|
628
635
|
});
|
|
629
636
|
commands.command('get-oracle-mappings').action(async () => {
|
|
630
637
|
const env = initializeClient(false, false);
|
|
631
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
638
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
632
639
|
console.log('Getting oracle mappings');
|
|
633
640
|
const oracleConfigs = await kaminoManager.getScopeOracleConfigs();
|
|
634
641
|
console.log('oracleConfigs', JSON.parse(JSON.stringify(oracleConfigs)));
|
|
635
642
|
});
|
|
636
643
|
commands.command('get-all-vaults').action(async () => {
|
|
637
644
|
const env = initializeClient(false, false);
|
|
638
|
-
const
|
|
645
|
+
const slotDuration = await (0, lib_1.getMedianSlotDurationInMsFromLastEpochs)();
|
|
646
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, slotDuration, env.kLendProgramId, env.kVaultProgramId);
|
|
639
647
|
const allVaults = await kaminoManager.getAllVaults();
|
|
640
648
|
console.log('all vaults', allVaults);
|
|
641
649
|
});
|
|
642
650
|
commands.command('get-all-vaults-pks').action(async () => {
|
|
643
651
|
const env = initializeClient(false, false);
|
|
644
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
652
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
645
653
|
const allVaults = await kaminoManager.getAllVaults();
|
|
646
654
|
console.log('all vaults', allVaults.map((vault) => vault.address.toBase58()));
|
|
647
655
|
});
|
|
@@ -651,7 +659,8 @@ async function main() {
|
|
|
651
659
|
.action(async ({ vault }) => {
|
|
652
660
|
const env = initializeClient(false, false);
|
|
653
661
|
const vaultAddress = new web3_js_1.PublicKey(vault);
|
|
654
|
-
const
|
|
662
|
+
const slotDuration = await (0, lib_1.getMedianSlotDurationInMsFromLastEpochs)();
|
|
663
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, slotDuration, env.kLendProgramId, env.kVaultProgramId);
|
|
655
664
|
const vaultState = await new lib_1.KaminoVault(vaultAddress, undefined, env.kVaultProgramId).getState(env.connection);
|
|
656
665
|
const simulatedHoldings = await kaminoManager.calculateSimulatedHoldingsWithInterest(vaultState);
|
|
657
666
|
console.log('Simulated holdings with interest', simulatedHoldings);
|
|
@@ -679,7 +688,8 @@ async function main() {
|
|
|
679
688
|
.action(async ({ vault }) => {
|
|
680
689
|
const env = initializeClient(false, false);
|
|
681
690
|
const vaultAddress = new web3_js_1.PublicKey(vault);
|
|
682
|
-
const
|
|
691
|
+
const slotDuration = await (0, lib_1.getMedianSlotDurationInMsFromLastEpochs)();
|
|
692
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, slotDuration, env.kLendProgramId, env.kVaultProgramId);
|
|
683
693
|
const vaultState = await new lib_1.KaminoVault(vaultAddress, undefined, env.kVaultProgramId).getState(env.connection);
|
|
684
694
|
const computedAllocation = await kaminoManager.getVaultComputedReservesAllocation(vaultState);
|
|
685
695
|
console.log('computedAllocation', computedAllocation);
|
|
@@ -730,7 +740,7 @@ async function main() {
|
|
|
730
740
|
if (mode === 'multisig') {
|
|
731
741
|
throw new Error('If using multisig mode, multisig is required');
|
|
732
742
|
}
|
|
733
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
743
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
734
744
|
const newLendingMarket = lib_1.LendingMarket.fromJSON(JSON.parse(fs.readFileSync(lendingMarketConfigPath, 'utf8')));
|
|
735
745
|
const ixns = kaminoManager.updateLendingMarketIxs(marketWithAddress, newLendingMarket);
|
|
736
746
|
// executing 6 ixns in a txn to make sure they fit
|
|
@@ -760,7 +770,7 @@ async function main() {
|
|
|
760
770
|
if (mode === 'multisig') {
|
|
761
771
|
throw new Error('If using multisig mode, multisig is required');
|
|
762
772
|
}
|
|
763
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
773
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
764
774
|
const ixn = kaminoManager.updateLendingMarketOwnerIxs(marketWithAddress);
|
|
765
775
|
const _updateLendingMarketSig = await processTxn(env.client, env.payer, [ixn], mode, 2500, [], 400_000);
|
|
766
776
|
mode === 'execute' &&
|
|
@@ -786,7 +796,7 @@ async function main() {
|
|
|
786
796
|
if (mode === 'multisig') {
|
|
787
797
|
throw new Error('If using multisig mode, multisig is required');
|
|
788
798
|
}
|
|
789
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
799
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
790
800
|
const currentName = (0, lib_1.parseZeroPaddedUtf8)(lendingMarketState.name);
|
|
791
801
|
const newNameEncoded = (0, lib_1.encodeTokenName)(newName);
|
|
792
802
|
console.log('Current name: ', currentName, ' encoded: ', lendingMarketState.name);
|
|
@@ -825,7 +835,7 @@ async function main() {
|
|
|
825
835
|
if (mode === 'multisig') {
|
|
826
836
|
throw new Error('If using multisig mode, multisig is required');
|
|
827
837
|
}
|
|
828
|
-
const kaminoManager = new lib_1.KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
838
|
+
const kaminoManager = new lib_1.KaminoManager(env.connection, lib_1.DEFAULT_RECENT_SLOT_DURATION_MS, env.kLendProgramId, env.kVaultProgramId);
|
|
829
839
|
const newReserveConfigFields = {
|
|
830
840
|
...reserveState.config,
|
|
831
841
|
borrowLimit: new anchor_1.BN(1000),
|
|
@@ -949,85 +959,85 @@ function createAddExtraComputeUnitFeeTransaction(units, microLamports) {
|
|
|
949
959
|
ixns.push(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: new decimal_js_1.default(microLamports).floor().toNumber() }));
|
|
950
960
|
return ixns;
|
|
951
961
|
}
|
|
952
|
-
function parseReserveConfigFromFile(
|
|
962
|
+
function parseReserveConfigFromFile(reserveConfigFromFile) {
|
|
953
963
|
const reserveConfigFields = {
|
|
954
|
-
status:
|
|
955
|
-
loanToValuePct:
|
|
956
|
-
liquidationThresholdPct:
|
|
957
|
-
minLiquidationBonusBps:
|
|
958
|
-
protocolLiquidationFeePct:
|
|
959
|
-
protocolTakeRatePct:
|
|
960
|
-
assetTier:
|
|
961
|
-
maxLiquidationBonusBps:
|
|
962
|
-
badDebtLiquidationBonusBps:
|
|
964
|
+
status: reserveConfigFromFile.status,
|
|
965
|
+
loanToValuePct: reserveConfigFromFile.loanToValuePct,
|
|
966
|
+
liquidationThresholdPct: reserveConfigFromFile.liquidationThresholdPct,
|
|
967
|
+
minLiquidationBonusBps: reserveConfigFromFile.minLiquidationBonusBps,
|
|
968
|
+
protocolLiquidationFeePct: reserveConfigFromFile.protocolLiquidationFeePct,
|
|
969
|
+
protocolTakeRatePct: reserveConfigFromFile.protocolLiquidationFeePct,
|
|
970
|
+
assetTier: reserveConfigFromFile.assetTier,
|
|
971
|
+
maxLiquidationBonusBps: reserveConfigFromFile.maxLiquidationBonusBps,
|
|
972
|
+
badDebtLiquidationBonusBps: reserveConfigFromFile.badDebtLiquidationBonusBps,
|
|
963
973
|
fees: {
|
|
964
|
-
borrowFeeSf: fraction_1.Fraction.fromDecimal(new decimal_js_1.default(
|
|
965
|
-
flashLoanFeeSf: fraction_1.Fraction.fromDecimal(new decimal_js_1.default(
|
|
974
|
+
borrowFeeSf: fraction_1.Fraction.fromDecimal(new decimal_js_1.default(reserveConfigFromFile.fees.borrowFee)).valueSf,
|
|
975
|
+
flashLoanFeeSf: fraction_1.Fraction.fromDecimal(new decimal_js_1.default(reserveConfigFromFile.fees.flashLoanFee)).valueSf,
|
|
966
976
|
padding: Array(8).fill(0),
|
|
967
977
|
},
|
|
968
|
-
depositLimit: new anchor_1.BN(
|
|
969
|
-
borrowLimit: new anchor_1.BN(
|
|
978
|
+
depositLimit: new anchor_1.BN(reserveConfigFromFile.depositLimit),
|
|
979
|
+
borrowLimit: new anchor_1.BN(reserveConfigFromFile.borrowLimit),
|
|
970
980
|
tokenInfo: {
|
|
971
|
-
name: (0, lib_1.encodeTokenName)(
|
|
981
|
+
name: (0, lib_1.encodeTokenName)(reserveConfigFromFile.tokenInfo.name),
|
|
972
982
|
heuristic: new types_1.PriceHeuristic({
|
|
973
|
-
lower: new anchor_1.BN(
|
|
974
|
-
upper: new anchor_1.BN(
|
|
975
|
-
exp: new anchor_1.BN(
|
|
983
|
+
lower: new anchor_1.BN(reserveConfigFromFile.tokenInfo.heuristic.lower),
|
|
984
|
+
upper: new anchor_1.BN(reserveConfigFromFile.tokenInfo.heuristic.upper),
|
|
985
|
+
exp: new anchor_1.BN(reserveConfigFromFile.tokenInfo.heuristic.exp),
|
|
976
986
|
}),
|
|
977
|
-
maxTwapDivergenceBps: new anchor_1.BN(
|
|
978
|
-
maxAgePriceSeconds: new anchor_1.BN(
|
|
979
|
-
maxAgeTwapSeconds: new anchor_1.BN(
|
|
980
|
-
...parseOracleConfiguration(
|
|
981
|
-
blockPriceUsage:
|
|
987
|
+
maxTwapDivergenceBps: new anchor_1.BN(reserveConfigFromFile.tokenInfo.maxTwapDivergenceBps),
|
|
988
|
+
maxAgePriceSeconds: new anchor_1.BN(reserveConfigFromFile.tokenInfo.maxAgePriceSeconds),
|
|
989
|
+
maxAgeTwapSeconds: new anchor_1.BN(reserveConfigFromFile.tokenInfo.maxAgeTwapSeconds),
|
|
990
|
+
...parseOracleConfiguration(reserveConfigFromFile),
|
|
991
|
+
blockPriceUsage: reserveConfigFromFile.tokenInfo.blockPriceUsage,
|
|
982
992
|
reserved: Array(7).fill(0),
|
|
983
993
|
padding: Array(19).fill(new anchor_1.BN(0)),
|
|
984
994
|
},
|
|
985
|
-
borrowRateCurve: parseBorrowRateCurve(
|
|
995
|
+
borrowRateCurve: parseBorrowRateCurve(reserveConfigFromFile),
|
|
986
996
|
depositWithdrawalCap: new types_1.WithdrawalCaps({
|
|
987
|
-
configCapacity: new anchor_1.BN(
|
|
997
|
+
configCapacity: new anchor_1.BN(reserveConfigFromFile.depositWithdrawalCap.configCapacity),
|
|
988
998
|
currentTotal: new anchor_1.BN(0),
|
|
989
999
|
lastIntervalStartTimestamp: new anchor_1.BN(0),
|
|
990
|
-
configIntervalLengthSeconds: new anchor_1.BN(
|
|
1000
|
+
configIntervalLengthSeconds: new anchor_1.BN(reserveConfigFromFile.depositWithdrawalCap.configIntervalLengthSeconds),
|
|
991
1001
|
}),
|
|
992
1002
|
debtWithdrawalCap: new types_1.WithdrawalCaps({
|
|
993
|
-
configCapacity: new anchor_1.BN(
|
|
1003
|
+
configCapacity: new anchor_1.BN(reserveConfigFromFile.debtWithdrawalCap.configCapacity),
|
|
994
1004
|
currentTotal: new anchor_1.BN(0),
|
|
995
1005
|
lastIntervalStartTimestamp: new anchor_1.BN(0),
|
|
996
|
-
configIntervalLengthSeconds: new anchor_1.BN(
|
|
1006
|
+
configIntervalLengthSeconds: new anchor_1.BN(reserveConfigFromFile.debtWithdrawalCap.configIntervalLengthSeconds),
|
|
997
1007
|
}),
|
|
998
|
-
deleveragingMarginCallPeriodSecs: new anchor_1.BN(
|
|
999
|
-
borrowFactorPct: new anchor_1.BN(
|
|
1000
|
-
elevationGroups:
|
|
1001
|
-
deleveragingThresholdDecreaseBpsPerDay: new anchor_1.BN(
|
|
1002
|
-
disableUsageAsCollOutsideEmode:
|
|
1003
|
-
utilizationLimitBlockBorrowingAbovePct:
|
|
1004
|
-
hostFixedInterestRateBps:
|
|
1005
|
-
autodeleverageEnabled:
|
|
1006
|
-
borrowLimitOutsideElevationGroup: new anchor_1.BN(
|
|
1007
|
-
borrowLimitAgainstThisCollateralInElevationGroup: parseReserveBorrowLimitAgainstCollInEmode(
|
|
1008
|
-
deleveragingBonusIncreaseBpsPerDay: new anchor_1.BN(
|
|
1009
|
-
reserved1: Array(
|
|
1008
|
+
deleveragingMarginCallPeriodSecs: new anchor_1.BN(reserveConfigFromFile.deleveragingMarginCallPeriodSecs),
|
|
1009
|
+
borrowFactorPct: new anchor_1.BN(reserveConfigFromFile.borrowFactorPct),
|
|
1010
|
+
elevationGroups: reserveConfigFromFile.elevationGroups,
|
|
1011
|
+
deleveragingThresholdDecreaseBpsPerDay: new anchor_1.BN(reserveConfigFromFile.deleveragingThresholdDecreaseBpsPerDay),
|
|
1012
|
+
disableUsageAsCollOutsideEmode: reserveConfigFromFile.disableUsageAsCollOutsideEmode,
|
|
1013
|
+
utilizationLimitBlockBorrowingAbovePct: reserveConfigFromFile.utilizationLimitBlockBorrowingAbovePct,
|
|
1014
|
+
hostFixedInterestRateBps: reserveConfigFromFile.hostFixedInterestRateBps,
|
|
1015
|
+
autodeleverageEnabled: reserveConfigFromFile.autodeleverageEnabled,
|
|
1016
|
+
borrowLimitOutsideElevationGroup: new anchor_1.BN(reserveConfigFromFile.borrowLimitOutsideElevationGroup),
|
|
1017
|
+
borrowLimitAgainstThisCollateralInElevationGroup: parseReserveBorrowLimitAgainstCollInEmode(reserveConfigFromFile),
|
|
1018
|
+
deleveragingBonusIncreaseBpsPerDay: new anchor_1.BN(reserveConfigFromFile.deleveragingBonusIncreaseBpsPerDay),
|
|
1019
|
+
reserved1: Array(1).fill(0),
|
|
1010
1020
|
reserved2: Array(2).fill(0),
|
|
1011
1021
|
reserved3: Array(8).fill(0),
|
|
1012
1022
|
};
|
|
1013
1023
|
return new types_1.ReserveConfig(reserveConfigFields);
|
|
1014
1024
|
}
|
|
1015
|
-
function parseOracleConfiguration(
|
|
1025
|
+
function parseOracleConfiguration(reserveConfigFromFile) {
|
|
1016
1026
|
const pythConfiguration = new types_2.PythConfiguration({
|
|
1017
|
-
price: new web3_js_1.PublicKey(
|
|
1027
|
+
price: new web3_js_1.PublicKey(reserveConfigFromFile.tokenInfo.pythConfiguration.price),
|
|
1018
1028
|
});
|
|
1019
1029
|
const switchboardConfiguration = new types_2.SwitchboardConfiguration({
|
|
1020
|
-
priceAggregator: new web3_js_1.PublicKey(
|
|
1021
|
-
twapAggregator: new web3_js_1.PublicKey(
|
|
1030
|
+
priceAggregator: new web3_js_1.PublicKey(reserveConfigFromFile.tokenInfo.switchboardConfiguration.priceAggregator),
|
|
1031
|
+
twapAggregator: new web3_js_1.PublicKey(reserveConfigFromFile.tokenInfo.switchboardConfiguration.twapAggregator),
|
|
1022
1032
|
});
|
|
1023
1033
|
const priceChain = [65535, 65535, 65535, 65535];
|
|
1024
1034
|
const twapChain = [65535, 65535, 65535, 65535];
|
|
1025
|
-
const priceChainFromFile =
|
|
1026
|
-
const twapChainFromFile =
|
|
1035
|
+
const priceChainFromFile = reserveConfigFromFile.tokenInfo.scopeConfiguration.priceChain;
|
|
1036
|
+
const twapChainFromFile = reserveConfigFromFile.tokenInfo.scopeConfiguration.twapChain;
|
|
1027
1037
|
priceChainFromFile.forEach((value, index) => (priceChain[index] = value));
|
|
1028
1038
|
twapChainFromFile.forEach((value, index) => (twapChain[index] = value));
|
|
1029
1039
|
const scopeConfiguration = new types_1.ScopeConfiguration({
|
|
1030
|
-
priceFeed: new web3_js_1.PublicKey(
|
|
1040
|
+
priceFeed: new web3_js_1.PublicKey(reserveConfigFromFile.tokenInfo.scopeConfiguration.priceFeed),
|
|
1031
1041
|
priceChain: priceChain,
|
|
1032
1042
|
twapChain: twapChain,
|
|
1033
1043
|
});
|
|
@@ -1037,20 +1047,20 @@ function parseOracleConfiguration(farmConfigFromFile) {
|
|
|
1037
1047
|
scopeConfiguration,
|
|
1038
1048
|
};
|
|
1039
1049
|
}
|
|
1040
|
-
function parseBorrowRateCurve(
|
|
1050
|
+
function parseBorrowRateCurve(reserveConfigFromFile) {
|
|
1041
1051
|
const curvePoints = [];
|
|
1042
|
-
|
|
1052
|
+
reserveConfigFromFile.borrowRateCurve.points.forEach((curvePoint) => curvePoints.push({
|
|
1043
1053
|
utilizationRateBps: curvePoint.utilizationRateBps,
|
|
1044
1054
|
borrowRateBps: curvePoint.borrowRateBps,
|
|
1045
1055
|
}));
|
|
1046
|
-
const
|
|
1047
|
-
curvePoints.forEach((curvePoint, index) => (
|
|
1048
|
-
const borrowRateCurve = new types_1.BorrowRateCurve({ points:
|
|
1056
|
+
const finalCurvePoints = Array(11).fill(curvePoints[curvePoints.length - 1]);
|
|
1057
|
+
curvePoints.forEach((curvePoint, index) => (finalCurvePoints[index] = curvePoint));
|
|
1058
|
+
const borrowRateCurve = new types_1.BorrowRateCurve({ points: finalCurvePoints });
|
|
1049
1059
|
return borrowRateCurve;
|
|
1050
1060
|
}
|
|
1051
|
-
function parseReserveBorrowLimitAgainstCollInEmode(
|
|
1061
|
+
function parseReserveBorrowLimitAgainstCollInEmode(reserveConfigFromFile) {
|
|
1052
1062
|
const reserveBorrowLimitAgainstCollInEmode = Array(32).fill(new anchor_1.BN(0));
|
|
1053
|
-
|
|
1063
|
+
reserveConfigFromFile.borrowLimitAgainstThisCollateralInElevationGroup.forEach((limit, index) => (reserveBorrowLimitAgainstCollInEmode[index] = new anchor_1.BN(limit)));
|
|
1054
1064
|
return reserveBorrowLimitAgainstCollInEmode;
|
|
1055
1065
|
}
|
|
1056
1066
|
function parseReserveConfigToFile(reserveConfig) {
|