@kamino-finance/klend-sdk 5.14.4 → 5.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/dist/classes/farm_utils.d.ts.map +1 -1
  2. package/dist/classes/farm_utils.js +1 -0
  3. package/dist/classes/farm_utils.js.map +1 -1
  4. package/dist/classes/manager.d.ts.map +1 -1
  5. package/dist/classes/manager.js +3 -1
  6. package/dist/classes/manager.js.map +1 -1
  7. package/dist/classes/market.d.ts.map +1 -1
  8. package/dist/classes/market.js.map +1 -1
  9. package/dist/classes/reserve.d.ts +1 -1
  10. package/dist/classes/reserve.d.ts.map +1 -1
  11. package/dist/classes/reserve.js +11 -8
  12. package/dist/classes/reserve.js.map +1 -1
  13. package/dist/classes/vault.d.ts +1 -1
  14. package/dist/classes/vault.d.ts.map +1 -1
  15. package/dist/classes/vault.js +89 -15
  16. package/dist/classes/vault.js.map +1 -1
  17. package/dist/client_kamino_manager.d.ts.map +1 -1
  18. package/dist/client_kamino_manager.js +20 -10
  19. package/dist/client_kamino_manager.js.map +1 -1
  20. package/dist/idl.json +193 -16
  21. package/dist/idl_codegen/accounts/GlobalConfig.d.ts +40 -0
  22. package/dist/idl_codegen/accounts/GlobalConfig.d.ts.map +1 -0
  23. package/dist/idl_codegen/accounts/GlobalConfig.js +116 -0
  24. package/dist/idl_codegen/accounts/GlobalConfig.js.map +1 -0
  25. package/dist/idl_codegen/accounts/LendingMarket.d.ts +24 -3
  26. package/dist/idl_codegen/accounts/LendingMarket.d.ts.map +1 -1
  27. package/dist/idl_codegen/accounts/LendingMarket.js +25 -7
  28. package/dist/idl_codegen/accounts/LendingMarket.js.map +1 -1
  29. package/dist/idl_codegen/accounts/index.d.ts +2 -0
  30. package/dist/idl_codegen/accounts/index.d.ts.map +1 -1
  31. package/dist/idl_codegen/accounts/index.js +3 -1
  32. package/dist/idl_codegen/accounts/index.js.map +1 -1
  33. package/dist/idl_codegen/errors/custom.d.ts +35 -11
  34. package/dist/idl_codegen/errors/custom.d.ts.map +1 -1
  35. package/dist/idl_codegen/errors/custom.js +64 -22
  36. package/dist/idl_codegen/errors/custom.js.map +1 -1
  37. package/dist/idl_codegen/instructions/idlMissingTypes.d.ts +2 -1
  38. package/dist/idl_codegen/instructions/idlMissingTypes.d.ts.map +1 -1
  39. package/dist/idl_codegen/instructions/idlMissingTypes.js +2 -1
  40. package/dist/idl_codegen/instructions/idlMissingTypes.js.map +1 -1
  41. package/dist/idl_codegen/instructions/index.d.ts +6 -0
  42. package/dist/idl_codegen/instructions/index.d.ts.map +1 -1
  43. package/dist/idl_codegen/instructions/index.js +7 -1
  44. package/dist/idl_codegen/instructions/index.js.map +1 -1
  45. package/dist/idl_codegen/instructions/initGlobalConfig.d.ts +10 -0
  46. package/dist/idl_codegen/instructions/initGlobalConfig.d.ts.map +1 -0
  47. package/dist/idl_codegen/instructions/initGlobalConfig.js +19 -0
  48. package/dist/idl_codegen/instructions/initGlobalConfig.js.map +1 -0
  49. package/dist/idl_codegen/instructions/updateGlobalConfig.d.ts +13 -0
  50. package/dist/idl_codegen/instructions/updateGlobalConfig.d.ts.map +1 -0
  51. package/dist/idl_codegen/instructions/updateGlobalConfig.js +61 -0
  52. package/dist/idl_codegen/instructions/updateGlobalConfig.js.map +1 -0
  53. package/dist/idl_codegen/instructions/updateGlobalConfigAdmin.d.ts +7 -0
  54. package/dist/idl_codegen/instructions/updateGlobalConfigAdmin.d.ts.map +1 -0
  55. package/dist/idl_codegen/instructions/updateGlobalConfigAdmin.js +16 -0
  56. package/dist/idl_codegen/instructions/updateGlobalConfigAdmin.js.map +1 -0
  57. package/dist/idl_codegen/instructions/updateReserveConfig.d.ts +5 -4
  58. package/dist/idl_codegen/instructions/updateReserveConfig.d.ts.map +1 -1
  59. package/dist/idl_codegen/instructions/updateReserveConfig.js +7 -5
  60. package/dist/idl_codegen/instructions/updateReserveConfig.js.map +1 -1
  61. package/dist/idl_codegen/instructions/withdrawProtocolFee.d.ts +2 -2
  62. package/dist/idl_codegen/instructions/withdrawProtocolFee.d.ts.map +1 -1
  63. package/dist/idl_codegen/instructions/withdrawProtocolFee.js +2 -6
  64. package/dist/idl_codegen/instructions/withdrawProtocolFee.js.map +1 -1
  65. package/dist/idl_codegen/types/UpdateGlobalConfigMode.d.ts +32 -0
  66. package/dist/idl_codegen/types/UpdateGlobalConfigMode.d.ts.map +1 -0
  67. package/dist/idl_codegen/types/UpdateGlobalConfigMode.js +108 -0
  68. package/dist/idl_codegen/types/UpdateGlobalConfigMode.js.map +1 -0
  69. package/dist/idl_codegen/types/UpdateLendingMarketMode.d.ts +33 -7
  70. package/dist/idl_codegen/types/UpdateLendingMarketMode.d.ts.map +1 -1
  71. package/dist/idl_codegen/types/UpdateLendingMarketMode.js +60 -12
  72. package/dist/idl_codegen/types/UpdateLendingMarketMode.js.map +1 -1
  73. package/dist/idl_codegen/types/index.d.ts +6 -2
  74. package/dist/idl_codegen/types/index.d.ts.map +1 -1
  75. package/dist/idl_codegen/types/index.js +3 -1
  76. package/dist/idl_codegen/types/index.js.map +1 -1
  77. package/dist/utils/api.d.ts +7 -1
  78. package/dist/utils/api.d.ts.map +1 -1
  79. package/dist/utils/api.js +3 -2
  80. package/dist/utils/api.js.map +1 -1
  81. package/dist/utils/constants.d.ts +1 -1
  82. package/dist/utils/constants.d.ts.map +1 -1
  83. package/dist/utils/constants.js +3 -3
  84. package/dist/utils/constants.js.map +1 -1
  85. package/dist/utils/instruction.d.ts.map +1 -1
  86. package/dist/utils/instruction.js.map +1 -1
  87. package/dist/utils/lookupTable.d.ts.map +1 -1
  88. package/dist/utils/lookupTable.js +1 -6
  89. package/dist/utils/lookupTable.js.map +1 -1
  90. package/dist/utils/managerTypes.js +1 -1
  91. package/dist/utils/managerTypes.js.map +1 -1
  92. package/dist/utils/seeds.d.ts +16 -0
  93. package/dist/utils/seeds.d.ts.map +1 -1
  94. package/dist/utils/seeds.js +23 -1
  95. package/dist/utils/seeds.js.map +1 -1
  96. package/package.json +1 -1
  97. package/src/classes/farm_utils.ts +1 -0
  98. package/src/classes/manager.ts +3 -1
  99. package/src/classes/market.ts +2 -6
  100. package/src/classes/reserve.ts +12 -8
  101. package/src/classes/vault.ts +118 -14
  102. package/src/classes/vault_types.ts +1 -1
  103. package/src/client_kamino_manager.ts +35 -13
  104. package/src/idl.json +193 -16
  105. package/src/idl_codegen/accounts/GlobalConfig.ts +125 -0
  106. package/src/idl_codegen/accounts/LendingMarket.ts +41 -9
  107. package/src/idl_codegen/accounts/index.ts +2 -0
  108. package/src/idl_codegen/errors/custom.ts +65 -20
  109. package/src/idl_codegen/instructions/idlMissingTypes.ts +4 -2
  110. package/src/idl_codegen/instructions/index.ts +9 -0
  111. package/src/idl_codegen/instructions/initGlobalConfig.ts +30 -0
  112. package/src/idl_codegen/instructions/updateGlobalConfig.ts +47 -0
  113. package/src/idl_codegen/instructions/updateGlobalConfigAdmin.ts +24 -0
  114. package/src/idl_codegen/instructions/updateReserveConfig.ts +10 -8
  115. package/src/idl_codegen/instructions/withdrawProtocolFee.ts +4 -8
  116. package/src/idl_codegen/types/UpdateGlobalConfigMode.ts +90 -0
  117. package/src/idl_codegen/types/UpdateLendingMarketMode.ts +73 -13
  118. package/src/idl_codegen/types/index.ts +16 -2
  119. package/src/utils/api.ts +9 -3
  120. package/src/utils/constants.ts +3 -3
  121. package/src/utils/instruction.ts +2 -2
  122. package/src/utils/lookupTable.ts +1 -7
  123. package/src/utils/managerTypes.ts +1 -1
  124. package/src/utils/seeds.ts +25 -0
@@ -524,13 +524,9 @@ export class KaminoMarket {
524
524
  getRewardPrice
525
525
  );
526
526
  }
527
-
527
+
528
528
  if (isNotNullPubkey(debtFarmAddress)) {
529
- result.borrowingRewards = await this.getRewardInfoForFarm(
530
- debtFarmAddress,
531
- totalBorrowAmount,
532
- getRewardPrice
533
- );
529
+ result.borrowingRewards = await this.getRewardInfoForFarm(debtFarmAddress, totalBorrowAmount, getRewardPrice);
534
530
  }
535
531
 
536
532
  return result;
@@ -9,6 +9,7 @@ import {
9
9
  } from '@solana/web3.js';
10
10
  import Decimal from 'decimal.js';
11
11
  import {
12
+ globalConfigPda,
12
13
  INITIAL_COLLATERAL_RATE,
13
14
  lendingMarketAuthPda,
14
15
  MarketWithAddress,
@@ -39,7 +40,6 @@ import {
39
40
  import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
40
41
  import { aprToApy, KaminoPrices } from '@kamino-finance/kliquidity-sdk';
41
42
  import { FarmState, RewardInfo } from '@kamino-finance/farms-sdk';
42
- import BN from 'bn.js';
43
43
 
44
44
  export const DEFAULT_RECENT_SLOT_DURATION_MS = 450;
45
45
 
@@ -1180,18 +1180,20 @@ export function updateReserveConfigIx(
1180
1180
  mode: UpdateConfigModeKind,
1181
1181
  value: Uint8Array,
1182
1182
  programId: PublicKey,
1183
- skipValidation: boolean = false
1183
+ skipConfigIntegrityValidation: boolean = false
1184
1184
  ): TransactionInstruction {
1185
1185
  const args: UpdateReserveConfigArgs = {
1186
- mode: new BN(mode.discriminator + 1),
1186
+ mode,
1187
1187
  value,
1188
- skipValidation,
1188
+ skipConfigIntegrityValidation,
1189
1189
  };
1190
1190
 
1191
+ const [globalConfig] = globalConfigPda(programId);
1191
1192
  const accounts: UpdateReserveConfigAccounts = {
1192
- lendingMarketOwner: signer,
1193
+ signer,
1193
1194
  lendingMarket: marketAddress,
1194
1195
  reserve: reserveAddress,
1196
+ globalConfig,
1195
1197
  };
1196
1198
 
1197
1199
  return updateReserveConfig(args, accounts, programId);
@@ -1265,15 +1267,17 @@ export function updateEntireReserveConfigIx(
1265
1267
  programId: PublicKey
1266
1268
  ): TransactionInstruction {
1267
1269
  const args: UpdateReserveConfigArgs = {
1268
- mode: new BN(UpdateConfigMode.UpdateEntireReserveConfig.discriminator + 1),
1270
+ mode: new UpdateConfigMode.UpdateEntireReserveConfig(),
1269
1271
  value: encodeUsingLayout(ReserveConfig.layout(), reserveConfig),
1270
- skipValidation: false,
1272
+ skipConfigIntegrityValidation: false,
1271
1273
  };
1272
1274
 
1275
+ const [globalConfig] = globalConfigPda(programId);
1273
1276
  const accounts: UpdateReserveConfigAccounts = {
1274
- lendingMarketOwner: signer,
1277
+ signer,
1275
1278
  lendingMarket: marketAddress,
1276
1279
  reserve: reserveAddress,
1280
+ globalConfig,
1277
1281
  };
1278
1282
 
1279
1283
  const ix = updateReserveConfig(args, accounts, programId);
@@ -1059,13 +1059,14 @@ export class KaminoVaultClient {
1059
1059
  async withdrawIxs(
1060
1060
  user: PublicKey,
1061
1061
  vault: KaminoVault,
1062
- shareAmount: Decimal,
1062
+ shareAmountToWithdraw: Decimal,
1063
1063
  slot: number,
1064
1064
  vaultReservesMap?: PubkeyHashMap<PublicKey, KaminoReserve>,
1065
1065
  farmState?: FarmState
1066
1066
  ): Promise<WithdrawIxs> {
1067
1067
  const vaultState = await vault.getState(this.getConnection());
1068
1068
  const kaminoVault = new KaminoVault(vault.address, vaultState, vault.programId);
1069
+ const hasFarm = await vault.hasFarm(this.getConnection());
1069
1070
 
1070
1071
  const withdrawIxs: WithdrawIxs = {
1071
1072
  unstakeFromFarmIfNeededIxs: [],
@@ -1073,9 +1074,56 @@ export class KaminoVaultClient {
1073
1074
  postWithdrawIxs: [],
1074
1075
  };
1075
1076
 
1076
- const shareLamportsToWithdraw = collToLamportsDecimal(shareAmount, vaultState.sharesMintDecimals.toNumber());
1077
- const hasFarm = await vault.hasFarm(this.getConnection());
1077
+ // compute the total shares the user has (in ATA + in farm) and check if they want to withdraw everything or just a part
1078
+ let userSharesAtaBalance = new Decimal(0);
1079
+ const userSharesAta = getAssociatedTokenAddress(vaultState.sharesMint, user);
1080
+ const userSharesAtaState = await this.getConnection().getAccountInfo(userSharesAta);
1081
+ if (userSharesAtaState) {
1082
+ const userSharesAtaBalanceInLamports = getTokenBalanceFromAccountInfoLamports(userSharesAtaState);
1083
+ userSharesAtaBalance = userSharesAtaBalanceInLamports.div(
1084
+ new Decimal(10).pow(vaultState.sharesMintDecimals.toString())
1085
+ );
1086
+ }
1087
+
1088
+ let userSharesInFarm = new Decimal(0);
1078
1089
  if (hasFarm) {
1090
+ userSharesInFarm = await getUserSharesInFarm(
1091
+ this.getConnection(),
1092
+ user,
1093
+ vaultState.vaultFarm,
1094
+ vaultState.sharesMintDecimals.toNumber()
1095
+ );
1096
+ }
1097
+
1098
+ let sharesToWithdraw = shareAmountToWithdraw;
1099
+ const totalUserShares = userSharesAtaBalance.add(userSharesInFarm);
1100
+ let withdrawAllShares = false;
1101
+ if (sharesToWithdraw.gt(totalUserShares)) {
1102
+ sharesToWithdraw = new Decimal(U64_MAX.toString()).div(
1103
+ new Decimal(10).pow(vaultState.sharesMintDecimals.toString())
1104
+ );
1105
+ withdrawAllShares = true;
1106
+ }
1107
+
1108
+ // if not enough shares in ATA unstake from farm
1109
+ const sharesInAtaAreEnoughForWithdraw = sharesToWithdraw.lte(userSharesAtaBalance);
1110
+ if (hasFarm && !sharesInAtaAreEnoughForWithdraw) {
1111
+ // if we need to unstake we need to make sure share ata is created
1112
+ const [{ createAtaIx }] = createAtasIdempotent(user, [
1113
+ {
1114
+ mint: vaultState.sharesMint,
1115
+ tokenProgram: TOKEN_PROGRAM_ID,
1116
+ },
1117
+ ]);
1118
+ withdrawIxs.unstakeFromFarmIfNeededIxs.push(createAtaIx);
1119
+ let shareLamportsToWithdraw = new Decimal(U64_MAX.toString());
1120
+ if (!withdrawAllShares) {
1121
+ const sharesToWithdrawFromFarm = sharesToWithdraw.sub(userSharesAtaBalance);
1122
+ shareLamportsToWithdraw = collToLamportsDecimal(
1123
+ sharesToWithdrawFromFarm,
1124
+ vaultState.sharesMintDecimals.toNumber()
1125
+ );
1126
+ }
1079
1127
  const unstakeAndWithdrawFromFarmIxs = await getFarmUnstakeAndWithdrawIxs(
1080
1128
  this.getConnection(),
1081
1129
  user,
@@ -1096,13 +1144,14 @@ export class KaminoVaultClient {
1096
1144
  const withdrawFromVaultIxs = await this.withdrawWithReserveIxs(
1097
1145
  user,
1098
1146
  kaminoVault,
1099
- shareAmount,
1147
+ sharesToWithdraw,
1148
+ totalUserShares,
1100
1149
  slot,
1101
1150
  vaultReservesMap
1102
1151
  );
1103
1152
  withdrawIxs.withdrawIxs = withdrawFromVaultIxs;
1104
1153
  } else {
1105
- const withdrawFromVaultIxs = await this.withdrawFromAvailableIxs(user, kaminoVault, shareAmount);
1154
+ const withdrawFromVaultIxs = await this.withdrawFromAvailableIxs(user, kaminoVault, sharesToWithdraw);
1106
1155
  withdrawIxs.withdrawIxs = withdrawFromVaultIxs;
1107
1156
  }
1108
1157
 
@@ -1113,6 +1162,13 @@ export class KaminoVaultClient {
1113
1162
  withdrawIxs.postWithdrawIxs.push(unwrapIx);
1114
1163
  }
1115
1164
 
1165
+ // if we burn all of user's shares close its shares ATA
1166
+ const burnAllUserShares = sharesToWithdraw.gt(userSharesAtaBalance);
1167
+ if (burnAllUserShares) {
1168
+ const closeAtaIx = createCloseAccountInstruction(userSharesAta, user, user, [], TOKEN_PROGRAM_ID);
1169
+ withdrawIxs.postWithdrawIxs.push(closeAtaIx);
1170
+ }
1171
+
1116
1172
  return withdrawIxs;
1117
1173
  }
1118
1174
 
@@ -1149,6 +1205,7 @@ export class KaminoVaultClient {
1149
1205
  user: PublicKey,
1150
1206
  vault: KaminoVault,
1151
1207
  shareAmount: Decimal,
1208
+ allUserShares: Decimal,
1152
1209
  slot: number,
1153
1210
  vaultReservesMap?: PubkeyHashMap<PublicKey, KaminoReserve>
1154
1211
  ): Promise<TransactionInstruction[]> {
@@ -1163,7 +1220,12 @@ export class KaminoVaultClient {
1163
1220
  },
1164
1221
  ]);
1165
1222
 
1166
- const shareLamportsToWithdraw = collToLamportsDecimal(shareAmount, vaultState.sharesMintDecimals.toNumber());
1223
+ const withdrawAllShares = shareAmount.gte(allUserShares);
1224
+ const actualSharesToWithdraw = shareAmount.lte(allUserShares) ? shareAmount : allUserShares;
1225
+ const shareLamportsToWithdraw = collToLamportsDecimal(
1226
+ actualSharesToWithdraw,
1227
+ vaultState.sharesMintDecimals.toNumber()
1228
+ );
1167
1229
  const tokensPerShare = await this.getTokensPerShareSingleVault(vault, slot);
1168
1230
  const sharesPerToken = new Decimal(1).div(tokensPerShare);
1169
1231
  const tokensToWithdraw = shareLamportsToWithdraw.mul(tokensPerShare);
@@ -1181,10 +1243,17 @@ export class KaminoVaultClient {
1181
1243
  const firstReserve = vaultState.vaultAllocationStrategy.find(
1182
1244
  (reserve) => !reserve.reserve.equals(PublicKey.default)
1183
1245
  );
1184
- reserveWithSharesAmountToWithdraw.push({
1185
- reserve: firstReserve!.reserve,
1186
- shares: shareLamportsToWithdraw,
1187
- });
1246
+ if (withdrawAllShares) {
1247
+ reserveWithSharesAmountToWithdraw.push({
1248
+ reserve: firstReserve!.reserve,
1249
+ shares: new Decimal(U64_MAX.toString()),
1250
+ });
1251
+ } else {
1252
+ reserveWithSharesAmountToWithdraw.push({
1253
+ reserve: firstReserve!.reserve,
1254
+ shares: shareLamportsToWithdraw,
1255
+ });
1256
+ }
1188
1257
  } else {
1189
1258
  // Get decreasing order sorted available liquidity to withdraw from each reserve allocated to
1190
1259
  const reserveAllocationAvailableLiquidityToWithdraw = await this.getReserveAllocationAvailableLiquidityToWithdraw(
@@ -1204,9 +1273,13 @@ export class KaminoVaultClient {
1204
1273
  tokensToWithdrawFromReserve = tokensToWithdrawFromReserve.add(availableTokens);
1205
1274
  isFirstWithdraw = false;
1206
1275
  }
1207
- // round up to the nearest integer the shares to withdraw
1208
- const sharesToWithdrawFromReserve = tokensToWithdrawFromReserve.mul(sharesPerToken).ceil();
1209
- reserveWithSharesAmountToWithdraw.push({ reserve: key, shares: sharesToWithdrawFromReserve });
1276
+ if (withdrawAllShares) {
1277
+ reserveWithSharesAmountToWithdraw.push({ reserve: key, shares: new Decimal(U64_MAX.toString()) });
1278
+ } else {
1279
+ // round up to the nearest integer the shares to withdraw
1280
+ const sharesToWithdrawFromReserve = tokensToWithdrawFromReserve.mul(sharesPerToken).ceil();
1281
+ reserveWithSharesAmountToWithdraw.push({ reserve: key, shares: sharesToWithdrawFromReserve });
1282
+ }
1210
1283
 
1211
1284
  tokenLeftToWithdraw = tokenLeftToWithdraw.sub(tokensToWithdrawFromReserve);
1212
1285
  }
@@ -2307,7 +2380,38 @@ export class KaminoVaultClient {
2307
2380
  kaminoMarkets?: KaminoMarket[]
2308
2381
  ): Promise<PubkeyHashMap<PublicKey, MarketOverview>> {
2309
2382
  const vaultReservesStateMap = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vaultState);
2310
- const vaultReservesState = Array.from(vaultReservesStateMap.values());
2383
+ const vaultReservesState: KaminoReserve[] = [];
2384
+
2385
+ const missingReserves = new PublicKeySet<PublicKey>([]);
2386
+ // filter the reserves that are not part of the vault allocation strategy
2387
+ vaultState.vaultAllocationStrategy.forEach(async (allocation) => {
2388
+ if (allocation.reserve.equals(PublicKey.default)) {
2389
+ return;
2390
+ }
2391
+ const reserve = vaultReservesStateMap.get(allocation.reserve);
2392
+ if (!reserve) {
2393
+ missingReserves.add(allocation.reserve);
2394
+ return;
2395
+ }
2396
+
2397
+ vaultReservesState.push(reserve);
2398
+ });
2399
+
2400
+ // read missing reserves
2401
+ const missingReservesStates = (await Reserve.fetchMultiple(this.getConnection(), missingReserves.toArray())).filter(
2402
+ (reserve) => reserve !== null
2403
+ );
2404
+ const missingReservesAndOracles = await getTokenOracleData(this.getConnection(), missingReservesStates);
2405
+ missingReservesAndOracles.forEach(([reserve, oracle], index) => {
2406
+ const fetchedReserve = new KaminoReserve(
2407
+ reserve,
2408
+ missingReserves.toArray()[index]!,
2409
+ oracle!,
2410
+ this.getConnection(),
2411
+ this.recentSlotDurationMs
2412
+ );
2413
+ vaultReservesState.push(fetchedReserve);
2414
+ });
2311
2415
 
2312
2416
  const vaultCollateralsPerReserve: PubkeyHashMap<PublicKey, MarketOverview> = new PubkeyHashMap();
2313
2417
 
@@ -48,7 +48,7 @@ export type DepositIxs = {
48
48
  export type WithdrawIxs = {
49
49
  unstakeFromFarmIfNeededIxs: TransactionInstruction[];
50
50
  withdrawIxs: TransactionInstruction[];
51
- postWithdrawIxs: TransactionInstruction[]; // wSOL ATA close ix
51
+ postWithdrawIxs: TransactionInstruction[]; // if needed: wSOL ATA close ix + share ATA close ix
52
52
  };
53
53
 
54
54
  /** The shares an user has in a vault (staked and unstaked), in tokens */
@@ -8,15 +8,20 @@ import {
8
8
  Signer,
9
9
  Transaction,
10
10
  TransactionInstruction,
11
+ TransactionMessage,
11
12
  TransactionSignature,
12
13
  VersionedTransaction,
13
14
  } from '@solana/web3.js';
14
15
  import {
15
16
  AssetReserveConfigCli,
16
17
  Chain,
18
+ createLookupTableIx,
17
19
  DEFAULT_RECENT_SLOT_DURATION_MS,
18
20
  encodeTokenName,
21
+ extendLookupTableIxs,
22
+ getLookupTableAccounts,
19
23
  getMedianSlotDurationInMsFromLastEpochs,
24
+ globalConfigPda,
20
25
  initLookupTableIx,
21
26
  KaminoManager,
22
27
  KaminoMarket,
@@ -27,6 +32,7 @@ import {
27
32
  MAINNET_BETA_CHAIN_ID,
28
33
  parseZeroPaddedUtf8,
29
34
  printHoldings,
35
+ PROGRAM_ID,
30
36
  Reserve,
31
37
  ReserveAllocationConfig,
32
38
  ReserveWithAddress,
@@ -153,7 +159,10 @@ async function main() {
153
159
 
154
160
  const _createReserveSig = await processTxn(env.client, env.payer, txnIxs[0], mode, 2500, [reserve]);
155
161
 
156
- const _updateReserveSig = await processTxn(env.client, env.payer, txnIxs[1], mode, 2500, [], 400_000);
162
+ const [lut, createLutIxs] = await createUpdateReserveConfigLutIxs(env, marketAddress, reserve.publicKey);
163
+ await processTxn(env.client, env.payer, createLutIxs, mode, 2500, []);
164
+
165
+ const _updateSig = await processTxn(env.client, env.payer, txnIxs[1], mode, 2500, [], 400_000, 1000, [lut]);
157
166
 
158
167
  mode === 'execute' &&
159
168
  console.log(
@@ -1612,7 +1621,8 @@ async function processTxn(
1612
1621
  priorityFeeMultiplier: number = 2500,
1613
1622
  extraSigners: Signer[],
1614
1623
  computeUnits: number = 200_000,
1615
- priorityFeeLamports: number = 1000
1624
+ priorityFeeLamports: number = 1000,
1625
+ luts: PublicKey[] = []
1616
1626
  ): Promise<TransactionSignature> {
1617
1627
  if (mode !== 'inspect' && mode !== 'simulate' && mode !== 'execute' && mode !== 'multisig') {
1618
1628
  throw new Error('Invalid mode: ' + mode + '. Must be one of: inspect/simulate/execute/multisig');
@@ -1632,25 +1642,27 @@ async function processTxn(
1632
1642
  } else {
1633
1643
  const microLamport = priorityFeeLamports * 10 ** 6; // 1000 lamports
1634
1644
  const microLamportsPrioritizationFee = microLamport / computeUnits;
1635
-
1636
- const tx = new Transaction();
1637
1645
  const { blockhash } = await web3Client.connection.getLatestBlockhash();
1646
+
1638
1647
  if (priorityFeeMultiplier) {
1639
1648
  const priorityFeeIxn = createAddExtraComputeUnitFeeTransaction(
1640
1649
  computeUnits,
1641
1650
  microLamportsPrioritizationFee * priorityFeeMultiplier
1642
1651
  );
1643
- tx.add(...priorityFeeIxn);
1652
+ ixs.push(...priorityFeeIxn);
1644
1653
  }
1645
- tx.recentBlockhash = blockhash;
1646
- tx.feePayer = admin.publicKey;
1647
- tx.add(...ixs);
1654
+
1655
+ const tx = new TransactionMessage({
1656
+ payerKey: admin.publicKey,
1657
+ recentBlockhash: blockhash,
1658
+ instructions: ixs,
1659
+ }).compileToV0Message(await getLookupTableAccounts(web3Client.connection, luts));
1648
1660
 
1649
1661
  if (mode === 'execute') {
1650
1662
  return await signSendAndConfirmRawTransactionWithRetry({
1651
1663
  mainConnection: web3Client.sendConnection,
1652
1664
  extraConnections: [],
1653
- tx: new VersionedTransaction(tx.compileMessage()),
1665
+ tx: new VersionedTransaction(tx),
1654
1666
  signers: [admin, ...extraSigners],
1655
1667
  commitment: 'confirmed',
1656
1668
  sendTransactionOptions: {
@@ -1659,9 +1671,7 @@ async function processTxn(
1659
1671
  },
1660
1672
  });
1661
1673
  } else if (mode === 'simulate') {
1662
- const simulation = await web3Client.sendConnection.simulateTransaction(
1663
- new VersionedTransaction(tx.compileMessage())
1664
- );
1674
+ const simulation = await web3Client.sendConnection.simulateTransaction(new VersionedTransaction(tx));
1665
1675
  if (simulation.value.logs && simulation.value.logs.length > 0) {
1666
1676
  console.log('Simulation: \n' + simulation.value.logs);
1667
1677
  } else {
@@ -1671,7 +1681,7 @@ async function processTxn(
1671
1681
  console.log(
1672
1682
  'Tx in B64',
1673
1683
  `https://explorer.solana.com/tx/inspector?message=${encodeURIComponent(
1674
- tx.serializeMessage().toString('base64')
1684
+ Buffer.from(tx.serialize()).toString('base64')
1675
1685
  )}`
1676
1686
  );
1677
1687
  }
@@ -1869,3 +1879,15 @@ function parseReserveConfigToFile(reserveConfig: ReserveConfig) {
1869
1879
  reserved2: Array(9).fill(0),
1870
1880
  };
1871
1881
  }
1882
+
1883
+ async function createUpdateReserveConfigLutIxs(
1884
+ env: Env,
1885
+ lendingMarketAddress: PublicKey,
1886
+ reserveAddress: PublicKey
1887
+ ): Promise<[PublicKey, TransactionInstruction[]]> {
1888
+ const [globalConfigAddress] = globalConfigPda(PROGRAM_ID);
1889
+ const contents = [globalConfigAddress, lendingMarketAddress, reserveAddress];
1890
+ const [createIx, lut] = await createLookupTableIx(env.connection, env.payer.publicKey);
1891
+ const extendIxs = extendLookupTableIxs(env.payer.publicKey, lut, contents);
1892
+ return [lut, [createIx, ...extendIxs]];
1893
+ }