@kamino-finance/klend-sdk 7.2.2 → 7.2.4
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/farm_utils.d.ts +1 -0
- package/dist/classes/farm_utils.d.ts.map +1 -1
- package/dist/classes/farm_utils.js +2 -1
- package/dist/classes/farm_utils.js.map +1 -1
- package/dist/classes/manager.d.ts +12 -3
- package/dist/classes/manager.d.ts.map +1 -1
- package/dist/classes/manager.js +23 -5
- package/dist/classes/manager.js.map +1 -1
- package/dist/classes/vault.d.ts +16 -4
- package/dist/classes/vault.d.ts.map +1 -1
- package/dist/classes/vault.js +53 -23
- package/dist/classes/vault.js.map +1 -1
- package/dist/classes/vault_types.d.ts +8 -1
- package/dist/classes/vault_types.d.ts.map +1 -1
- package/dist/manager/client_kamino_manager.js +40 -12
- package/dist/manager/client_kamino_manager.js.map +1 -1
- package/dist/utils/lookupTable.d.ts +1 -1
- package/dist/utils/lookupTable.d.ts.map +1 -1
- package/dist/utils/lookupTable.js +9 -3
- package/dist/utils/lookupTable.js.map +1 -1
- package/dist/utils/vaultAllocation.d.ts +4 -3
- package/dist/utils/vaultAllocation.d.ts.map +1 -1
- package/dist/utils/vaultAllocation.js +8 -5
- package/dist/utils/vaultAllocation.js.map +1 -1
- package/package.json +2 -2
- package/src/classes/farm_utils.ts +1 -0
- package/src/classes/manager.ts +36 -5
- package/src/classes/vault.ts +121 -35
- package/src/classes/vault_types.ts +9 -1
- package/src/manager/client_kamino_manager.ts +60 -14
- package/src/utils/lookupTable.ts +8 -3
- package/src/utils/vaultAllocation.ts +9 -5
package/src/classes/manager.ts
CHANGED
|
@@ -80,6 +80,7 @@ import { VaultConfigField, VaultConfigFieldKind } from '../@codegen/kvault/types
|
|
|
80
80
|
import {
|
|
81
81
|
AcceptVaultOwnershipIxs,
|
|
82
82
|
APYs,
|
|
83
|
+
CreateVaultFarm,
|
|
83
84
|
DepositIxs,
|
|
84
85
|
DisinvestAllReservesIxs,
|
|
85
86
|
InitVaultIxs,
|
|
@@ -238,6 +239,23 @@ export class KaminoManager {
|
|
|
238
239
|
return this._vaultClient.createVaultIxs(vaultConfig);
|
|
239
240
|
}
|
|
240
241
|
|
|
242
|
+
/**
|
|
243
|
+
* This method creates a farm for a vault
|
|
244
|
+
* @param admin - the admin of the vault
|
|
245
|
+
* @param vault - the vault to create a farm for (the vault should be already initialized)
|
|
246
|
+
* @returns a struct with the farm, the setup farm ixs and the update farm ixs
|
|
247
|
+
*/
|
|
248
|
+
async createVaultFarmIxs(admin: TransactionSigner, vault: KaminoVault): Promise<CreateVaultFarm> {
|
|
249
|
+
const vaultState = await vault.getState();
|
|
250
|
+
if (!vaultState) {
|
|
251
|
+
throw new Error('Vault not initialized');
|
|
252
|
+
}
|
|
253
|
+
if (vaultState.vaultFarm !== DEFAULT_PUBLIC_KEY) {
|
|
254
|
+
throw new Error('Vault already has a farm');
|
|
255
|
+
}
|
|
256
|
+
return this._vaultClient.createVaultFarm(admin, vault.address, vaultState.sharesMint);
|
|
257
|
+
}
|
|
258
|
+
|
|
241
259
|
/**
|
|
242
260
|
* This method creates an instruction to set the shares metadata for a vault
|
|
243
261
|
* @param authority - the vault admin
|
|
@@ -581,20 +599,24 @@ export class KaminoManager {
|
|
|
581
599
|
* @param mode the field to update (based on VaultConfigFieldKind enum)
|
|
582
600
|
* @param value the value to update the field with
|
|
583
601
|
* @param [signer] the signer of the transaction. Optional. If not provided the admin of the vault will be used. It should be used when changing the admin of the vault if we want to build or batch multiple ixs in the same tx
|
|
602
|
+
* @param [lutIxsSigner] the signer of the transaction to be used for the lookup table instructions. Optional. If not provided the admin of the vault will be used. It should be used when changing the admin of the vault if we want to build or batch multiple ixs in the same tx
|
|
603
|
+
* @param [skipLutUpdate] if true, the lookup table instructions will not be included in the returned instructions
|
|
584
604
|
* @returns a struct that contains the instruction to update the field and an optional list of instructions to update the lookup table
|
|
585
605
|
*/
|
|
586
606
|
async updateVaultConfigIxs(
|
|
587
607
|
vault: KaminoVault,
|
|
588
608
|
mode: VaultConfigFieldKind | string,
|
|
589
609
|
value: string,
|
|
590
|
-
signer?: TransactionSigner
|
|
610
|
+
signer?: TransactionSigner,
|
|
611
|
+
lutIxsSigner?: TransactionSigner,
|
|
612
|
+
skipLutUpdate: boolean = false
|
|
591
613
|
): Promise<UpdateVaultConfigIxs> {
|
|
592
614
|
if (typeof mode === 'string') {
|
|
593
615
|
const field = VaultConfigField.fromDecoded({ [mode]: '' });
|
|
594
|
-
return this._vaultClient.updateVaultConfigIxs(vault, field, value, signer);
|
|
616
|
+
return this._vaultClient.updateVaultConfigIxs(vault, field, value, signer, lutIxsSigner, skipLutUpdate);
|
|
595
617
|
}
|
|
596
618
|
|
|
597
|
-
return this._vaultClient.updateVaultConfigIxs(vault, mode, value, signer);
|
|
619
|
+
return this._vaultClient.updateVaultConfigIxs(vault, mode, value, signer, lutIxsSigner, skipLutUpdate);
|
|
598
620
|
}
|
|
599
621
|
|
|
600
622
|
/** Sets the farm where the shares can be staked. This is store in vault state and a vault can only have one farm, so the new farm will ovveride the old farm
|
|
@@ -607,9 +629,18 @@ export class KaminoManager {
|
|
|
607
629
|
vault: KaminoVault,
|
|
608
630
|
farm: Address,
|
|
609
631
|
errorOnOverride: boolean = true,
|
|
610
|
-
vaultAdminAuthority?: TransactionSigner
|
|
632
|
+
vaultAdminAuthority?: TransactionSigner,
|
|
633
|
+
lutIxsSigner?: TransactionSigner,
|
|
634
|
+
skipLutUpdate: boolean = false
|
|
611
635
|
): Promise<UpdateVaultConfigIxs> {
|
|
612
|
-
return this._vaultClient.setVaultFarmIxs(
|
|
636
|
+
return this._vaultClient.setVaultFarmIxs(
|
|
637
|
+
vault,
|
|
638
|
+
farm,
|
|
639
|
+
errorOnOverride,
|
|
640
|
+
vaultAdminAuthority,
|
|
641
|
+
lutIxsSigner,
|
|
642
|
+
skipLutUpdate
|
|
643
|
+
);
|
|
613
644
|
}
|
|
614
645
|
|
|
615
646
|
/**
|
package/src/classes/vault.ts
CHANGED
|
@@ -93,6 +93,7 @@ import { getAccountOwner, getProgramAccounts } from '../utils/rpc';
|
|
|
93
93
|
import {
|
|
94
94
|
AcceptVaultOwnershipIxs,
|
|
95
95
|
APYs,
|
|
96
|
+
CreateVaultFarm,
|
|
96
97
|
DepositIxs,
|
|
97
98
|
DisinvestAllReservesIxs,
|
|
98
99
|
InitVaultIxs,
|
|
@@ -107,9 +108,11 @@ import {
|
|
|
107
108
|
} from './vault_types';
|
|
108
109
|
import { batchFetch, collToLamportsDecimal, ZERO } from '@kamino-finance/kliquidity-sdk';
|
|
109
110
|
import { FullBPSDecimal } from '@kamino-finance/kliquidity-sdk/dist/utils/CreationParameters';
|
|
110
|
-
import { FarmIncentives, FarmState, getUserStatePDA } from '@kamino-finance/farms-sdk/dist';
|
|
111
|
+
import { FarmConfigOption, FarmIncentives, FarmState, getUserStatePDA } from '@kamino-finance/farms-sdk/dist';
|
|
111
112
|
import { getAccountsInLut, initLookupTableIx, insertIntoLookupTableIxs } from '../utils/lookupTable';
|
|
112
113
|
import {
|
|
114
|
+
FARMS_ADMIN_MAINNET,
|
|
115
|
+
FARMS_GLOBAL_CONFIG_MAINNET,
|
|
113
116
|
getFarmStakeIxs,
|
|
114
117
|
getFarmUnstakeAndWithdrawIxs,
|
|
115
118
|
getSharesInFarmUserPosition,
|
|
@@ -285,6 +288,8 @@ export class KaminoVaultClient {
|
|
|
285
288
|
};
|
|
286
289
|
const initVaultIx = initVault(initVaultAccounts, undefined, this._kaminoVaultProgramId);
|
|
287
290
|
|
|
291
|
+
const createVaultFarm = await this.createVaultFarm(vaultConfig.admin, vaultState.address, sharesMint);
|
|
292
|
+
|
|
288
293
|
// create and set up the vault lookup table
|
|
289
294
|
const [createLUTIx, lut] = await initLookupTableIx(vaultConfig.admin, slot);
|
|
290
295
|
|
|
@@ -300,6 +305,8 @@ export class KaminoVaultClient {
|
|
|
300
305
|
TOKEN_PROGRAM_ADDRESS,
|
|
301
306
|
this._kaminoLendProgramId,
|
|
302
307
|
SYSVAR_INSTRUCTIONS_ADDRESS,
|
|
308
|
+
createVaultFarm.farm.address,
|
|
309
|
+
FARMS_GLOBAL_CONFIG_MAINNET,
|
|
303
310
|
];
|
|
304
311
|
const insertIntoLUTIxs = await insertIntoLookupTableIxs(
|
|
305
312
|
this.getConnection(),
|
|
@@ -345,6 +352,12 @@ export class KaminoVaultClient {
|
|
|
345
352
|
);
|
|
346
353
|
ixs.push(setNameIx);
|
|
347
354
|
}
|
|
355
|
+
const setFarmIx = this.updateUninitialisedVaultConfigIx(
|
|
356
|
+
vaultConfig.admin,
|
|
357
|
+
vaultState.address,
|
|
358
|
+
new VaultConfigField.Farm(),
|
|
359
|
+
createVaultFarm.farm.address
|
|
360
|
+
);
|
|
348
361
|
|
|
349
362
|
const metadataIx = await this.getSetSharesMetadataIx(
|
|
350
363
|
this.getConnection(),
|
|
@@ -366,10 +379,57 @@ export class KaminoVaultClient {
|
|
|
366
379
|
populateLUTIxs: insertIntoLUTIxs,
|
|
367
380
|
cleanupIxs,
|
|
368
381
|
initSharesMetadataIx: metadataIx,
|
|
382
|
+
createVaultFarm,
|
|
383
|
+
setFarmToVaultIx: setFarmIx,
|
|
369
384
|
},
|
|
370
385
|
};
|
|
371
386
|
}
|
|
372
387
|
|
|
388
|
+
/**
|
|
389
|
+
* This method creates a farm for a vault
|
|
390
|
+
* @param signer - the signer of the transaction
|
|
391
|
+
* @param vaultSharesMint - the mint of the vault shares
|
|
392
|
+
* @param vaultAddress - the address of the vault (it doesn't need to be already initialized)
|
|
393
|
+
* @returns a struct with the farm, the setup farm ixs and the update farm ixs
|
|
394
|
+
*/
|
|
395
|
+
async createVaultFarm(
|
|
396
|
+
signer: TransactionSigner,
|
|
397
|
+
vaultAddress: Address,
|
|
398
|
+
vaultSharesMint: Address
|
|
399
|
+
): Promise<CreateVaultFarm> {
|
|
400
|
+
const farmsSDK = new Farms(this._rpc);
|
|
401
|
+
|
|
402
|
+
const farm = await generateKeyPairSigner();
|
|
403
|
+
const ixs = await farmsSDK.createFarmIxs(signer, farm, FARMS_GLOBAL_CONFIG_MAINNET, vaultSharesMint);
|
|
404
|
+
|
|
405
|
+
const updatePendingFarmAdminIx = await farmsSDK.updateFarmConfigIx(
|
|
406
|
+
signer,
|
|
407
|
+
farm.address,
|
|
408
|
+
DEFAULT_PUBLIC_KEY,
|
|
409
|
+
new FarmConfigOption.UpdatePendingFarmAdmin(),
|
|
410
|
+
FARMS_ADMIN_MAINNET,
|
|
411
|
+
undefined,
|
|
412
|
+
undefined,
|
|
413
|
+
true
|
|
414
|
+
);
|
|
415
|
+
const updateFarmVaultIdIx = await farmsSDK.updateFarmConfigIx(
|
|
416
|
+
signer,
|
|
417
|
+
farm.address,
|
|
418
|
+
DEFAULT_PUBLIC_KEY,
|
|
419
|
+
new FarmConfigOption.UpdateVaultId(),
|
|
420
|
+
vaultAddress,
|
|
421
|
+
undefined,
|
|
422
|
+
undefined,
|
|
423
|
+
true
|
|
424
|
+
);
|
|
425
|
+
|
|
426
|
+
return {
|
|
427
|
+
farm,
|
|
428
|
+
setupFarmIxs: ixs,
|
|
429
|
+
updateFarmIxs: [updatePendingFarmAdminIx, updateFarmVaultIdIx],
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
|
|
373
433
|
/**
|
|
374
434
|
* This method creates an instruction to set the shares metadata for a vault
|
|
375
435
|
* @param rpc
|
|
@@ -697,13 +757,17 @@ export class KaminoVaultClient {
|
|
|
697
757
|
* @param mode the field to update (based on VaultConfigFieldKind enum)
|
|
698
758
|
* @param value the value to update the field with
|
|
699
759
|
* @param [vaultAdminAuthority] the signer of the transaction. Optional. If not provided the admin of the vault will be used. It should be used when changing the admin of the vault if we want to build or batch multiple ixs in the same tx
|
|
760
|
+
* @param [lutIxsSigner] the signer of the transaction to be used for the lookup table instructions. Optional. If not provided the admin of the vault will be used. It should be used when changing the admin of the vault if we want to build or batch multiple ixs in the same tx
|
|
761
|
+
* @param [skipLutUpdate] if true, the lookup table instructions will not be included in the returned instructions
|
|
700
762
|
* @returns a struct that contains the instruction to update the field and an optional list of instructions to update the lookup table
|
|
701
763
|
*/
|
|
702
764
|
async updateVaultConfigIxs(
|
|
703
765
|
vault: KaminoVault,
|
|
704
766
|
mode: VaultConfigFieldKind,
|
|
705
767
|
value: string,
|
|
706
|
-
vaultAdminAuthority?: TransactionSigner
|
|
768
|
+
vaultAdminAuthority?: TransactionSigner,
|
|
769
|
+
lutIxsSigner?: TransactionSigner,
|
|
770
|
+
skipLutUpdate: boolean = false
|
|
707
771
|
): Promise<UpdateVaultConfigIxs> {
|
|
708
772
|
const vaultState: VaultState = await vault.getState();
|
|
709
773
|
const admin = parseVaultAdmin(vaultState, vaultAdminAuthority);
|
|
@@ -753,36 +817,41 @@ export class KaminoVaultClient {
|
|
|
753
817
|
|
|
754
818
|
const updateLUTIxs: Instruction[] = [];
|
|
755
819
|
|
|
756
|
-
if (
|
|
757
|
-
const
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
[newPubkey]
|
|
763
|
-
);
|
|
764
|
-
updateLUTIxs.push(...insertIntoLutIxs);
|
|
765
|
-
} else if (mode.kind === new VaultConfigField.Farm().kind) {
|
|
766
|
-
const keysToAddToLUT = [address(value)];
|
|
767
|
-
// if the farm already exist we want to read its state to add it to the LUT
|
|
768
|
-
try {
|
|
769
|
-
const farmState = await FarmState.fetch(this.getConnection(), keysToAddToLUT[0]);
|
|
770
|
-
keysToAddToLUT.push(
|
|
771
|
-
farmState!.farmVault,
|
|
772
|
-
farmState!.farmVaultsAuthority,
|
|
773
|
-
farmState!.token.mint,
|
|
774
|
-
farmState!.scopePrices,
|
|
775
|
-
farmState!.globalConfig
|
|
776
|
-
);
|
|
820
|
+
if (!skipLutUpdate) {
|
|
821
|
+
const lutIxsSignerAccount = lutIxsSigner ? lutIxsSigner : admin;
|
|
822
|
+
|
|
823
|
+
if (mode.kind === new VaultConfigField.PendingVaultAdmin().kind) {
|
|
824
|
+
const newPubkey = address(value);
|
|
825
|
+
|
|
777
826
|
const insertIntoLutIxs = await insertIntoLookupTableIxs(
|
|
778
827
|
this.getConnection(),
|
|
779
|
-
|
|
828
|
+
lutIxsSignerAccount,
|
|
780
829
|
vaultState.vaultLookupTable,
|
|
781
|
-
|
|
830
|
+
[newPubkey]
|
|
782
831
|
);
|
|
783
832
|
updateLUTIxs.push(...insertIntoLutIxs);
|
|
784
|
-
}
|
|
785
|
-
|
|
833
|
+
} else if (mode.kind === new VaultConfigField.Farm().kind) {
|
|
834
|
+
const keysToAddToLUT = [address(value)];
|
|
835
|
+
// if the farm already exist we want to read its state to add it to the LUT
|
|
836
|
+
try {
|
|
837
|
+
const farmState = await FarmState.fetch(this.getConnection(), keysToAddToLUT[0]);
|
|
838
|
+
keysToAddToLUT.push(
|
|
839
|
+
farmState!.farmVault,
|
|
840
|
+
farmState!.farmVaultsAuthority,
|
|
841
|
+
farmState!.token.mint,
|
|
842
|
+
farmState!.scopePrices,
|
|
843
|
+
farmState!.globalConfig
|
|
844
|
+
);
|
|
845
|
+
const insertIntoLutIxs = await insertIntoLookupTableIxs(
|
|
846
|
+
this.getConnection(),
|
|
847
|
+
lutIxsSignerAccount,
|
|
848
|
+
vaultState.vaultLookupTable,
|
|
849
|
+
keysToAddToLUT
|
|
850
|
+
);
|
|
851
|
+
updateLUTIxs.push(...insertIntoLutIxs);
|
|
852
|
+
} catch (error) {
|
|
853
|
+
console.log(`Error fetching farm ${keysToAddToLUT[0].toString()} state`, error);
|
|
854
|
+
}
|
|
786
855
|
}
|
|
787
856
|
}
|
|
788
857
|
|
|
@@ -799,19 +868,30 @@ export class KaminoVaultClient {
|
|
|
799
868
|
* @param farm - the farm where the vault shares can be staked
|
|
800
869
|
* @param [errorOnOverride] - if true, the function will throw an error if the vault already has a farm. If false, it will override the farm
|
|
801
870
|
* @param [vaultAdminAuthority] - vault admin - a noop vaultAdminAuthority is provided when absent for multisigs
|
|
802
|
-
*
|
|
871
|
+
* @param [lutIxsSigner] - the signer of the transaction to be used for the lookup table instructions. Optional. If not provided the admin of the vault will be used. It should be used when changing the admin of the vault if we want to build or batch multiple ixs in the same tx
|
|
872
|
+
* @param [skipLutUpdate] - if true, the lookup table instructions will not be included in the returned instructions
|
|
873
|
+
* @returns - a struct that contains the instruction to update the farm and an optional list of instructions to update the lookup table
|
|
803
874
|
*/
|
|
804
875
|
async setVaultFarmIxs(
|
|
805
876
|
vault: KaminoVault,
|
|
806
877
|
farm: Address,
|
|
807
878
|
errorOnOverride: boolean = true,
|
|
808
|
-
vaultAdminAuthority?: TransactionSigner
|
|
879
|
+
vaultAdminAuthority?: TransactionSigner,
|
|
880
|
+
lutIxsSigner?: TransactionSigner,
|
|
881
|
+
skipLutUpdate: boolean = false
|
|
809
882
|
): Promise<UpdateVaultConfigIxs> {
|
|
810
883
|
const vaultHasFarm = await vault.hasFarm();
|
|
811
884
|
if (vaultHasFarm && errorOnOverride) {
|
|
812
885
|
throw new Error('Vault already has a farm, if you want to override it set errorOnOverride to false');
|
|
813
886
|
}
|
|
814
|
-
return this.updateVaultConfigIxs(
|
|
887
|
+
return this.updateVaultConfigIxs(
|
|
888
|
+
vault,
|
|
889
|
+
new VaultConfigField.Farm(),
|
|
890
|
+
farm,
|
|
891
|
+
vaultAdminAuthority,
|
|
892
|
+
lutIxsSigner,
|
|
893
|
+
skipLutUpdate
|
|
894
|
+
);
|
|
815
895
|
}
|
|
816
896
|
|
|
817
897
|
/**
|
|
@@ -1916,7 +1996,8 @@ export class KaminoVaultClient {
|
|
|
1916
1996
|
holdings.totalAUMIncludingFees.sub(holdings.pendingFees),
|
|
1917
1997
|
new Decimal(vaultState.unallocatedWeight.toString()),
|
|
1918
1998
|
new Decimal(vaultState.unallocatedTokensCap.toString()),
|
|
1919
|
-
initialVaultAllocations
|
|
1999
|
+
initialVaultAllocations,
|
|
2000
|
+
vaultState.tokenMintDecimals.toNumber()
|
|
1920
2001
|
);
|
|
1921
2002
|
}
|
|
1922
2003
|
|
|
@@ -1924,9 +2005,16 @@ export class KaminoVaultClient {
|
|
|
1924
2005
|
vaultAUM: Decimal,
|
|
1925
2006
|
vaultUnallocatedWeight: Decimal,
|
|
1926
2007
|
vaultUnallocatedCap: Decimal,
|
|
1927
|
-
initialVaultAllocations: Map<Address, ReserveAllocationOverview
|
|
2008
|
+
initialVaultAllocations: Map<Address, ReserveAllocationOverview>,
|
|
2009
|
+
vaultTokenDecimals: number
|
|
1928
2010
|
) {
|
|
1929
|
-
return computeReservesAllocation(
|
|
2011
|
+
return computeReservesAllocation(
|
|
2012
|
+
vaultAUM,
|
|
2013
|
+
vaultUnallocatedWeight,
|
|
2014
|
+
vaultUnallocatedCap,
|
|
2015
|
+
initialVaultAllocations,
|
|
2016
|
+
vaultTokenDecimals
|
|
2017
|
+
);
|
|
1930
2018
|
}
|
|
1931
2019
|
|
|
1932
2020
|
/**
|
|
@@ -2018,9 +2106,7 @@ export class KaminoVaultClient {
|
|
|
2018
2106
|
if (await vault.hasFarm()) {
|
|
2019
2107
|
const userFarmState = allUserFarmStatesMap.get(state.vaultFarm);
|
|
2020
2108
|
if (userFarmState) {
|
|
2021
|
-
console.log('there is a farm state for vault', vault.address);
|
|
2022
2109
|
const stakedShares = getSharesInFarmUserPosition(userFarmState, state.sharesMintDecimals.toNumber());
|
|
2023
|
-
console.log('staked shares', stakedShares);
|
|
2024
2110
|
const userSharesBalance = vaultUserShareBalance.get(vault.address);
|
|
2025
2111
|
if (userSharesBalance) {
|
|
2026
2112
|
userSharesBalance.stakedShares = stakedShares;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Address, Instruction } from '@solana/kit';
|
|
1
|
+
import { Address, Instruction, TransactionSigner } 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 */
|
|
@@ -9,6 +9,8 @@ export type InitVaultIxs = {
|
|
|
9
9
|
populateLUTIxs: Instruction[];
|
|
10
10
|
cleanupIxs: Instruction[];
|
|
11
11
|
initSharesMetadataIx: Instruction;
|
|
12
|
+
createVaultFarm: CreateVaultFarm;
|
|
13
|
+
setFarmToVaultIx: Instruction;
|
|
12
14
|
};
|
|
13
15
|
|
|
14
16
|
export type AcceptVaultOwnershipIxs = {
|
|
@@ -78,3 +80,9 @@ export type APYs = {
|
|
|
78
80
|
grossAPY: Decimal;
|
|
79
81
|
netAPY: Decimal;
|
|
80
82
|
};
|
|
83
|
+
|
|
84
|
+
export type CreateVaultFarm = {
|
|
85
|
+
farm: TransactionSigner;
|
|
86
|
+
setupFarmIxs: Instruction[];
|
|
87
|
+
updateFarmIxs: Instruction[];
|
|
88
|
+
};
|
|
@@ -48,7 +48,7 @@ import { initEnv, ManagerEnv } from './tx/ManagerEnv';
|
|
|
48
48
|
import { processTx } from './tx/processor';
|
|
49
49
|
import { getPriorityFeeAndCuIxs } from '../client/tx/priorityFee';
|
|
50
50
|
import { fetchAddressLookupTable, fetchAllAddressLookupTable } from '@solana-program/address-lookup-table';
|
|
51
|
-
import { noopSigner } from '../utils/signer';
|
|
51
|
+
import { noopSigner, parseKeypairFile } from '../utils/signer';
|
|
52
52
|
|
|
53
53
|
dotenv.config({
|
|
54
54
|
path: `.env${process.env.ENV ? '.' + process.env.ENV : ''}`,
|
|
@@ -352,6 +352,22 @@ async function main() {
|
|
|
352
352
|
...instructions.createAtaIfNeededIxs,
|
|
353
353
|
...instructions.initVaultIxs,
|
|
354
354
|
instructions.createLUTIx,
|
|
355
|
+
instructions.setFarmToVaultIx,
|
|
356
|
+
...getPriorityFeeAndCuIxs({
|
|
357
|
+
priorityFeeMultiplier: 2500,
|
|
358
|
+
}),
|
|
359
|
+
],
|
|
360
|
+
mode,
|
|
361
|
+
[]
|
|
362
|
+
);
|
|
363
|
+
await sleep(2000);
|
|
364
|
+
// create the farm
|
|
365
|
+
await processTx(
|
|
366
|
+
env.c,
|
|
367
|
+
admin,
|
|
368
|
+
[
|
|
369
|
+
...instructions.createVaultFarm.setupFarmIxs,
|
|
370
|
+
...instructions.createVaultFarm.updateFarmIxs,
|
|
355
371
|
...getPriorityFeeAndCuIxs({
|
|
356
372
|
priorityFeeMultiplier: 2500,
|
|
357
373
|
}),
|
|
@@ -455,7 +471,9 @@ async function main() {
|
|
|
455
471
|
kaminoVault,
|
|
456
472
|
new PendingVaultAdmin(),
|
|
457
473
|
newAdmin,
|
|
458
|
-
signer
|
|
474
|
+
signer,
|
|
475
|
+
undefined,
|
|
476
|
+
true
|
|
459
477
|
);
|
|
460
478
|
|
|
461
479
|
await processTx(
|
|
@@ -485,7 +503,12 @@ async function main() {
|
|
|
485
503
|
'simulate|multisig|execute - simulate - to print txn simulation and to get tx simulation link in explorer, execute - execute tx, multisig - to get bs58 tx for multisig usage'
|
|
486
504
|
)
|
|
487
505
|
.option(`--staging`, 'If true, will use the staging programs')
|
|
488
|
-
.
|
|
506
|
+
.option(`--skip-lut-update`, 'If set, it will skip the LUT update')
|
|
507
|
+
.option(
|
|
508
|
+
`--lutSigner <string>`,
|
|
509
|
+
'If set, it will use the provided signer instead of the default one for the LUT update'
|
|
510
|
+
)
|
|
511
|
+
.action(async ({ vault, field, value, mode, staging, skipLutUpdate, lutSigner }) => {
|
|
489
512
|
const env = await initEnv(staging);
|
|
490
513
|
const vaultAddress = address(vault);
|
|
491
514
|
|
|
@@ -500,7 +523,20 @@ async function main() {
|
|
|
500
523
|
const vaultState = await kaminoVault.getState();
|
|
501
524
|
const signer = await env.getSigner({ vaultState });
|
|
502
525
|
|
|
503
|
-
|
|
526
|
+
let lutSignerOrUndefined = undefined;
|
|
527
|
+
if (lutSigner) {
|
|
528
|
+
lutSignerOrUndefined = await parseKeypairFile(lutSigner as string);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
const shouldSkipLutUpdate = !!skipLutUpdate;
|
|
532
|
+
const instructions = await kaminoManager.updateVaultConfigIxs(
|
|
533
|
+
kaminoVault,
|
|
534
|
+
field,
|
|
535
|
+
value,
|
|
536
|
+
signer,
|
|
537
|
+
lutSignerOrUndefined,
|
|
538
|
+
shouldSkipLutUpdate
|
|
539
|
+
);
|
|
504
540
|
|
|
505
541
|
await processTx(
|
|
506
542
|
env.c,
|
|
@@ -576,10 +612,15 @@ async function main() {
|
|
|
576
612
|
)
|
|
577
613
|
.option(`--staging`, 'If true, will use the staging programs')
|
|
578
614
|
.option(`--multisig <string>`, 'If using multisig mode this is required, otherwise will be ignored')
|
|
579
|
-
.
|
|
615
|
+
.option(`--signer <string>`, 'If set, it will use the provided signer instead of the default one')
|
|
616
|
+
.action(async ({ lut, addresses, mode, staging, multisig, signer }) => {
|
|
580
617
|
const env = await initEnv(multisig, staging);
|
|
581
618
|
const lutAddress = address(lut);
|
|
582
|
-
|
|
619
|
+
let txSigner = await env.getSigner();
|
|
620
|
+
// if the signer is provided (path to a keypair) we use it, otherwise we use the default one
|
|
621
|
+
if (signer) {
|
|
622
|
+
txSigner = await parseKeypairFile(signer as string);
|
|
623
|
+
}
|
|
583
624
|
const addressesArr = addresses.split(' ').map((a: string) => address(a));
|
|
584
625
|
|
|
585
626
|
if (mode === 'multisig' && !multisig) {
|
|
@@ -593,12 +634,11 @@ async function main() {
|
|
|
593
634
|
env.kvaultProgramId
|
|
594
635
|
);
|
|
595
636
|
|
|
596
|
-
const
|
|
597
|
-
const instructions = await kaminoManager.insertIntoLutIxs(signer, lutAddress, addressesArr);
|
|
637
|
+
const instructions = await kaminoManager.insertIntoLutIxs(txSigner, lutAddress, addressesArr);
|
|
598
638
|
|
|
599
639
|
await processTx(
|
|
600
640
|
env.c,
|
|
601
|
-
|
|
641
|
+
txSigner,
|
|
602
642
|
[
|
|
603
643
|
...instructions,
|
|
604
644
|
...getPriorityFeeAndCuIxs({
|
|
@@ -640,7 +680,8 @@ async function main() {
|
|
|
640
680
|
'simulate|multisig|execute - simulate - to print txn simulation and to get tx simulation link in explorer, execute - execute tx, multisig - to get bs58 tx for multisig usage'
|
|
641
681
|
)
|
|
642
682
|
.option(`--staging`, 'If true, will use the staging programs')
|
|
643
|
-
.
|
|
683
|
+
.option(`--signer <string>`, 'If set, it will use the provided signer instead of the default one')
|
|
684
|
+
.action(async ({ vault, mode, staging, signer }) => {
|
|
644
685
|
const env = await initEnv(staging);
|
|
645
686
|
const vaultAddress = address(vault);
|
|
646
687
|
|
|
@@ -653,14 +694,18 @@ async function main() {
|
|
|
653
694
|
|
|
654
695
|
const kaminoVault = new KaminoVault(env.c.rpc, vaultAddress, undefined, env.kvaultProgramId);
|
|
655
696
|
const vaultState = await kaminoVault.getState();
|
|
656
|
-
|
|
657
|
-
|
|
697
|
+
let txSigner = await env.getSigner({ vaultState });
|
|
698
|
+
// if the signer is provided (path to a keypair) we use it, otherwise we use the default one
|
|
699
|
+
if (signer) {
|
|
700
|
+
txSigner = await parseKeypairFile(signer as string);
|
|
701
|
+
}
|
|
702
|
+
const syncLUTIxs = await kaminoManager.syncVaultLUTIxs(txSigner, kaminoVault);
|
|
658
703
|
|
|
659
704
|
// if we need to create the LUT we have to do that in a separate tx and wait a little bit after
|
|
660
705
|
if (syncLUTIxs.setupLUTIfNeededIxs.length > 0) {
|
|
661
706
|
await processTx(
|
|
662
707
|
env.c,
|
|
663
|
-
|
|
708
|
+
txSigner,
|
|
664
709
|
[
|
|
665
710
|
...syncLUTIxs.setupLUTIfNeededIxs,
|
|
666
711
|
...getPriorityFeeAndCuIxs({
|
|
@@ -677,7 +722,7 @@ async function main() {
|
|
|
677
722
|
for (const ix of syncLUTIxs.syncLUTIxs) {
|
|
678
723
|
await processTx(
|
|
679
724
|
env.c,
|
|
680
|
-
|
|
725
|
+
txSigner,
|
|
681
726
|
[
|
|
682
727
|
ix,
|
|
683
728
|
...getPriorityFeeAndCuIxs({
|
|
@@ -1353,6 +1398,7 @@ async function main() {
|
|
|
1353
1398
|
console.log('reserve ', reserveAddress);
|
|
1354
1399
|
console.log('reserve incentive', incentive);
|
|
1355
1400
|
});
|
|
1401
|
+
console.log('totalIncentivesAPY', vaultOverview.reservesFarmsIncentives.totalIncentivesAPY.toString());
|
|
1356
1402
|
});
|
|
1357
1403
|
|
|
1358
1404
|
commands
|
package/src/utils/lookupTable.ts
CHANGED
|
@@ -110,11 +110,16 @@ export function closeLookupTableIx(authority: TransactionSigner, lookupTable: Ad
|
|
|
110
110
|
* Returns the accounts in a lookup table
|
|
111
111
|
* @param rpc
|
|
112
112
|
* @param lookupTable - lookup table to get the accounts from
|
|
113
|
-
* @returns - an array of accounts in the lookup table
|
|
113
|
+
* @returns - an array of accounts in the lookup table or an empty array if the lookup table does not exist
|
|
114
114
|
*/
|
|
115
115
|
export async function getAccountsInLut(rpc: Rpc<GetAccountInfoApi>, lookupTable: Address): Promise<Address[]> {
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
try {
|
|
117
|
+
const lutState = await fetchAddressLookupTable(rpc, lookupTable);
|
|
118
|
+
return lutState.data.addresses;
|
|
119
|
+
} catch (error) {
|
|
120
|
+
console.error(`Error fetching accounts in lookup table ${lookupTable.toString()}`, error);
|
|
121
|
+
return [];
|
|
122
|
+
}
|
|
118
123
|
}
|
|
119
124
|
/**
|
|
120
125
|
* This method inserts the missing keys from the provided keys into an existent lookup table
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Decimal from 'decimal.js';
|
|
2
2
|
import { Address } from '@solana/kit';
|
|
3
|
+
import { lamportsToCollDecimal } from '@kamino-finance/farms-sdk';
|
|
3
4
|
|
|
4
5
|
export interface ReserveAllocationOverview {
|
|
5
6
|
targetWeight: Decimal;
|
|
@@ -13,21 +14,22 @@ export interface VaultAllocationResult {
|
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
const ZERO = new Decimal(0);
|
|
16
|
-
const ONE = new Decimal(1);
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Computes the allocation of vault funds across reserves based on weights and caps
|
|
20
|
-
* @param vaultAUM - Total AUM of the vault
|
|
20
|
+
* @param vaultAUM - Total AUM of the vault, in tokens
|
|
21
21
|
* @param vaultUnallocatedWeight - Weight for unallocated funds
|
|
22
22
|
* @param vaultUnallocatedCap - Maximum amount that can remain unallocated
|
|
23
23
|
* @param initialVaultAllocations - Map of reserve addresses to their allocation configurations
|
|
24
|
-
* @
|
|
24
|
+
* @param vaultTokenDecimals - The number of decimals of the vault token, needed to compute the min amount
|
|
25
|
+
* @returns Object containing target unallocated amount and target allocations per reserve, in tokens
|
|
25
26
|
*/
|
|
26
27
|
export function computeReservesAllocation(
|
|
27
28
|
vaultAUM: Decimal,
|
|
28
29
|
vaultUnallocatedWeight: Decimal,
|
|
29
30
|
vaultUnallocatedCap: Decimal,
|
|
30
|
-
initialVaultAllocations: Map<Address, ReserveAllocationOverview
|
|
31
|
+
initialVaultAllocations: Map<Address, ReserveAllocationOverview>,
|
|
32
|
+
vaultTokenDecimals: number
|
|
31
33
|
): VaultAllocationResult {
|
|
32
34
|
let totalAllocation = new Decimal(0);
|
|
33
35
|
const allReserves = Array.from(initialVaultAllocations.keys());
|
|
@@ -51,8 +53,10 @@ export function computeReservesAllocation(
|
|
|
51
53
|
|
|
52
54
|
let currentAllocationSum = totalAllocation;
|
|
53
55
|
|
|
56
|
+
const reservesCount = allReserves.length;
|
|
57
|
+
const maxRemainedUninvestedLamports = lamportsToCollDecimal(new Decimal(reservesCount), vaultTokenDecimals); // invest only if the AUM has more lamports than the number of reserves
|
|
54
58
|
// Iteratively allocate funds to reserves based on weights and caps
|
|
55
|
-
while (totalLeftToInvest.gt(
|
|
59
|
+
while (totalLeftToInvest.gt(maxRemainedUninvestedLamports) && currentAllocationSum.gt(ZERO)) {
|
|
56
60
|
const totalLeftover = totalLeftToInvest;
|
|
57
61
|
|
|
58
62
|
for (const reserve of allReserves) {
|