@kamino-finance/klend-sdk 5.14.0-beta.0 → 5.14.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 (150) hide show
  1. package/dist/classes/farm_utils.d.ts.map +1 -1
  2. package/dist/classes/farm_utils.js +10 -3
  3. package/dist/classes/farm_utils.js.map +1 -1
  4. package/dist/classes/manager.d.ts +21 -6
  5. package/dist/classes/manager.d.ts.map +1 -1
  6. package/dist/classes/manager.js +311 -40
  7. package/dist/classes/manager.js.map +1 -1
  8. package/dist/classes/obligation.d.ts +1 -3
  9. package/dist/classes/obligation.d.ts.map +1 -1
  10. package/dist/classes/obligation.js +2 -18
  11. package/dist/classes/obligation.js.map +1 -1
  12. package/dist/classes/obligationOrder.d.ts +2 -1
  13. package/dist/classes/obligationOrder.d.ts.map +1 -1
  14. package/dist/classes/obligationOrder.js +16 -3
  15. package/dist/classes/obligationOrder.js.map +1 -1
  16. package/dist/classes/reserve.d.ts +14 -5
  17. package/dist/classes/reserve.d.ts.map +1 -1
  18. package/dist/classes/reserve.js +463 -91
  19. package/dist/classes/reserve.js.map +1 -1
  20. package/dist/classes/shared.d.ts +1 -0
  21. package/dist/classes/shared.d.ts.map +1 -1
  22. package/dist/classes/shared.js.map +1 -1
  23. package/dist/classes/utils.d.ts +0 -1
  24. package/dist/classes/utils.d.ts.map +1 -1
  25. package/dist/classes/utils.js +0 -12
  26. package/dist/classes/utils.js.map +1 -1
  27. package/dist/classes/vault.d.ts +11 -1
  28. package/dist/classes/vault.d.ts.map +1 -1
  29. package/dist/classes/vault.js +54 -6
  30. package/dist/classes/vault.js.map +1 -1
  31. package/dist/client_kamino_manager.d.ts.map +1 -1
  32. package/dist/client_kamino_manager.js +26 -27
  33. package/dist/client_kamino_manager.js.map +1 -1
  34. package/dist/idl.json +9 -186
  35. package/dist/idl_codegen/accounts/LendingMarket.d.ts +3 -24
  36. package/dist/idl_codegen/accounts/LendingMarket.d.ts.map +1 -1
  37. package/dist/idl_codegen/accounts/LendingMarket.js +7 -25
  38. package/dist/idl_codegen/accounts/LendingMarket.js.map +1 -1
  39. package/dist/idl_codegen/accounts/index.d.ts +0 -2
  40. package/dist/idl_codegen/accounts/index.d.ts.map +1 -1
  41. package/dist/idl_codegen/accounts/index.js +1 -3
  42. package/dist/idl_codegen/accounts/index.js.map +1 -1
  43. package/dist/idl_codegen/errors/custom.d.ts +1 -25
  44. package/dist/idl_codegen/errors/custom.d.ts.map +1 -1
  45. package/dist/idl_codegen/errors/custom.js +1 -43
  46. package/dist/idl_codegen/errors/custom.js.map +1 -1
  47. package/dist/idl_codegen/instructions/idlMissingTypes.d.ts +1 -2
  48. package/dist/idl_codegen/instructions/idlMissingTypes.d.ts.map +1 -1
  49. package/dist/idl_codegen/instructions/idlMissingTypes.js +1 -2
  50. package/dist/idl_codegen/instructions/idlMissingTypes.js.map +1 -1
  51. package/dist/idl_codegen/instructions/index.d.ts +0 -6
  52. package/dist/idl_codegen/instructions/index.d.ts.map +1 -1
  53. package/dist/idl_codegen/instructions/index.js +1 -7
  54. package/dist/idl_codegen/instructions/index.js.map +1 -1
  55. package/dist/idl_codegen/instructions/updateReserveConfig.d.ts +3 -4
  56. package/dist/idl_codegen/instructions/updateReserveConfig.d.ts.map +1 -1
  57. package/dist/idl_codegen/instructions/updateReserveConfig.js +3 -5
  58. package/dist/idl_codegen/instructions/updateReserveConfig.js.map +1 -1
  59. package/dist/idl_codegen/instructions/withdrawProtocolFee.d.ts +2 -2
  60. package/dist/idl_codegen/instructions/withdrawProtocolFee.d.ts.map +1 -1
  61. package/dist/idl_codegen/instructions/withdrawProtocolFee.js +6 -2
  62. package/dist/idl_codegen/instructions/withdrawProtocolFee.js.map +1 -1
  63. package/dist/idl_codegen/types/UpdateLendingMarketMode.d.ts +7 -33
  64. package/dist/idl_codegen/types/UpdateLendingMarketMode.d.ts.map +1 -1
  65. package/dist/idl_codegen/types/UpdateLendingMarketMode.js +12 -60
  66. package/dist/idl_codegen/types/UpdateLendingMarketMode.js.map +1 -1
  67. package/dist/idl_codegen/types/index.d.ts +2 -6
  68. package/dist/idl_codegen/types/index.d.ts.map +1 -1
  69. package/dist/idl_codegen/types/index.js +1 -3
  70. package/dist/idl_codegen/types/index.js.map +1 -1
  71. package/dist/lending_operations/repay_with_collateral_calcs.d.ts.map +1 -1
  72. package/dist/lending_operations/repay_with_collateral_calcs.js +2 -2
  73. package/dist/lending_operations/repay_with_collateral_calcs.js.map +1 -1
  74. package/dist/utils/accountListing.d.ts +1 -1
  75. package/dist/utils/accountListing.d.ts.map +1 -1
  76. package/dist/utils/accountListing.js +2 -2
  77. package/dist/utils/accountListing.js.map +1 -1
  78. package/dist/utils/api.d.ts +5 -1
  79. package/dist/utils/api.d.ts.map +1 -1
  80. package/dist/utils/api.js +15 -6
  81. package/dist/utils/api.js.map +1 -1
  82. package/dist/utils/constants.d.ts +1 -1
  83. package/dist/utils/constants.js +1 -1
  84. package/dist/utils/lookupTable.d.ts.map +1 -1
  85. package/dist/utils/lookupTable.js +6 -1
  86. package/dist/utils/lookupTable.js.map +1 -1
  87. package/dist/utils/managerTypes.d.ts.map +1 -1
  88. package/dist/utils/managerTypes.js +4 -10
  89. package/dist/utils/managerTypes.js.map +1 -1
  90. package/dist/utils/seeds.d.ts +0 -16
  91. package/dist/utils/seeds.d.ts.map +1 -1
  92. package/dist/utils/seeds.js +1 -23
  93. package/dist/utils/seeds.js.map +1 -1
  94. package/package.json +1 -1
  95. package/src/classes/farm_utils.ts +11 -3
  96. package/src/classes/manager.ts +417 -52
  97. package/src/classes/obligation.ts +9 -20
  98. package/src/classes/obligationOrder.ts +22 -3
  99. package/src/classes/reserve.ts +783 -119
  100. package/src/classes/shared.ts +1 -0
  101. package/src/classes/utils.ts +0 -12
  102. package/src/classes/vault.ts +75 -7
  103. package/src/client_kamino_manager.ts +34 -42
  104. package/src/idl.json +9 -186
  105. package/src/idl_codegen/accounts/LendingMarket.ts +9 -41
  106. package/src/idl_codegen/accounts/index.ts +0 -2
  107. package/src/idl_codegen/errors/custom.ts +0 -45
  108. package/src/idl_codegen/instructions/idlMissingTypes.ts +2 -4
  109. package/src/idl_codegen/instructions/index.ts +0 -9
  110. package/src/idl_codegen/instructions/updateReserveConfig.ts +5 -7
  111. package/src/idl_codegen/instructions/withdrawProtocolFee.ts +8 -4
  112. package/src/idl_codegen/types/UpdateLendingMarketMode.ts +13 -73
  113. package/src/idl_codegen/types/index.ts +2 -16
  114. package/src/lending_operations/repay_with_collateral_calcs.ts +2 -5
  115. package/src/utils/accountListing.ts +3 -2
  116. package/src/utils/api.ts +20 -6
  117. package/src/utils/constants.ts +1 -1
  118. package/src/utils/lookupTable.ts +7 -1
  119. package/src/utils/managerTypes.ts +4 -10
  120. package/src/utils/seeds.ts +0 -25
  121. package/dist/classes/configItems.d.ts +0 -137
  122. package/dist/classes/configItems.d.ts.map +0 -1
  123. package/dist/classes/configItems.js +0 -143
  124. package/dist/classes/configItems.js.map +0 -1
  125. package/dist/idl_codegen/accounts/GlobalConfig.d.ts +0 -40
  126. package/dist/idl_codegen/accounts/GlobalConfig.d.ts.map +0 -1
  127. package/dist/idl_codegen/accounts/GlobalConfig.js +0 -116
  128. package/dist/idl_codegen/accounts/GlobalConfig.js.map +0 -1
  129. package/dist/idl_codegen/instructions/initGlobalConfig.d.ts +0 -10
  130. package/dist/idl_codegen/instructions/initGlobalConfig.d.ts.map +0 -1
  131. package/dist/idl_codegen/instructions/initGlobalConfig.js +0 -19
  132. package/dist/idl_codegen/instructions/initGlobalConfig.js.map +0 -1
  133. package/dist/idl_codegen/instructions/updateGlobalConfig.d.ts +0 -13
  134. package/dist/idl_codegen/instructions/updateGlobalConfig.d.ts.map +0 -1
  135. package/dist/idl_codegen/instructions/updateGlobalConfig.js +0 -61
  136. package/dist/idl_codegen/instructions/updateGlobalConfig.js.map +0 -1
  137. package/dist/idl_codegen/instructions/updateGlobalConfigAdmin.d.ts +0 -7
  138. package/dist/idl_codegen/instructions/updateGlobalConfigAdmin.d.ts.map +0 -1
  139. package/dist/idl_codegen/instructions/updateGlobalConfigAdmin.js +0 -16
  140. package/dist/idl_codegen/instructions/updateGlobalConfigAdmin.js.map +0 -1
  141. package/dist/idl_codegen/types/UpdateGlobalConfigMode.d.ts +0 -32
  142. package/dist/idl_codegen/types/UpdateGlobalConfigMode.d.ts.map +0 -1
  143. package/dist/idl_codegen/types/UpdateGlobalConfigMode.js +0 -108
  144. package/dist/idl_codegen/types/UpdateGlobalConfigMode.js.map +0 -1
  145. package/src/classes/configItems.ts +0 -229
  146. package/src/idl_codegen/accounts/GlobalConfig.ts +0 -125
  147. package/src/idl_codegen/instructions/initGlobalConfig.ts +0 -30
  148. package/src/idl_codegen/instructions/updateGlobalConfig.ts +0 -47
  149. package/src/idl_codegen/instructions/updateGlobalConfigAdmin.ts +0 -24
  150. package/src/idl_codegen/types/UpdateGlobalConfigMode.ts +0 -90
@@ -28,6 +28,7 @@ import {
28
28
  } from './vault';
29
29
  import {
30
30
  AddAssetToMarketParams,
31
+ assertNever,
31
32
  CreateKaminoMarketParams,
32
33
  createReserveIxs,
33
34
  ENV,
@@ -44,6 +45,7 @@ import {
44
45
  KaminoReserve,
45
46
  LendingMarket,
46
47
  lendingMarketAuthPda,
48
+ LendingMarketFields,
47
49
  MarketWithAddress,
48
50
  parseForChangesReserveConfigAndGetIxs,
49
51
  parseOracleType,
@@ -51,6 +53,7 @@ import {
51
53
  PubkeyHashMap,
52
54
  Reserve,
53
55
  ReserveWithAddress,
56
+ sameLengthArrayEquals,
54
57
  ScopeOracleConfig,
55
58
  updateEntireReserveConfigIx,
56
59
  updateLendingMarket,
@@ -62,7 +65,12 @@ import {
62
65
  import { PROGRAM_ID } from '../idl_codegen/programId';
63
66
  import { Scope, TokenMetadatas, U16_MAX } from '@kamino-finance/scope-sdk';
64
67
  import BN from 'bn.js';
65
- import { ReserveConfig, UpdateLendingMarketMode, UpdateLendingMarketModeKind } from '../idl_codegen/types';
68
+ import {
69
+ ElevationGroup,
70
+ ReserveConfig,
71
+ UpdateLendingMarketMode,
72
+ UpdateLendingMarketModeKind,
73
+ } from '../idl_codegen/types';
66
74
  import Decimal from 'decimal.js';
67
75
  import * as anchor from '@coral-xyz/anchor';
68
76
  import { VaultState } from '../idl_codegen_kamino_vault/accounts';
@@ -88,7 +96,6 @@ import { FarmState } from '@kamino-finance/farms-sdk/dist';
88
96
  import SwitchboardProgram from '@switchboard-xyz/sbv2-lite';
89
97
  import { getSquadsMultisigAdminsAndThreshold, walletIsSquadsMultisig, WalletType } from '../utils/multisig';
90
98
  import { decodeVaultState } from '../utils/vault';
91
- import { ConfigUpdater } from './configItems';
92
99
 
93
100
  /**
94
101
  * KaminoManager is a class that provides a high-level interface to interact with the Kamino Lend and Kamino Vault programs, in order to create and manage a market, as well as vaults
@@ -384,15 +391,7 @@ export class KaminoManager {
384
391
  const ixs: TransactionInstruction[] = [];
385
392
 
386
393
  if (!reserveState || updateEntireConfig) {
387
- ixs.push(
388
- updateEntireReserveConfigIx(
389
- marketWithAddress.state.lendingMarketOwner,
390
- marketWithAddress.address,
391
- reserve,
392
- config,
393
- this._kaminoLendProgramId
394
- )
395
- );
394
+ ixs.push(updateEntireReserveConfigIx(marketWithAddress, reserve, config, this._kaminoLendProgramId));
396
395
  } else {
397
396
  ixs.push(
398
397
  ...parseForChangesReserveConfigAndGetIxs(
@@ -658,9 +657,9 @@ export class KaminoManager {
658
657
  * Get all lending markets
659
658
  * @returns an array of all lending markets
660
659
  */
661
- async getAllMarkets(): Promise<KaminoMarket[]> {
660
+ async getAllMarkets(programId: PublicKey = PROGRAM_ID): Promise<KaminoMarket[]> {
662
661
  // Get all lending markets
663
- const marketGenerator = getAllLendingMarketAccounts(this.getConnection());
662
+ const marketGenerator = getAllLendingMarketAccounts(this.getConnection(), programId);
664
663
  const slotDuration = await getMedianSlotDurationInMsFromLastEpochs();
665
664
 
666
665
  const lendingMarketPairs: [PublicKey, LendingMarket][] = [];
@@ -874,7 +873,7 @@ export class KaminoManager {
874
873
  }
875
874
 
876
875
  /**
877
- * This will return an VaultOverview object that encapsulates all the information about the vault, including the holdings, reserves details, theoretical APY, utilization ratio and total borrowed amount
876
+ * This will return an VaultOverview object that encapsulates all the information about the vault, including the holdings, reserves details, theoretical APY, actual APY, utilization ratio and total borrowed amount
878
877
  * @param vault - the kamino vault to get available liquidity to withdraw for
879
878
  * @param price - the price of the token in the vault (e.g. USDC)
880
879
  * @param [slot] - the slot for which to retrieve the vault overview for. Optional. If not provided the function will fetch the current slot
@@ -949,6 +948,21 @@ export class KaminoManager {
949
948
  return this._vaultClient.getVaultTheoreticalAPY(vault, slot, vaultReserves);
950
949
  }
951
950
 
951
+ /**
952
+ * This will return the APY of the vault based on the current invested amounts; for percentage it needs multiplication by 100
953
+ * @param vault - the kamino vault to get APY for
954
+ * @param slot - current slot
955
+ * @param [vaultReservesMap] - hashmap from each reserve pubkey to the reserve state. Optional. If provided the function will be significantly faster as it will not have to fetch the reserves
956
+ * @returns a struct containing estimated gross APY and net APY (gross - vault fees) for the vault
957
+ */
958
+ async getVaultActualAPY(
959
+ vault: VaultState,
960
+ slot: number,
961
+ vaultReserves?: PubkeyHashMap<PublicKey, KaminoReserve>
962
+ ): Promise<APYs> {
963
+ return this._vaultClient.getVaultActualAPY(vault, slot, vaultReserves);
964
+ }
965
+
952
966
  /**
953
967
  * Retrive the total amount of interest earned by the vault since its inception, up to the last interaction with the vault on chain, including what was charged as fees
954
968
  * @param vaultState the kamino vault state to get total net yield for
@@ -1014,6 +1028,13 @@ export class KaminoManager {
1014
1028
  return this._vaultClient.calculateSimulatedFees(vaultState, simulatedCurrentHoldingsWithInterest, currentTimestamp);
1015
1029
  }
1016
1030
 
1031
+ /**
1032
+ * This will compute the PDA that is used as delegatee in Farms program to compute the user state PDA
1033
+ */
1034
+ computeUserFarmStateForUserInVault(farmProgramID: PublicKey, vault: PublicKey, reserve: PublicKey, user: PublicKey) {
1035
+ return this._vaultClient.computeUserFarmStateDelegateePDAForUserInVault(farmProgramID, reserve, vault, user);
1036
+ }
1037
+
1017
1038
  /**
1018
1039
  * This will load the onchain state for all the reserves that the vault has allocations for
1019
1040
  * @param vaultState - the vault state to load reserves for
@@ -1248,51 +1269,383 @@ export class KaminoManager {
1248
1269
  };
1249
1270
  }
1250
1271
  } // KaminoManager
1272
+ export type BaseLendingMarketKey = keyof LendingMarketFields;
1273
+ const EXCLUDED_LENDING_MARKET_KEYS = [
1274
+ 'version',
1275
+ 'bumpSeed',
1276
+ 'reserved0',
1277
+ 'reserved1',
1278
+ 'padding1',
1279
+ 'padding2',
1280
+ 'elevationGroupPadding',
1281
+ 'quoteCurrency',
1282
+ ] as const;
1283
+ export type ExcludedLendingMarketKey = (typeof EXCLUDED_LENDING_MARKET_KEYS)[number];
1284
+
1285
+ function isExcludedLendingMarketKey(value: unknown): value is ExcludedLendingMarketKey {
1286
+ return EXCLUDED_LENDING_MARKET_KEYS.includes(value as ExcludedLendingMarketKey);
1287
+ }
1251
1288
 
1252
- export const MARKET_UPDATER = new ConfigUpdater(UpdateLendingMarketMode.fromDecoded, LendingMarket, (config) => ({
1253
- [UpdateLendingMarketMode.UpdateOwner.kind]: config.lendingMarketOwnerCached,
1254
- [UpdateLendingMarketMode.UpdateImmutableFlag.kind]: config.immutable,
1255
- [UpdateLendingMarketMode.UpdateEmergencyMode.kind]: config.emergencyMode,
1256
- [UpdateLendingMarketMode.UpdateLiquidationCloseFactor.kind]: config.liquidationMaxDebtCloseFactorPct,
1257
- [UpdateLendingMarketMode.UpdateLiquidationMaxValue.kind]: config.maxLiquidatableDebtMarketValueAtOnce,
1258
- [UpdateLendingMarketMode.DeprecatedUpdateGlobalUnhealthyBorrow.kind]: null, // deprecated
1259
- [UpdateLendingMarketMode.UpdateGlobalAllowedBorrow.kind]: config.globalAllowedBorrowValue,
1260
- [UpdateLendingMarketMode.UpdateRiskCouncil.kind]: config.riskCouncil,
1261
- [UpdateLendingMarketMode.UpdateMinFullLiquidationThreshold.kind]: config.minFullLiquidationValueThreshold,
1262
- [UpdateLendingMarketMode.UpdateInsolvencyRiskLtv.kind]: config.insolvencyRiskUnhealthyLtvPct,
1263
- [UpdateLendingMarketMode.UpdateElevationGroup.kind]: config.elevationGroups,
1264
- [UpdateLendingMarketMode.UpdateReferralFeeBps.kind]: config.referralFeeBps,
1265
- [UpdateLendingMarketMode.DeprecatedUpdateMultiplierPoints.kind]: null, // deprecated
1266
- [UpdateLendingMarketMode.UpdatePriceRefreshTriggerToMaxAgePct.kind]: config.priceRefreshTriggerToMaxAgePct,
1267
- [UpdateLendingMarketMode.UpdateAutodeleverageEnabled.kind]: config.autodeleverageEnabled,
1268
- [UpdateLendingMarketMode.UpdateBorrowingDisabled.kind]: config.borrowDisabled,
1269
- [UpdateLendingMarketMode.UpdateMinNetValueObligationPostAction.kind]: config.minNetValueInObligationSf,
1270
- [UpdateLendingMarketMode.UpdateMinValueLtvSkipPriorityLiqCheck.kind]: config.minValueSkipLiquidationLtvChecks,
1271
- [UpdateLendingMarketMode.UpdateMinValueBfSkipPriorityLiqCheck.kind]: config.minValueSkipLiquidationBfChecks,
1272
- [UpdateLendingMarketMode.UpdatePaddingFields.kind]: null, // we do not update padding this way
1273
- [UpdateLendingMarketMode.UpdateName.kind]: config.name,
1274
- [UpdateLendingMarketMode.UpdateIndividualAutodeleverageMarginCallPeriodSecs.kind]:
1275
- config.individualAutodeleverageMarginCallPeriodSecs,
1276
- [UpdateLendingMarketMode.UpdateInitialDepositAmount.kind]: config.minInitialDepositAmount,
1277
- [UpdateLendingMarketMode.UpdateObligationOrderCreationEnabled.kind]: config.obligationOrderCreationEnabled,
1278
- [UpdateLendingMarketMode.UpdateObligationOrderExecutionEnabled.kind]: config.obligationOrderExecutionEnabled,
1279
- }));
1289
+ export type LendingMarketKey = Exclude<BaseLendingMarketKey, ExcludedLendingMarketKey>;
1290
+
1291
+ const updateLendingMarketConfig = (
1292
+ key: LendingMarketKey,
1293
+ market: LendingMarket,
1294
+ newMarket: LendingMarket
1295
+ ): { mode: number; value: Buffer }[] => {
1296
+ const updateLendingMarketIxsArgs: { mode: number; value: Buffer }[] = [];
1297
+ switch (key) {
1298
+ case 'lendingMarketOwner': {
1299
+ if (!market.lendingMarketOwner.equals(newMarket.lendingMarketOwner)) {
1300
+ updateLendingMarketIxsArgs.push({
1301
+ mode: UpdateLendingMarketMode.UpdateOwner.discriminator,
1302
+ value: updateMarketConfigEncodedValue(
1303
+ UpdateLendingMarketMode.UpdateOwner.discriminator,
1304
+ newMarket.lendingMarketOwner
1305
+ ),
1306
+ });
1307
+ }
1308
+ break;
1309
+ }
1310
+ case 'lendingMarketOwnerCached':
1311
+ if (!market.lendingMarketOwnerCached.equals(newMarket.lendingMarketOwnerCached)) {
1312
+ updateLendingMarketIxsArgs.push({
1313
+ mode: UpdateLendingMarketMode.UpdateOwner.discriminator,
1314
+ value: updateMarketConfigEncodedValue(
1315
+ UpdateLendingMarketMode.UpdateOwner.discriminator,
1316
+ newMarket.lendingMarketOwnerCached
1317
+ ),
1318
+ });
1319
+ }
1320
+ break;
1321
+ case 'referralFeeBps':
1322
+ if (market.referralFeeBps !== newMarket.referralFeeBps) {
1323
+ updateLendingMarketIxsArgs.push({
1324
+ mode: UpdateLendingMarketMode.UpdateReferralFeeBps.discriminator,
1325
+ value: updateMarketConfigEncodedValue(
1326
+ UpdateLendingMarketMode.UpdateReferralFeeBps.discriminator,
1327
+ newMarket.referralFeeBps
1328
+ ),
1329
+ });
1330
+ }
1331
+ break;
1332
+ case 'emergencyMode':
1333
+ if (market.emergencyMode !== newMarket.emergencyMode) {
1334
+ updateLendingMarketIxsArgs.push({
1335
+ mode: UpdateLendingMarketMode.UpdateEmergencyMode.discriminator,
1336
+ value: updateMarketConfigEncodedValue(
1337
+ UpdateLendingMarketMode.UpdateEmergencyMode.discriminator,
1338
+ newMarket.emergencyMode
1339
+ ),
1340
+ });
1341
+ }
1342
+ break;
1343
+ case 'autodeleverageEnabled':
1344
+ if (market.autodeleverageEnabled !== newMarket.autodeleverageEnabled) {
1345
+ updateLendingMarketIxsArgs.push({
1346
+ mode: UpdateLendingMarketMode.UpdateAutodeleverageEnabled.discriminator,
1347
+ value: updateMarketConfigEncodedValue(
1348
+ UpdateLendingMarketMode.UpdateAutodeleverageEnabled.discriminator,
1349
+ newMarket.autodeleverageEnabled
1350
+ ),
1351
+ });
1352
+ }
1353
+ break;
1354
+ case 'borrowDisabled':
1355
+ if (market.borrowDisabled !== newMarket.borrowDisabled) {
1356
+ updateLendingMarketIxsArgs.push({
1357
+ mode: UpdateLendingMarketMode.UpdateBorrowingDisabled.discriminator,
1358
+ value: updateMarketConfigEncodedValue(
1359
+ UpdateLendingMarketMode.UpdateBorrowingDisabled.discriminator,
1360
+ newMarket.borrowDisabled
1361
+ ),
1362
+ });
1363
+ }
1364
+ break;
1365
+ case 'priceRefreshTriggerToMaxAgePct':
1366
+ if (market.priceRefreshTriggerToMaxAgePct !== newMarket.priceRefreshTriggerToMaxAgePct) {
1367
+ updateLendingMarketIxsArgs.push({
1368
+ mode: UpdateLendingMarketMode.UpdatePriceRefreshTriggerToMaxAgePct.discriminator,
1369
+ value: updateMarketConfigEncodedValue(
1370
+ UpdateLendingMarketMode.UpdatePriceRefreshTriggerToMaxAgePct.discriminator,
1371
+ newMarket.priceRefreshTriggerToMaxAgePct
1372
+ ),
1373
+ });
1374
+ }
1375
+ break;
1376
+ case 'liquidationMaxDebtCloseFactorPct':
1377
+ if (market.liquidationMaxDebtCloseFactorPct !== newMarket.liquidationMaxDebtCloseFactorPct) {
1378
+ updateLendingMarketIxsArgs.push({
1379
+ mode: UpdateLendingMarketMode.UpdateLiquidationCloseFactor.discriminator,
1380
+ value: updateMarketConfigEncodedValue(
1381
+ UpdateLendingMarketMode.UpdateLiquidationCloseFactor.discriminator,
1382
+ newMarket.liquidationMaxDebtCloseFactorPct
1383
+ ),
1384
+ });
1385
+ }
1386
+ break;
1387
+ case 'insolvencyRiskUnhealthyLtvPct':
1388
+ if (market.insolvencyRiskUnhealthyLtvPct !== newMarket.insolvencyRiskUnhealthyLtvPct) {
1389
+ updateLendingMarketIxsArgs.push({
1390
+ mode: UpdateLendingMarketMode.UpdateInsolvencyRiskLtv.discriminator,
1391
+ value: updateMarketConfigEncodedValue(
1392
+ UpdateLendingMarketMode.UpdateInsolvencyRiskLtv.discriminator,
1393
+ newMarket.insolvencyRiskUnhealthyLtvPct
1394
+ ),
1395
+ });
1396
+ }
1397
+ break;
1398
+ case 'minFullLiquidationValueThreshold':
1399
+ if (!market.minFullLiquidationValueThreshold.eq(newMarket.minFullLiquidationValueThreshold)) {
1400
+ updateLendingMarketIxsArgs.push({
1401
+ mode: UpdateLendingMarketMode.UpdateMinFullLiquidationThreshold.discriminator,
1402
+ value: updateMarketConfigEncodedValue(
1403
+ UpdateLendingMarketMode.UpdateMinFullLiquidationThreshold.discriminator,
1404
+ newMarket.minFullLiquidationValueThreshold.toNumber()
1405
+ ),
1406
+ });
1407
+ }
1408
+ break;
1409
+ case 'maxLiquidatableDebtMarketValueAtOnce':
1410
+ if (!market.maxLiquidatableDebtMarketValueAtOnce.eq(newMarket.maxLiquidatableDebtMarketValueAtOnce)) {
1411
+ updateLendingMarketIxsArgs.push({
1412
+ mode: UpdateLendingMarketMode.UpdateLiquidationMaxValue.discriminator,
1413
+ value: updateMarketConfigEncodedValue(
1414
+ UpdateLendingMarketMode.UpdateLiquidationMaxValue.discriminator,
1415
+ newMarket.maxLiquidatableDebtMarketValueAtOnce.toNumber()
1416
+ ),
1417
+ });
1418
+ }
1419
+ break;
1420
+ case 'globalAllowedBorrowValue':
1421
+ if (!market.globalAllowedBorrowValue.eq(newMarket.globalAllowedBorrowValue)) {
1422
+ updateLendingMarketIxsArgs.push({
1423
+ mode: UpdateLendingMarketMode.UpdateGlobalAllowedBorrow.discriminator,
1424
+ value: updateMarketConfigEncodedValue(
1425
+ UpdateLendingMarketMode.UpdateGlobalAllowedBorrow.discriminator,
1426
+ newMarket.globalAllowedBorrowValue.toNumber()
1427
+ ),
1428
+ });
1429
+ }
1430
+ break;
1431
+ case 'riskCouncil':
1432
+ if (!market.riskCouncil.equals(newMarket.riskCouncil)) {
1433
+ updateLendingMarketIxsArgs.push({
1434
+ mode: UpdateLendingMarketMode.UpdateRiskCouncil.discriminator,
1435
+ value: updateMarketConfigEncodedValue(
1436
+ UpdateLendingMarketMode.UpdateRiskCouncil.discriminator,
1437
+ newMarket.riskCouncil
1438
+ ),
1439
+ });
1440
+ }
1441
+ break;
1442
+ case 'elevationGroups':
1443
+ let elevationGroupsDiffs = 0;
1444
+ for (let i = 0; i < market.elevationGroups.length; i++) {
1445
+ if (
1446
+ market.elevationGroups[i].id !== newMarket.elevationGroups[i].id ||
1447
+ market.elevationGroups[i].maxLiquidationBonusBps !== newMarket.elevationGroups[i].maxLiquidationBonusBps ||
1448
+ market.elevationGroups[i].ltvPct !== newMarket.elevationGroups[i].ltvPct ||
1449
+ market.elevationGroups[i].liquidationThresholdPct !== newMarket.elevationGroups[i].liquidationThresholdPct ||
1450
+ market.elevationGroups[i].allowNewLoans !== newMarket.elevationGroups[i].allowNewLoans ||
1451
+ market.elevationGroups[i].maxReservesAsCollateral !== newMarket.elevationGroups[i].maxReservesAsCollateral ||
1452
+ !market.elevationGroups[i].debtReserve.equals(newMarket.elevationGroups[i].debtReserve)
1453
+ ) {
1454
+ updateLendingMarketIxsArgs.push({
1455
+ mode: UpdateLendingMarketMode.UpdateElevationGroup.discriminator,
1456
+ value: updateMarketConfigEncodedValue(
1457
+ UpdateLendingMarketMode.UpdateElevationGroup.discriminator,
1458
+ newMarket.elevationGroups[i]
1459
+ ),
1460
+ });
1461
+ elevationGroupsDiffs++;
1462
+ }
1463
+ }
1464
+ if (elevationGroupsDiffs > 1) {
1465
+ throw new Error('Can only update 1 elevation group at a time');
1466
+ }
1467
+ break;
1468
+ case 'minNetValueInObligationSf':
1469
+ if (!market.minNetValueInObligationSf.eq(newMarket.minNetValueInObligationSf)) {
1470
+ updateLendingMarketIxsArgs.push({
1471
+ mode: UpdateLendingMarketMode.UpdateMinNetValueObligationPostAction.discriminator,
1472
+ value: updateMarketConfigEncodedValue(
1473
+ UpdateLendingMarketMode.UpdateMinNetValueObligationPostAction.discriminator,
1474
+ newMarket.minNetValueInObligationSf.toString()
1475
+ ),
1476
+ });
1477
+ }
1478
+ break;
1479
+ case 'minValueSkipLiquidationBfChecks':
1480
+ if (!market.minValueSkipLiquidationBfChecks.eq(newMarket.minValueSkipLiquidationBfChecks)) {
1481
+ updateLendingMarketIxsArgs.push({
1482
+ mode: UpdateLendingMarketMode.UpdateMinValueBfSkipPriorityLiqCheck.discriminator,
1483
+ value: updateMarketConfigEncodedValue(
1484
+ UpdateLendingMarketMode.UpdateMinValueBfSkipPriorityLiqCheck.discriminator,
1485
+ newMarket.minValueSkipLiquidationBfChecks.toNumber()
1486
+ ),
1487
+ });
1488
+ }
1489
+ break;
1490
+ case 'minValueSkipLiquidationLtvChecks':
1491
+ if (!market.minValueSkipLiquidationLtvChecks.eq(newMarket.minValueSkipLiquidationLtvChecks)) {
1492
+ updateLendingMarketIxsArgs.push({
1493
+ mode: UpdateLendingMarketMode.UpdateMinValueLtvSkipPriorityLiqCheck.discriminator,
1494
+ value: updateMarketConfigEncodedValue(
1495
+ UpdateLendingMarketMode.UpdateMinValueLtvSkipPriorityLiqCheck.discriminator,
1496
+ newMarket.minValueSkipLiquidationLtvChecks.toNumber()
1497
+ ),
1498
+ });
1499
+ }
1500
+ break;
1501
+ case 'individualAutodeleverageMarginCallPeriodSecs':
1502
+ if (
1503
+ market.individualAutodeleverageMarginCallPeriodSecs !== newMarket.individualAutodeleverageMarginCallPeriodSecs
1504
+ ) {
1505
+ updateLendingMarketIxsArgs.push({
1506
+ mode: UpdateLendingMarketMode.UpdateIndividualAutodeleverageMarginCallPeriodSecs.discriminator,
1507
+ value: updateMarketConfigEncodedValue(
1508
+ UpdateLendingMarketMode.UpdateIndividualAutodeleverageMarginCallPeriodSecs.discriminator,
1509
+ newMarket.individualAutodeleverageMarginCallPeriodSecs.toNumber()
1510
+ ),
1511
+ });
1512
+ }
1513
+ break;
1514
+ case 'name':
1515
+ if (!sameLengthArrayEquals(market.name, newMarket.name)) {
1516
+ updateLendingMarketIxsArgs.push({
1517
+ mode: UpdateLendingMarketMode.UpdateName.discriminator,
1518
+ value: updateMarketConfigEncodedValue(UpdateLendingMarketMode.UpdateName.discriminator, newMarket.name),
1519
+ });
1520
+ }
1521
+ break;
1522
+ case 'minInitialDepositAmount':
1523
+ if (!market.minInitialDepositAmount.eq(newMarket.minInitialDepositAmount)) {
1524
+ updateLendingMarketIxsArgs.push({
1525
+ mode: UpdateLendingMarketMode.UpdateInitialDepositAmount.discriminator,
1526
+ value: updateMarketConfigEncodedValue(
1527
+ UpdateLendingMarketMode.UpdateInitialDepositAmount.discriminator,
1528
+ newMarket.minInitialDepositAmount.toNumber()
1529
+ ),
1530
+ });
1531
+ }
1532
+ break;
1533
+ case 'obligationOrdersEnabled':
1534
+ if (market.obligationOrdersEnabled !== newMarket.obligationOrdersEnabled) {
1535
+ updateLendingMarketIxsArgs.push({
1536
+ mode: UpdateLendingMarketMode.UpdateObligationOrdersEnabled.discriminator,
1537
+ value: updateMarketConfigEncodedValue(
1538
+ UpdateLendingMarketMode.UpdateObligationOrdersEnabled.discriminator,
1539
+ newMarket.obligationOrdersEnabled
1540
+ ),
1541
+ });
1542
+ }
1543
+ break;
1544
+ default:
1545
+ assertNever(key);
1546
+ }
1547
+ return updateLendingMarketIxsArgs;
1548
+ };
1280
1549
 
1281
1550
  function parseForChangesMarketConfigAndGetIxs(
1282
1551
  marketWithAddress: MarketWithAddress,
1283
1552
  newMarket: LendingMarket,
1284
1553
  programId: PublicKey
1285
1554
  ): TransactionInstruction[] {
1286
- const encodedMarketUpdates = MARKET_UPDATER.encodeAllUpdates(marketWithAddress.state, newMarket);
1287
- return encodedMarketUpdates.map((encodedMarketUpdate) =>
1288
- updateMarketConfigIx(marketWithAddress, encodedMarketUpdate.mode, encodedMarketUpdate.value, programId)
1289
- );
1555
+ const market = marketWithAddress.state;
1556
+ const updateLendingMarketIxsArgs: { mode: number; value: Buffer }[] = [];
1557
+
1558
+ for (const key in market.toJSON()) {
1559
+ if (isExcludedLendingMarketKey(key)) {
1560
+ continue;
1561
+ }
1562
+ updateLendingMarketIxsArgs.push(...updateLendingMarketConfig(key as LendingMarketKey, market, newMarket));
1563
+ }
1564
+
1565
+ const ixs: TransactionInstruction[] = [];
1566
+
1567
+ updateLendingMarketIxsArgs.forEach((updateLendingMarketConfigArgs) => {
1568
+ ixs.push(
1569
+ updateMarketConfigIx(
1570
+ marketWithAddress,
1571
+ updateLendingMarketConfigArgs.mode,
1572
+ updateLendingMarketConfigArgs.value,
1573
+ programId
1574
+ )
1575
+ );
1576
+ });
1577
+
1578
+ return ixs;
1579
+ }
1580
+
1581
+ function updateMarketConfigEncodedValue(
1582
+ discriminator: UpdateLendingMarketModeKind['discriminator'],
1583
+ value: number | number[] | PublicKey | ElevationGroup | string
1584
+ ): Buffer {
1585
+ let buffer: Buffer = Buffer.alloc(72);
1586
+ let pkBuffer: Buffer;
1587
+ let valueBigInt: bigint;
1588
+ let valueArray: number[];
1589
+
1590
+ switch (discriminator) {
1591
+ case UpdateLendingMarketMode.UpdateEmergencyMode.discriminator:
1592
+ case UpdateLendingMarketMode.UpdateLiquidationCloseFactor.discriminator:
1593
+ case UpdateLendingMarketMode.UpdateInsolvencyRiskLtv.discriminator:
1594
+ case UpdateLendingMarketMode.UpdatePriceRefreshTriggerToMaxAgePct.discriminator:
1595
+ case UpdateLendingMarketMode.UpdateAutodeleverageEnabled.discriminator:
1596
+ case UpdateLendingMarketMode.UpdateObligationOrdersEnabled.discriminator:
1597
+ case UpdateLendingMarketMode.UpdateBorrowingDisabled.discriminator:
1598
+ buffer.writeUIntLE(value as number, 0, 1);
1599
+ break;
1600
+ case UpdateLendingMarketMode.UpdateReferralFeeBps.discriminator:
1601
+ buffer.writeUInt16LE(value as number, 0);
1602
+ break;
1603
+ case UpdateLendingMarketMode.UpdateLiquidationMaxValue.discriminator:
1604
+ case UpdateLendingMarketMode.UpdateGlobalAllowedBorrow.discriminator:
1605
+ case UpdateLendingMarketMode.UpdateMinFullLiquidationThreshold.discriminator:
1606
+ case UpdateLendingMarketMode.UpdateMinValueBfSkipPriorityLiqCheck.discriminator:
1607
+ case UpdateLendingMarketMode.UpdateMinValueLtvSkipPriorityLiqCheck.discriminator:
1608
+ case UpdateLendingMarketMode.UpdateIndividualAutodeleverageMarginCallPeriodSecs.discriminator:
1609
+ case UpdateLendingMarketMode.UpdateInitialDepositAmount.discriminator:
1610
+ value = value as number;
1611
+ buffer.writeBigUint64LE(BigInt(value), 0);
1612
+ break;
1613
+ case UpdateLendingMarketMode.UpdateOwner.discriminator:
1614
+ case UpdateLendingMarketMode.UpdateRiskCouncil.discriminator:
1615
+ pkBuffer = (value as PublicKey).toBuffer();
1616
+ pkBuffer.copy(buffer, 0);
1617
+ break;
1618
+ case UpdateLendingMarketMode.UpdateElevationGroup.discriminator:
1619
+ buffer = serializeElevationGroup(value as ElevationGroup);
1620
+ break;
1621
+ case UpdateLendingMarketMode.UpdateMinNetValueObligationPostAction.discriminator:
1622
+ valueBigInt = BigInt(value as string);
1623
+ for (let i = 0; i < 16; i++) {
1624
+ buffer[15 - i] = Number((valueBigInt >> BigInt(i * 8)) & BigInt(0xff));
1625
+ }
1626
+ break;
1627
+ case UpdateLendingMarketMode.UpdateName.discriminator:
1628
+ valueArray = value as number[];
1629
+ for (let i = 0; i < valueArray.length; i++) {
1630
+ buffer.writeUIntLE(valueArray[i], i, 1);
1631
+ }
1632
+ break;
1633
+ case UpdateLendingMarketMode.UpdatePaddingFields.discriminator:
1634
+ case UpdateLendingMarketMode.DeprecatedUpdateGlobalUnhealthyBorrow.discriminator:
1635
+ case UpdateLendingMarketMode.DeprecatedUpdateMultiplierPoints.discriminator:
1636
+ // Deliberately skipped - we are not updating padding or deprecated fields using this method
1637
+ break;
1638
+ default:
1639
+ assertNever(discriminator);
1640
+ }
1641
+
1642
+ return buffer;
1290
1643
  }
1291
1644
 
1292
1645
  function updateMarketConfigIx(
1293
1646
  marketWithAddress: MarketWithAddress,
1294
- mode: UpdateLendingMarketModeKind,
1295
- value: Uint8Array,
1647
+ modeDiscriminator: number,
1648
+ value: Buffer,
1296
1649
  programId: PublicKey
1297
1650
  ): TransactionInstruction {
1298
1651
  const accounts: UpdateLendingMarketAccounts = {
@@ -1301,13 +1654,25 @@ function updateMarketConfigIx(
1301
1654
  };
1302
1655
 
1303
1656
  const args: UpdateLendingMarketArgs = {
1304
- mode: new anchor.BN(mode.discriminator),
1305
- // NOTE: the Market's update handler expects a `[u8; 72]` (contrary to e.g. the Reserve's update handler accepting
1306
- // `Vec<u8>`). Hence, we need to add explicit padding here:
1307
- value: [...value, ...Array(72 - value.length).fill(0)],
1657
+ mode: new anchor.BN(modeDiscriminator),
1658
+ value: [...value],
1308
1659
  };
1309
1660
 
1310
1661
  const ix = updateLendingMarket(args, accounts, programId);
1311
1662
 
1312
1663
  return ix;
1313
1664
  }
1665
+
1666
+ function serializeElevationGroup(elevationGroup: ElevationGroup): Buffer {
1667
+ const buffer = Buffer.alloc(72);
1668
+ buffer.writeUInt16LE(elevationGroup.maxLiquidationBonusBps, 0);
1669
+ buffer.writeUIntLE(elevationGroup.id, 2, 1);
1670
+ buffer.writeUIntLE(elevationGroup.ltvPct, 3, 1);
1671
+ buffer.writeUIntLE(elevationGroup.liquidationThresholdPct, 4, 1);
1672
+ buffer.writeUIntLE(elevationGroup.allowNewLoans, 5, 1);
1673
+ buffer.writeUIntLE(elevationGroup.maxReservesAsCollateral, 6, 1);
1674
+ buffer.writeUIntLE(elevationGroup.padding0, 7, 1);
1675
+ const debtReserveBuffer = elevationGroup.debtReserve.toBuffer();
1676
+ debtReserveBuffer.copy(buffer, 8);
1677
+ return buffer;
1678
+ }
@@ -436,11 +436,16 @@ export class KaminoObligation {
436
436
 
437
437
  /**
438
438
  * Get the loan to value and liquidation loan to value for a collateral token reserve as ratios, accounting for the obligation elevation group if it is active
439
- * @param market
440
- * @param reserve
441
439
  */
442
- public getLtvForReserve(market: KaminoMarket, reserve: KaminoReserve): { maxLtv: Decimal; liquidationLtv: Decimal } {
443
- return KaminoObligation.getLtvForReserve(market, reserve, this.state.elevationGroup);
440
+ public getLtvForReserve(
441
+ market: KaminoMarket,
442
+ reserveAddress: PublicKey
443
+ ): { maxLtv: Decimal; liquidationLtv: Decimal } {
444
+ return KaminoObligation.getLtvForReserve(
445
+ market,
446
+ market.getExistingReserveByAddress(reserveAddress),
447
+ this.state.elevationGroup
448
+ );
444
449
  }
445
450
 
446
451
  /**
@@ -631,14 +636,6 @@ export class KaminoObligation {
631
636
  let newObligationDeposits = this.state.deposits;
632
637
  let newObligationBorrows = this.state.borrows;
633
638
 
634
- // Print deposits and borrows before
635
- for (const deposit of this.state.deposits) {
636
- console.log(`Before Deposit: ${deposit.depositReserve.toBase58()} - ${deposit.depositedAmount}`);
637
- }
638
- for (const borrow of this.state.borrows) {
639
- console.log(`Before Borrow: ${borrow.borrowReserve.toBase58()} - ${borrow.borrowedAmountSf}`);
640
- }
641
-
642
639
  switch (action) {
643
640
  case 'deposit': {
644
641
  if (amountCollateral === undefined || mintCollateral === undefined) {
@@ -753,14 +750,6 @@ export class KaminoObligation {
753
750
  null
754
751
  );
755
752
 
756
- // Print deposits and borrows after
757
- for (const deposit of newObligationDeposits) {
758
- console.log(`After Deposit: ${deposit.depositReserve.toBase58()} - ${deposit.depositedAmount}`);
759
- }
760
- for (const borrow of newObligationBorrows) {
761
- console.log(`After Borrow: ${borrow.borrowReserve.toBase58()} - ${borrow.borrowedAmountSf}`);
762
- }
763
-
764
753
  newStats = refreshedStats;
765
754
  newDeposits = deposits;
766
755
  newBorrows = borrows;
@@ -8,6 +8,7 @@ import { KaminoObligation, Position } from './obligation';
8
8
  import { TokenAmount } from './shared';
9
9
  import { ONE_HUNDRED_PCT_IN_BPS } from '../utils';
10
10
  import { getSingleElement } from '../utils/validations';
11
+ import { KaminoMarket } from './market';
11
12
 
12
13
  // Polymorphic parts of an order:
13
14
 
@@ -300,7 +301,10 @@ export class KaminoObligationOrder {
300
301
  *
301
302
  * May return `undefined` when the order's condition is not met.
302
303
  */
303
- findMaxAvailableExecution(obligation: KaminoObligation): AvailableOrderExecution | undefined {
304
+ findMaxAvailableExecution(
305
+ kaminoMarket: KaminoMarket,
306
+ obligation: KaminoObligation
307
+ ): AvailableOrderExecution | undefined {
304
308
  const conditionHit = this.condition.evaluate(obligation);
305
309
  if (conditionHit === null) {
306
310
  return undefined; // condition not met - cannot execute
@@ -311,9 +315,24 @@ export class KaminoObligationOrder {
311
315
  const executionBonusRate = this.calculateExecutionBonusRate(conditionHit, obligation);
312
316
  const executionBonusFactor = new Decimal(1).add(executionBonusRate);
313
317
  const maxWithdrawValue = maxRepayValue.mul(executionBonusFactor);
314
- const [actualWithdrawValue, withdrawDeposit] = obligation
318
+
319
+ // The order execution only allows us to pick the lowest-liquidation-LTV deposit for withdrawal (excluding 0-LTV
320
+ // assets, which are never liquidatable), hence we pre-filter the candidate deposits:
321
+ const liquidationLtvsOfDeposits = obligation
315
322
  .getDeposits()
316
- .map((deposit): [Decimal, Position] => {
323
+ .map((deposit): [Decimal, Position] => [
324
+ obligation.getLtvForReserve(kaminoMarket, deposit.reserveAddress).liquidationLtv,
325
+ deposit,
326
+ ]);
327
+ const liquidatableDeposits = liquidationLtvsOfDeposits.filter(([liquidationLtv, _deposit]) => liquidationLtv.gt(0));
328
+ // Note: in theory, we could use the Obligation's `lowestReserveDepositLiquidationLtv` (cached by SC) here, but it
329
+ // is equally easy to just find the minimum (and avoid any issues related to stale `KaminoObligation` state or
330
+ // `Decimal` rounding/comparison).
331
+ const minLiquidationLtv = Decimal.min(...liquidatableDeposits.map(([liquidationLtv, _deposit]) => liquidationLtv));
332
+
333
+ const [actualWithdrawValue, withdrawDeposit] = liquidatableDeposits
334
+ .filter(([liquidationLtv, _deposit]) => liquidationLtv.eq(minLiquidationLtv))
335
+ .map(([_liquidationLtv, deposit]): [Decimal, Position] => {
317
336
  const availableWithdrawValue = Decimal.min(deposit.marketValueRefreshed, maxWithdrawValue);
318
337
  return [availableWithdrawValue, deposit];
319
338
  })