@gearbox-protocol/sdk 13.3.3 → 13.4.0-beta.1

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.
@@ -35,6 +35,7 @@ var import_constants = require("../constants/index.js");
35
35
  var import_router = require("../router/index.js");
36
36
  var import_utils = require("../utils/index.js");
37
37
  var import_viem2 = require("../utils/viem/index.js");
38
+ var import_multicall_utils = require("./multicall-utils.js");
38
39
  const COMPRESSORS = {
39
40
  [import_chains.chains.Mainnet.id]: "0x36F3d0Bb73CBC2E94fE24dF0f26a689409cF9023",
40
41
  [import_chains.chains.Monad.id]: "0x36F3d0Bb73CBC2E94fE24dF0f26a689409cF9023"
@@ -334,12 +335,12 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
334
335
  keepAssets,
335
336
  debtOnly
336
337
  });
337
- const priceUpdates = await this.getPriceUpdatesForFacade({
338
- creditManager: account.creditManager,
339
- creditAccount: account,
340
- ignoreReservePrices
341
- });
342
- const calls = [...priceUpdates, ...routerCloseResult.calls];
338
+ const calls = await this.prependPriceUpdates(
339
+ account.creditManager,
340
+ routerCloseResult.calls,
341
+ account,
342
+ { ignoreReservePrices }
343
+ );
343
344
  let lossPolicyData;
344
345
  if (applyLossPolicy) {
345
346
  const market = this.sdk.marketRegister.findByCreditManager(
@@ -394,12 +395,7 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
394
395
  creditManager: cm.creditManager,
395
396
  slippage
396
397
  });
397
- const priceUpdates = await this.getPriceUpdatesForFacade({
398
- creditManager: ca.creditManager,
399
- creditAccount: ca
400
- });
401
- const calls = [
402
- ...operation === "close" ? [] : priceUpdates,
398
+ const operationCalls = [
403
399
  ...routerCloseResult.calls,
404
400
  ...this.prepareDisableQuotas(ca),
405
401
  ...this.prepareDecreaseDebt(ca),
@@ -407,6 +403,7 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
407
403
  (t) => this.prepareWithdrawToken(ca.creditFacade, t, import_constants.MAX_UINT256, to)
408
404
  )
409
405
  ];
406
+ const calls = operation === "close" ? operationCalls : await this.prependPriceUpdates(ca.creditManager, operationCalls, ca);
410
407
  const tx = operation === "close" ? cm.creditFacade.closeCreditAccount(ca.creditAccount, calls) : cm.creditFacade.multicall(ca.creditAccount, calls);
411
408
  return { tx, calls, routerCloseResult, creditFacade: cm.creditFacade };
412
409
  }
@@ -426,17 +423,15 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
426
423
  const cm = this.sdk.marketRegister.findCreditManager(
427
424
  creditAccount.creditManager
428
425
  );
429
- const priceUpdates = await this.getPriceUpdatesForFacade({
430
- creditManager: creditAccount.creditManager,
426
+ const operationCalls = this.prepareUpdateQuotas(
427
+ creditAccount.creditFacade,
428
+ { minQuota, averageQuota }
429
+ );
430
+ const calls = await this.prependPriceUpdates(
431
+ creditAccount.creditManager,
432
+ operationCalls,
431
433
  creditAccount
432
- });
433
- const calls = [
434
- ...priceUpdates,
435
- ...this.prepareUpdateQuotas(creditAccount.creditFacade, {
436
- minQuota,
437
- averageQuota
438
- })
439
- ];
434
+ );
440
435
  const tx = cm.creditFacade.multicall(creditAccount.creditAccount, calls);
441
436
  return { tx, calls, creditFacade: cm.creditFacade };
442
437
  }
@@ -462,13 +457,7 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
462
457
  const cm = this.sdk.marketRegister.findCreditManager(
463
458
  creditAccount.creditManager
464
459
  );
465
- const priceUpdatesCalls = await this.getPriceUpdatesForFacade({
466
- creditManager: creditAccount.creditManager,
467
- creditAccount,
468
- desiredQuotas: averageQuota
469
- });
470
- const calls = [
471
- ...priceUpdatesCalls,
460
+ const operationCalls = [
472
461
  ...this.prepareAddCollateral(
473
462
  creditAccount.creditFacade,
474
463
  [asset],
@@ -479,6 +468,11 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
479
468
  averageQuota
480
469
  })
481
470
  ];
471
+ const calls = await this.prependPriceUpdates(
472
+ creditAccount.creditManager,
473
+ operationCalls,
474
+ creditAccount
475
+ );
482
476
  const tx = cm.creditFacade.multicall(creditAccount.creditAccount, calls);
483
477
  tx.value = ethAmount.toString(10);
484
478
  return { tx, calls, creditFacade: cm.creditFacade };
@@ -506,10 +500,6 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
506
500
  const cm = this.sdk.marketRegister.findCreditManager(
507
501
  creditAccount.creditManager
508
502
  );
509
- const priceUpdatesCalls = await this.getPriceUpdatesForFacade({
510
- creditManager: creditAccount.creditManager,
511
- creditAccount
512
- });
513
503
  const addCollateralCalls = addCollateral && isDecrease ? this.prepareAddCollateral(
514
504
  creditAccount.creditFacade,
515
505
  [
@@ -520,11 +510,15 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
520
510
  ],
521
511
  {}
522
512
  ) : [];
523
- const calls = [
524
- ...priceUpdatesCalls,
513
+ const operationCalls = [
525
514
  ...addCollateralCalls,
526
515
  this.#prepareChangeDebt(creditAccount.creditFacade, change, isDecrease)
527
516
  ];
517
+ const calls = await this.prependPriceUpdates(
518
+ creditAccount.creditManager,
519
+ operationCalls,
520
+ creditAccount
521
+ );
528
522
  const tx = cm.creditFacade.multicall(creditAccount.creditAccount, calls);
529
523
  return { tx, calls, creditFacade: cm.creditFacade };
530
524
  }
@@ -547,19 +541,18 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
547
541
  const cm = this.sdk.marketRegister.findCreditManager(
548
542
  creditAccount.creditManager
549
543
  );
550
- const priceUpdatesCalls = await this.getPriceUpdatesForFacade({
551
- creditManager: creditAccount.creditManager,
552
- creditAccount,
553
- desiredQuotas: averageQuota
554
- });
555
- const calls = [
556
- ...priceUpdatesCalls,
544
+ const operationCalls = [
557
545
  ...swapCalls,
558
546
  ...this.prepareUpdateQuotas(creditAccount.creditFacade, {
559
547
  minQuota,
560
548
  averageQuota
561
549
  })
562
550
  ];
551
+ const calls = await this.prependPriceUpdates(
552
+ creditAccount.creditManager,
553
+ operationCalls,
554
+ creditAccount
555
+ );
563
556
  const tx = cm.creditFacade.multicall(creditAccount.creditAccount, calls);
564
557
  return { tx, calls, creditFacade: cm.creditFacade };
565
558
  }
@@ -661,13 +654,7 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
661
654
  args: []
662
655
  })
663
656
  };
664
- const priceUpdatesCalls = await this.getPriceUpdatesForFacade({
665
- creditManager: creditAccount.creditManager,
666
- creditAccount,
667
- desiredQuotas: averageQuota
668
- });
669
- const calls = [
670
- ...priceUpdatesCalls,
657
+ const operationCalls = [
671
658
  storeExpectedBalances,
672
659
  ...preview.requestCalls,
673
660
  compareBalances,
@@ -676,6 +663,11 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
676
663
  averageQuota
677
664
  })
678
665
  ];
666
+ const calls = await this.prependPriceUpdates(
667
+ creditAccount.creditManager,
668
+ operationCalls,
669
+ creditAccount
670
+ );
679
671
  const tx = cm.creditFacade.multicall(creditAccount.creditAccount, calls);
680
672
  return { tx, calls, creditFacade: cm.creditFacade };
681
673
  }
@@ -725,22 +717,21 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
725
717
  args: []
726
718
  })
727
719
  };
728
- const priceUpdatesCalls = zeroDebt ? [] : await this.getPriceUpdatesForFacade({
729
- creditManager: creditAccount.creditManager,
730
- creditAccount,
731
- desiredQuotas: averageQuota
732
- });
733
720
  const quotaCalls = zeroDebt ? [] : this.prepareUpdateQuotas(creditAccount.creditFacade, {
734
721
  minQuota,
735
722
  averageQuota
736
723
  });
737
- const calls = [
738
- ...priceUpdatesCalls,
724
+ const operationCalls = [
739
725
  storeExpectedBalances,
740
726
  ...claimableNow.claimCalls,
741
727
  compareBalances,
742
728
  ...quotaCalls
743
729
  ];
730
+ const calls = zeroDebt ? operationCalls : await this.prependPriceUpdates(
731
+ creditAccount.creditManager,
732
+ operationCalls,
733
+ creditAccount
734
+ );
744
735
  const tx = cm.creditFacade.multicall(creditAccount.creditAccount, calls);
745
736
  return { tx, calls, creditFacade: cm.creditFacade };
746
737
  }
@@ -783,12 +774,7 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
783
774
  }) {
784
775
  const cmSuite = this.sdk.marketRegister.findCreditManager(creditManager);
785
776
  const cm = cmSuite.creditManager;
786
- const priceUpdatesCalls = await this.getPriceUpdatesForFacade({
787
- creditManager: cm.address,
788
- desiredQuotas: averageQuota
789
- });
790
- const calls = [
791
- ...priceUpdatesCalls,
777
+ const operationCalls = [
792
778
  this.#prepareIncreaseDebt(cm.creditFacade, debt),
793
779
  ...this.prepareAddCollateral(cm.creditFacade, collateral, permits),
794
780
  ...openPathCalls,
@@ -798,6 +784,7 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
798
784
  averageQuota
799
785
  })
800
786
  ];
787
+ const calls = await this.prependPriceUpdates(cm.address, operationCalls);
801
788
  const tx = cmSuite.creditFacade.openCreditAccount(to, calls, referralCode);
802
789
  tx.value = ethAmount.toString(10);
803
790
  return { calls, tx, creditFacade: cmSuite.creditFacade };
@@ -882,37 +869,6 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
882
869
  );
883
870
  return resp;
884
871
  }
885
- /**
886
- * Returns raw txs that are needed to update all price feeds so that all credit accounts (possibly from different markets) compute
887
- *
888
- * This can be used by batch liquidator
889
- * @param accounts
890
- * @returns
891
- */
892
- async getUpdateForAccounts(accounts) {
893
- const tokensByPool = /* @__PURE__ */ new Map();
894
- const oracleByPool = /* @__PURE__ */ new Map();
895
- for (const acc of accounts) {
896
- const market = this.sdk.marketRegister.findByCreditManager(
897
- acc.creditManager
898
- );
899
- const pool = market.pool.pool.address;
900
- oracleByPool.set(pool, market.priceOracle);
901
- for (const t of acc.tokens) {
902
- if (t.balance > 10n) {
903
- const tokens = tokensByPool.get(pool) ?? /* @__PURE__ */ new Set();
904
- tokens.add(t.token);
905
- tokensByPool.set(pool, tokens);
906
- }
907
- }
908
- }
909
- const priceFeeds = [];
910
- for (const [pool, oracle] of oracleByPool.entries()) {
911
- const tokens = Array.from(tokensByPool.get(pool) ?? []);
912
- priceFeeds.push(...oracle.priceFeedsForTokens(tokens));
913
- }
914
- return this.sdk.priceFeeds.generatePriceFeedsUpdateTxs(priceFeeds);
915
- }
916
872
  async getUpdateForAccount(options) {
917
873
  const { creditManager, creditAccount, desiredQuotas, ignoreReservePrices } = options;
918
874
  const quotaRecord = desiredQuotas ? (0, import_router.assetsMap)(desiredQuotas) : desiredQuotas;
@@ -976,19 +932,113 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
976
932
  return market.priceOracle.onDemandPriceUpdates(
977
933
  cm.creditFacade.address,
978
934
  update
935
+ ).raw;
936
+ }
937
+ /**
938
+ * Analyzes a multicall array and prepends necessary on-demand price feed updates.
939
+ *
940
+ * Deduplicates existing `onDemandPriceUpdates` calls
941
+ *
942
+ * @param creditManager - Address of the credit manager
943
+ * @param calls - The multicall array to prepend price updates to
944
+ * @param ca - Credit account slice, undefined when opening a new account
945
+ * @param options - Optional settings for price update generation
946
+ * @returns A new array with a single consolidated price update call prepended,
947
+ * followed by the non-price-update calls in their original order
948
+ */
949
+ async prependPriceUpdates(creditManager, calls, ca, options) {
950
+ const market = this.sdk.marketRegister.findByCreditManager(creditManager);
951
+ const cm = this.sdk.marketRegister.findCreditManager(creditManager).creditManager;
952
+ const { priceUpdates: existingUpdates, remainingCalls } = (0, import_multicall_utils.extractPriceUpdates)(calls);
953
+ const tokens = new import_utils.AddressSet([
954
+ cm.underlying,
955
+ // underlying - always included
956
+ ...(0, import_multicall_utils.extractQuotaTokens)(calls)
957
+ // tokens from `updateQuota` calls
958
+ ]);
959
+ if (ca) {
960
+ for (const t of ca.tokens) {
961
+ const isEnabled = (t.mask & ca.enabledTokensMask) !== 0n;
962
+ if (t.balance > 10n && isEnabled) {
963
+ tokens.add(t.token);
964
+ }
965
+ }
966
+ }
967
+ const ignoreReservePrices = options?.ignoreReservePrices;
968
+ const priceFeeds = market.priceOracle.priceFeedsForTokens(Array.from(tokens), {
969
+ main: true,
970
+ reserve: !ignoreReservePrices
971
+ });
972
+ const tStr = tokens.map((t) => this.labelAddress(t)).join(", ");
973
+ const remark = ignoreReservePrices ? " main" : "";
974
+ this.logger?.debug(
975
+ { account: ca?.creditAccount, manager: cm.name },
976
+ `prependPriceUpdates for ${tStr} from ${priceFeeds.length}${remark} price feeds`
979
977
  );
978
+ const generatedUpdates = await this.sdk.priceFeeds.generatePriceFeedsUpdates(priceFeeds);
979
+ const merged = (0, import_multicall_utils.mergePriceUpdates)(existingUpdates, generatedUpdates);
980
+ if (merged.length === 0) {
981
+ return remainingCalls;
982
+ }
983
+ return [
984
+ {
985
+ target: cm.creditFacade,
986
+ callData: (0, import_viem.encodeFunctionData)({
987
+ abi: import_generated.iCreditFacadeMulticallV310Abi,
988
+ functionName: "onDemandPriceUpdates",
989
+ args: [merged]
990
+ })
991
+ },
992
+ ...remainingCalls
993
+ ];
980
994
  }
981
995
  /**
982
- * Returns price updates in format that is accepted by various credit facade methods (multicall, close/liquidate, etc...).
983
- * - If there are desiredQuotas and creditAccount update quotaBalance > 0 || (balance > 10n && isEnabled). Is used when account has both: balances and quota buys.
984
- * - If there is creditAccount update balance > 10n && isEnabled. Is used in credit account actions when quota is not being bought.
985
- * - If there is desiredQuotas update quotaBalance > 0. Is used on credit account opening, when quota is bought for the first time.
986
- * @param acc
987
- * @returns
996
+ * Executes a multicall on a credit account, automatically prepending
997
+ * necessary on-demand price feed updates.
998
+ *
999
+ * @param creditAccount - Credit account to execute multicall on
1000
+ * @param calls - Array of multicall operations (price updates will be inferred)
1001
+ * @param options - Optional settings for price update generation
1002
+ * @returns Raw transaction ready to be signed and sent
988
1003
  */
989
- async getPriceUpdatesForFacade(options) {
990
- const updates = await this.getOnDemandPriceUpdates(options);
991
- return updates.multicall;
1004
+ async multicall(creditAccount, calls, options) {
1005
+ const cm = this.sdk.marketRegister.findCreditManager(
1006
+ creditAccount.creditManager
1007
+ );
1008
+ const callsWithPrices = await this.prependPriceUpdates(
1009
+ creditAccount.creditManager,
1010
+ calls,
1011
+ creditAccount,
1012
+ options
1013
+ );
1014
+ return cm.creditFacade.multicall(
1015
+ creditAccount.creditAccount,
1016
+ callsWithPrices
1017
+ );
1018
+ }
1019
+ /**
1020
+ * Executes a bot multicall on a credit account, automatically prepending
1021
+ * necessary on-demand price feed updates.
1022
+ *
1023
+ * @param creditAccount - Credit account to execute bot multicall on
1024
+ * @param calls - Array of multicall operations (price updates will be inferred)
1025
+ * @param options - Optional settings for price update generation
1026
+ * @returns Raw transaction ready to be signed and sent
1027
+ */
1028
+ async botMulticall(creditAccount, calls, options) {
1029
+ const cm = this.sdk.marketRegister.findCreditManager(
1030
+ creditAccount.creditManager
1031
+ );
1032
+ const callsWithPrices = await this.prependPriceUpdates(
1033
+ creditAccount.creditManager,
1034
+ calls,
1035
+ creditAccount,
1036
+ options
1037
+ );
1038
+ return cm.creditFacade.botMulticall(
1039
+ creditAccount.creditAccount,
1040
+ callsWithPrices
1041
+ );
992
1042
  }
993
1043
  prepareDisableQuotas(ca) {
994
1044
  const calls = [];
@@ -1110,79 +1160,6 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
1110
1160
  )[0];
1111
1161
  }
1112
1162
  }
1113
- const iMellowClaimerAdapterAbi = [
1114
- {
1115
- type: "function",
1116
- name: "getMultiVaultSubvaultIndices",
1117
- inputs: [{ name: "multiVault", type: "address", internalType: "address" }],
1118
- outputs: [
1119
- {
1120
- name: "subvaultIndices",
1121
- type: "uint256[]",
1122
- internalType: "uint256[]"
1123
- },
1124
- {
1125
- name: "withdrawalIndices",
1126
- type: "uint256[][]",
1127
- internalType: "uint256[][]"
1128
- }
1129
- ],
1130
- stateMutability: "view"
1131
- },
1132
- {
1133
- type: "function",
1134
- name: "getUserSubvaultIndices",
1135
- inputs: [
1136
- { name: "multiVault", type: "address", internalType: "address" },
1137
- { name: "user", type: "address", internalType: "address" }
1138
- ],
1139
- outputs: [
1140
- {
1141
- name: "subvaultIndices",
1142
- type: "uint256[]",
1143
- internalType: "uint256[]"
1144
- },
1145
- {
1146
- name: "withdrawalIndices",
1147
- type: "uint256[][]",
1148
- internalType: "uint256[][]"
1149
- }
1150
- ],
1151
- stateMutability: "view"
1152
- },
1153
- {
1154
- type: "function",
1155
- name: "multiAccept",
1156
- inputs: [
1157
- { name: "multiVault", type: "address", internalType: "address" },
1158
- {
1159
- name: "subvaultIndices",
1160
- type: "uint256[]",
1161
- internalType: "uint256[]"
1162
- },
1163
- { name: "indices", type: "uint256[][]", internalType: "uint256[][]" }
1164
- ],
1165
- outputs: [{ name: "", type: "bool", internalType: "bool" }],
1166
- stateMutability: "nonpayable"
1167
- },
1168
- {
1169
- type: "function",
1170
- name: "multiAcceptAndClaim",
1171
- inputs: [
1172
- { name: "multiVault", type: "address", internalType: "address" },
1173
- {
1174
- name: "subvaultIndices",
1175
- type: "uint256[]",
1176
- internalType: "uint256[]"
1177
- },
1178
- { name: "indices", type: "uint256[][]", internalType: "uint256[][]" },
1179
- { name: "", type: "address", internalType: "address" },
1180
- { name: "maxAssets", type: "uint256", internalType: "uint256" }
1181
- ],
1182
- outputs: [{ name: "", type: "bool", internalType: "bool" }],
1183
- stateMutability: "nonpayable"
1184
- }
1185
- ];
1186
1163
  // Annotate the CommonJS export names for ESM import in node:
1187
1164
  0 && (module.exports = {
1188
1165
  AbstractCreditAccountService,
@@ -37,10 +37,6 @@ class CreditAccountServiceV310 extends import_AbstractCreditAccountsService.Abst
37
37
  const cm = this.sdk.marketRegister.findCreditManager(
38
38
  targetContract.creditManager
39
39
  );
40
- const priceUpdatesCalls = targetContract.type === "creditAccount" ? await this.getPriceUpdatesForFacade({
41
- creditManager: targetContract.creditManager,
42
- creditAccount: targetContract
43
- }) : [];
44
40
  const permissions = defaultPermissions !== null ? defaultPermissions : await (0, import_viem.getContract)({
45
41
  address: botAddress,
46
42
  client: this.sdk.client,
@@ -64,7 +60,11 @@ class CreditAccountServiceV310 extends import_AbstractCreditAccountsService.Abst
64
60
  args: [botAddress, permissions]
65
61
  })
66
62
  };
67
- const calls = [...priceUpdatesCalls, addBotCall];
63
+ const calls = targetContract.type === "creditAccount" ? await this.prependPriceUpdates(
64
+ targetContract.creditManager,
65
+ [addBotCall],
66
+ targetContract
67
+ ) : [addBotCall];
68
68
  const tx = targetContract.type === "creditAccount" ? cm.creditFacade.multicall(targetContract.creditAccount, calls) : void 0;
69
69
  return { tx, calls, creditFacade: cm.creditFacade };
70
70
  }
@@ -81,12 +81,7 @@ class CreditAccountServiceV310 extends import_AbstractCreditAccountsService.Abst
81
81
  const cm = this.sdk.marketRegister.findCreditManager(
82
82
  creditAccount.creditManager
83
83
  );
84
- const priceUpdatesCalls = await this.getPriceUpdatesForFacade({
85
- creditManager: creditAccount.creditManager,
86
- creditAccount
87
- });
88
- const calls = [
89
- ...priceUpdatesCalls,
84
+ const operationCalls = [
90
85
  ...assetsToWithdraw.map(
91
86
  (a) => this.prepareWithdrawToken(
92
87
  creditAccount.creditFacade,
@@ -100,6 +95,11 @@ class CreditAccountServiceV310 extends import_AbstractCreditAccountsService.Abst
100
95
  averageQuota
101
96
  })
102
97
  ];
98
+ const calls = await this.prependPriceUpdates(
99
+ creditAccount.creditManager,
100
+ operationCalls,
101
+ creditAccount
102
+ );
103
103
  const tx = cm.creditFacade.multicall(creditAccount.creditAccount, calls);
104
104
  return { tx, calls, creditFacade: cm.creditFacade };
105
105
  }
@@ -122,12 +122,7 @@ class CreditAccountServiceV310 extends import_AbstractCreditAccountsService.Abst
122
122
  tokensToClaim,
123
123
  creditAccount: ca
124
124
  });
125
- const priceUpdates = await this.getPriceUpdatesForFacade({
126
- creditManager: ca.creditManager,
127
- creditAccount: ca
128
- });
129
- const calls = [
130
- ...operation === "close" ? [] : priceUpdates,
125
+ const operationCalls = [
131
126
  ...this.prepareAddCollateral(ca.creditFacade, addCollateral, permits),
132
127
  ...this.prepareDisableQuotas(ca),
133
128
  ...this.prepareDecreaseDebt(ca),
@@ -136,6 +131,7 @@ class CreditAccountServiceV310 extends import_AbstractCreditAccountsService.Abst
136
131
  (t) => this.prepareWithdrawToken(ca.creditFacade, t.token, import_math.MAX_UINT256, to)
137
132
  )
138
133
  ];
134
+ const calls = operation === "close" ? operationCalls : await this.prependPriceUpdates(ca.creditManager, operationCalls, ca);
139
135
  const tx = operation === "close" ? cm.creditFacade.closeCreditAccount(ca.creditAccount, calls) : cm.creditFacade.multicall(ca.creditAccount, calls);
140
136
  return { tx, calls, creditFacade: cm.creditFacade };
141
137
  }
@@ -156,19 +152,19 @@ class CreditAccountServiceV310 extends import_AbstractCreditAccountsService.Abst
156
152
  tokensToClaim,
157
153
  creditAccount: ca
158
154
  });
159
- const priceUpdates = await this.getPriceUpdatesForFacade({
160
- creditManager: ca.creditManager,
161
- creditAccount: ca
162
- });
163
155
  const addCollateral = collateralAssets.filter((a) => a.balance > 0);
164
- const calls = [
165
- ...priceUpdates,
156
+ const operationCalls = [
166
157
  ...this.prepareAddCollateral(ca.creditFacade, addCollateral, permits),
167
158
  ...claimPath.calls,
168
159
  ...assetsToWithdraw.map(
169
160
  (t) => this.prepareWithdrawToken(ca.creditFacade, t.token, import_math.MAX_UINT256, to)
170
161
  )
171
162
  ];
163
+ const calls = await this.prependPriceUpdates(
164
+ ca.creditManager,
165
+ operationCalls,
166
+ ca
167
+ );
172
168
  const tx = cm.creditFacade.liquidateCreditAccount(
173
169
  ca.creditAccount,
174
170
  to,
@@ -198,16 +194,15 @@ class CreditAccountServiceV310 extends import_AbstractCreditAccountsService.Abst
198
194
  });
199
195
  }
200
196
  if (claimPath.calls.length === 0) throw new Error("No path to execute");
201
- const priceUpdatesCalls = await this.getPriceUpdatesForFacade({
202
- creditManager: ca.creditManager,
203
- creditAccount: ca,
204
- desiredQuotas: averageQuota
205
- });
206
- const calls = [
207
- ...priceUpdatesCalls,
197
+ const operationCalls = [
208
198
  ...claimPath.calls,
209
199
  ...this.prepareUpdateQuotas(ca.creditFacade, { minQuota, averageQuota })
210
200
  ];
201
+ const calls = await this.prependPriceUpdates(
202
+ ca.creditManager,
203
+ operationCalls,
204
+ ca
205
+ );
211
206
  const tx = cm.creditFacade.multicall(ca.creditAccount, calls);
212
207
  return { tx, calls, creditFacade: cm.creditFacade };
213
208
  }
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var multicall_utils_exports = {};
20
+ __export(multicall_utils_exports, {
21
+ extractPriceUpdates: () => extractPriceUpdates,
22
+ extractQuotaTokens: () => extractQuotaTokens,
23
+ mergePriceUpdates: () => mergePriceUpdates
24
+ });
25
+ module.exports = __toCommonJS(multicall_utils_exports);
26
+ var import_viem = require("viem");
27
+ var import_generated = require("../../abi/310/generated.js");
28
+ var import_AddressMap = require("../utils/AddressMap.js");
29
+ var import_AddressSet = require("../utils/AddressSet.js");
30
+ const ON_DEMAND_SELECTOR = (0, import_viem.toFunctionSelector)(
31
+ (0, import_viem.getAbiItem)({
32
+ abi: import_generated.iCreditFacadeMulticallV310Abi,
33
+ name: "onDemandPriceUpdates"
34
+ })
35
+ );
36
+ const UPDATE_QUOTA_SELECTOR = (0, import_viem.toFunctionSelector)(
37
+ (0, import_viem.getAbiItem)({
38
+ abi: import_generated.iCreditFacadeMulticallV310Abi,
39
+ name: "updateQuota"
40
+ })
41
+ );
42
+ function extractPriceUpdates(calls) {
43
+ const priceUpdates = [];
44
+ const remainingCalls = [];
45
+ for (const call of calls) {
46
+ if (isOnDemandPriceUpdateCall(call)) {
47
+ const decoded = (0, import_viem.decodeFunctionData)({
48
+ abi: import_generated.iCreditFacadeMulticallV310Abi,
49
+ data: call.callData
50
+ });
51
+ const updates = decoded.args[0];
52
+ priceUpdates.push(...updates);
53
+ } else {
54
+ remainingCalls.push(call);
55
+ }
56
+ }
57
+ return { priceUpdates, remainingCalls };
58
+ }
59
+ function extractQuotaTokens(calls) {
60
+ const tokens = new import_AddressSet.AddressSet();
61
+ for (const { callData } of calls) {
62
+ if (callData.slice(0, 10) !== UPDATE_QUOTA_SELECTOR) {
63
+ continue;
64
+ }
65
+ const decoded = (0, import_viem.decodeFunctionData)({
66
+ abi: import_generated.iCreditFacadeMulticallV310Abi,
67
+ data: callData
68
+ });
69
+ const [token, quotaChange] = decoded.args;
70
+ if (quotaChange > 0n) {
71
+ tokens.add(token);
72
+ }
73
+ }
74
+ return tokens;
75
+ }
76
+ function mergePriceUpdates(existing, generated) {
77
+ const seen = new import_AddressMap.AddressMap();
78
+ for (const u of [...generated, ...existing]) {
79
+ seen.upsert(u.priceFeed, u);
80
+ }
81
+ return seen.values();
82
+ }
83
+ function isOnDemandPriceUpdateCall(call) {
84
+ return call.callData.slice(0, 10) === ON_DEMAND_SELECTOR;
85
+ }
86
+ // Annotate the CommonJS export names for ESM import in node:
87
+ 0 && (module.exports = {
88
+ extractPriceUpdates,
89
+ extractQuotaTokens,
90
+ mergePriceUpdates
91
+ });
@@ -91,6 +91,12 @@ class CreditFacadeV310Contract extends import_CreditFacadeV310BaseContract.Credi
91
91
  args: [ca, calls]
92
92
  });
93
93
  }
94
+ botMulticall(ca, calls) {
95
+ return this.createRawTx({
96
+ functionName: "botMulticall",
97
+ args: [ca, calls]
98
+ });
99
+ }
94
100
  openCreditAccount(to, calls, referralCode) {
95
101
  return this.createRawTx({
96
102
  functionName: "openCreditAccount",