@across-protocol/sdk 3.1.27 → 3.1.28

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 (229) hide show
  1. package/dist/cjs/clients/BundleDataClient/BundleDataClient.d.ts +60 -0
  2. package/dist/cjs/clients/BundleDataClient/BundleDataClient.js +929 -0
  3. package/dist/cjs/clients/BundleDataClient/BundleDataClient.js.map +1 -0
  4. package/dist/cjs/clients/BundleDataClient/index.d.ts +2 -0
  5. package/dist/cjs/clients/BundleDataClient/index.js +6 -0
  6. package/dist/cjs/clients/BundleDataClient/index.js.map +1 -0
  7. package/dist/cjs/clients/BundleDataClient/utils/DataworkerUtils.d.ts +15 -0
  8. package/dist/cjs/clients/BundleDataClient/utils/DataworkerUtils.js +131 -0
  9. package/dist/cjs/clients/BundleDataClient/utils/DataworkerUtils.js.map +1 -0
  10. package/dist/cjs/clients/BundleDataClient/utils/FillUtils.d.ts +6 -0
  11. package/dist/cjs/clients/BundleDataClient/utils/FillUtils.js +19 -0
  12. package/dist/cjs/clients/BundleDataClient/utils/FillUtils.js.map +1 -0
  13. package/dist/cjs/clients/BundleDataClient/utils/MerkleTreeUtils.d.ts +3 -0
  14. package/dist/cjs/clients/BundleDataClient/utils/MerkleTreeUtils.js +23 -0
  15. package/dist/cjs/clients/BundleDataClient/utils/MerkleTreeUtils.js.map +1 -0
  16. package/dist/cjs/clients/BundleDataClient/utils/PoolRebalanceUtils.d.ts +24 -0
  17. package/dist/cjs/clients/BundleDataClient/utils/PoolRebalanceUtils.js +129 -0
  18. package/dist/cjs/clients/BundleDataClient/utils/PoolRebalanceUtils.js.map +1 -0
  19. package/dist/cjs/clients/BundleDataClient/utils/SuperstructUtils.d.ts +302 -0
  20. package/dist/cjs/clients/BundleDataClient/utils/SuperstructUtils.js +77 -0
  21. package/dist/cjs/clients/BundleDataClient/utils/SuperstructUtils.js.map +1 -0
  22. package/dist/cjs/clients/BundleDataClient/utils/index.d.ts +6 -0
  23. package/dist/cjs/clients/BundleDataClient/utils/index.js +10 -0
  24. package/dist/cjs/clients/BundleDataClient/utils/index.js.map +1 -0
  25. package/dist/cjs/clients/BundleDataClient/utils/shims.d.ts +8 -0
  26. package/dist/cjs/clients/BundleDataClient/utils/shims.js +3 -0
  27. package/dist/cjs/clients/BundleDataClient/utils/shims.js.map +1 -0
  28. package/dist/cjs/clients/index.d.ts +1 -0
  29. package/dist/cjs/clients/index.js +2 -1
  30. package/dist/cjs/clients/index.js.map +1 -1
  31. package/dist/cjs/interfaces/BundleData.d.ts +63 -0
  32. package/dist/cjs/interfaces/BundleData.js +3 -0
  33. package/dist/cjs/interfaces/BundleData.js.map +1 -0
  34. package/dist/cjs/interfaces/index.d.ts +1 -0
  35. package/dist/cjs/interfaces/index.js +1 -0
  36. package/dist/cjs/interfaces/index.js.map +1 -1
  37. package/dist/cjs/providers/alchemy.js +5 -5
  38. package/dist/cjs/providers/alchemy.js.map +1 -1
  39. package/dist/cjs/providers/drpc.d.ts +2 -0
  40. package/dist/cjs/providers/drpc.js +21 -0
  41. package/dist/cjs/providers/drpc.js.map +1 -0
  42. package/dist/cjs/providers/infura.js +5 -5
  43. package/dist/cjs/providers/infura.js.map +1 -1
  44. package/dist/cjs/providers/types.d.ts +1 -1
  45. package/dist/cjs/providers/utils.js +3 -1
  46. package/dist/cjs/providers/utils.js.map +1 -1
  47. package/dist/cjs/utils/AddressUtils.d.ts +1 -0
  48. package/dist/cjs/utils/AddressUtils.js +15 -1
  49. package/dist/cjs/utils/AddressUtils.js.map +1 -1
  50. package/dist/cjs/utils/ContractUtils.d.ts +1 -0
  51. package/dist/cjs/utils/ContractUtils.js +12 -0
  52. package/dist/cjs/utils/ContractUtils.js.map +1 -0
  53. package/dist/cjs/utils/Multicall.d.ts +3 -2
  54. package/dist/cjs/utils/Multicall.js +40 -41
  55. package/dist/cjs/utils/Multicall.js.map +1 -1
  56. package/dist/cjs/utils/ObjectUtils.d.ts +18 -0
  57. package/dist/cjs/utils/ObjectUtils.js +27 -1
  58. package/dist/cjs/utils/ObjectUtils.js.map +1 -1
  59. package/dist/cjs/utils/abi/contracts/index.d.ts +1 -0
  60. package/dist/cjs/utils/abi/contracts/index.js +9 -0
  61. package/dist/cjs/utils/abi/contracts/index.js.map +1 -0
  62. package/dist/cjs/utils/abi/typechain/Multicall3.d.ts +289 -0
  63. package/dist/cjs/utils/abi/typechain/Multicall3.js +3 -0
  64. package/dist/cjs/utils/abi/typechain/Multicall3.js.map +1 -0
  65. package/dist/cjs/utils/abi/typechain/common.d.ts +21 -0
  66. package/dist/cjs/utils/abi/typechain/common.js +3 -0
  67. package/dist/cjs/utils/abi/typechain/common.js.map +1 -0
  68. package/dist/cjs/utils/abi/typechain/factories/Multicall3__factory.d.ts +339 -0
  69. package/dist/cjs/utils/abi/typechain/factories/Multicall3__factory.js +458 -0
  70. package/dist/cjs/utils/abi/typechain/factories/Multicall3__factory.js.map +1 -0
  71. package/dist/cjs/utils/abi/typechain/factories/index.d.ts +1 -0
  72. package/dist/cjs/utils/abi/typechain/factories/index.js +6 -0
  73. package/dist/cjs/utils/abi/typechain/factories/index.js.map +1 -0
  74. package/dist/cjs/utils/abi/typechain/index.d.ts +3 -0
  75. package/dist/cjs/utils/abi/typechain/index.js +8 -0
  76. package/dist/cjs/utils/abi/typechain/index.js.map +1 -0
  77. package/dist/esm/clients/BundleDataClient/BundleDataClient.d.ts +60 -0
  78. package/dist/esm/clients/BundleDataClient/BundleDataClient.js +1097 -0
  79. package/dist/esm/clients/BundleDataClient/BundleDataClient.js.map +1 -0
  80. package/dist/esm/clients/BundleDataClient/index.d.ts +2 -0
  81. package/dist/esm/clients/BundleDataClient/index.js +3 -0
  82. package/dist/esm/clients/BundleDataClient/index.js.map +1 -0
  83. package/dist/esm/clients/BundleDataClient/utils/DataworkerUtils.d.ts +15 -0
  84. package/dist/esm/clients/BundleDataClient/utils/DataworkerUtils.js +182 -0
  85. package/dist/esm/clients/BundleDataClient/utils/DataworkerUtils.js.map +1 -0
  86. package/dist/esm/clients/BundleDataClient/utils/FillUtils.d.ts +6 -0
  87. package/dist/esm/clients/BundleDataClient/utils/FillUtils.js +20 -0
  88. package/dist/esm/clients/BundleDataClient/utils/FillUtils.js.map +1 -0
  89. package/dist/esm/clients/BundleDataClient/utils/MerkleTreeUtils.d.ts +3 -0
  90. package/dist/esm/clients/BundleDataClient/utils/MerkleTreeUtils.js +20 -0
  91. package/dist/esm/clients/BundleDataClient/utils/MerkleTreeUtils.js.map +1 -0
  92. package/dist/esm/clients/BundleDataClient/utils/PoolRebalanceUtils.d.ts +24 -0
  93. package/dist/esm/clients/BundleDataClient/utils/PoolRebalanceUtils.js +157 -0
  94. package/dist/esm/clients/BundleDataClient/utils/PoolRebalanceUtils.js.map +1 -0
  95. package/dist/esm/clients/BundleDataClient/utils/SuperstructUtils.d.ts +302 -0
  96. package/dist/esm/clients/BundleDataClient/utils/SuperstructUtils.js +79 -0
  97. package/dist/esm/clients/BundleDataClient/utils/SuperstructUtils.js.map +1 -0
  98. package/dist/esm/clients/BundleDataClient/utils/index.d.ts +6 -0
  99. package/dist/esm/clients/BundleDataClient/utils/index.js +7 -0
  100. package/dist/esm/clients/BundleDataClient/utils/index.js.map +1 -0
  101. package/dist/esm/clients/BundleDataClient/utils/shims.d.ts +8 -0
  102. package/dist/esm/clients/BundleDataClient/utils/shims.js +2 -0
  103. package/dist/esm/clients/BundleDataClient/utils/shims.js.map +1 -0
  104. package/dist/esm/clients/index.d.ts +1 -0
  105. package/dist/esm/clients/index.js +2 -0
  106. package/dist/esm/clients/index.js.map +1 -1
  107. package/dist/esm/interfaces/BundleData.d.ts +63 -0
  108. package/dist/esm/interfaces/BundleData.js +2 -0
  109. package/dist/esm/interfaces/BundleData.js.map +1 -0
  110. package/dist/esm/interfaces/index.d.ts +1 -0
  111. package/dist/esm/interfaces/index.js +1 -0
  112. package/dist/esm/interfaces/index.js.map +1 -1
  113. package/dist/esm/providers/alchemy.js +6 -6
  114. package/dist/esm/providers/alchemy.js.map +1 -1
  115. package/dist/esm/providers/drpc.d.ts +2 -0
  116. package/dist/esm/providers/drpc.js +18 -0
  117. package/dist/esm/providers/drpc.js.map +1 -0
  118. package/dist/esm/providers/infura.js +6 -6
  119. package/dist/esm/providers/infura.js.map +1 -1
  120. package/dist/esm/providers/types.d.ts +1 -1
  121. package/dist/esm/providers/utils.js +3 -1
  122. package/dist/esm/providers/utils.js.map +1 -1
  123. package/dist/esm/utils/AddressUtils.d.ts +1 -0
  124. package/dist/esm/utils/AddressUtils.js +16 -1
  125. package/dist/esm/utils/AddressUtils.js.map +1 -1
  126. package/dist/esm/utils/ContractUtils.d.ts +1 -0
  127. package/dist/esm/utils/ContractUtils.js +8 -0
  128. package/dist/esm/utils/ContractUtils.js.map +1 -0
  129. package/dist/esm/utils/Multicall.d.ts +3 -2
  130. package/dist/esm/utils/Multicall.js +39 -42
  131. package/dist/esm/utils/Multicall.js.map +1 -1
  132. package/dist/esm/utils/ObjectUtils.d.ts +18 -0
  133. package/dist/esm/utils/ObjectUtils.js +24 -0
  134. package/dist/esm/utils/ObjectUtils.js.map +1 -1
  135. package/dist/esm/utils/abi/contracts/index.d.ts +1 -0
  136. package/dist/esm/utils/abi/contracts/index.js +2 -0
  137. package/dist/esm/utils/abi/contracts/index.js.map +1 -0
  138. package/dist/esm/utils/abi/typechain/Multicall3.d.ts +292 -0
  139. package/dist/esm/utils/abi/typechain/Multicall3.js +2 -0
  140. package/dist/esm/utils/abi/typechain/Multicall3.js.map +1 -0
  141. package/dist/esm/utils/abi/typechain/common.d.ts +21 -0
  142. package/dist/esm/utils/abi/typechain/common.js +2 -0
  143. package/dist/esm/utils/abi/typechain/common.js.map +1 -0
  144. package/dist/esm/utils/abi/typechain/factories/Multicall3__factory.d.ts +339 -0
  145. package/dist/esm/utils/abi/typechain/factories/Multicall3__factory.js +458 -0
  146. package/dist/esm/utils/abi/typechain/factories/Multicall3__factory.js.map +1 -0
  147. package/dist/esm/utils/abi/typechain/factories/index.d.ts +1 -0
  148. package/dist/esm/utils/abi/typechain/factories/index.js +5 -0
  149. package/dist/esm/utils/abi/typechain/factories/index.js.map +1 -0
  150. package/dist/esm/utils/abi/typechain/index.d.ts +3 -0
  151. package/dist/esm/utils/abi/typechain/index.js +4 -0
  152. package/dist/esm/utils/abi/typechain/index.js.map +1 -0
  153. package/dist/types/clients/BundleDataClient/BundleDataClient.d.ts +61 -0
  154. package/dist/types/clients/BundleDataClient/BundleDataClient.d.ts.map +1 -0
  155. package/dist/types/clients/BundleDataClient/index.d.ts +3 -0
  156. package/dist/types/clients/BundleDataClient/index.d.ts.map +1 -0
  157. package/dist/types/clients/BundleDataClient/utils/DataworkerUtils.d.ts +16 -0
  158. package/dist/types/clients/BundleDataClient/utils/DataworkerUtils.d.ts.map +1 -0
  159. package/dist/types/clients/BundleDataClient/utils/FillUtils.d.ts +7 -0
  160. package/dist/types/clients/BundleDataClient/utils/FillUtils.d.ts.map +1 -0
  161. package/dist/types/clients/BundleDataClient/utils/MerkleTreeUtils.d.ts +4 -0
  162. package/dist/types/clients/BundleDataClient/utils/MerkleTreeUtils.d.ts.map +1 -0
  163. package/dist/types/clients/BundleDataClient/utils/PoolRebalanceUtils.d.ts +25 -0
  164. package/dist/types/clients/BundleDataClient/utils/PoolRebalanceUtils.d.ts.map +1 -0
  165. package/dist/types/clients/BundleDataClient/utils/SuperstructUtils.d.ts +303 -0
  166. package/dist/types/clients/BundleDataClient/utils/SuperstructUtils.d.ts.map +1 -0
  167. package/dist/types/clients/BundleDataClient/utils/index.d.ts +7 -0
  168. package/dist/types/clients/BundleDataClient/utils/index.d.ts.map +1 -0
  169. package/dist/types/clients/BundleDataClient/utils/shims.d.ts +9 -0
  170. package/dist/types/clients/BundleDataClient/utils/shims.d.ts.map +1 -0
  171. package/dist/types/clients/index.d.ts +1 -0
  172. package/dist/types/clients/index.d.ts.map +1 -1
  173. package/dist/types/interfaces/BundleData.d.ts +64 -0
  174. package/dist/types/interfaces/BundleData.d.ts.map +1 -0
  175. package/dist/types/interfaces/index.d.ts +1 -0
  176. package/dist/types/interfaces/index.d.ts.map +1 -1
  177. package/dist/types/providers/drpc.d.ts +3 -0
  178. package/dist/types/providers/drpc.d.ts.map +1 -0
  179. package/dist/types/providers/types.d.ts +1 -1
  180. package/dist/types/providers/types.d.ts.map +1 -1
  181. package/dist/types/providers/utils.d.ts.map +1 -1
  182. package/dist/types/utils/AddressUtils.d.ts +1 -0
  183. package/dist/types/utils/AddressUtils.d.ts.map +1 -1
  184. package/dist/types/utils/ContractUtils.d.ts +2 -0
  185. package/dist/types/utils/ContractUtils.d.ts.map +1 -0
  186. package/dist/types/utils/Multicall.d.ts +3 -2
  187. package/dist/types/utils/Multicall.d.ts.map +1 -1
  188. package/dist/types/utils/ObjectUtils.d.ts +18 -0
  189. package/dist/types/utils/ObjectUtils.d.ts.map +1 -1
  190. package/dist/types/utils/abi/contracts/index.d.ts +2 -0
  191. package/dist/types/utils/abi/contracts/index.d.ts.map +1 -0
  192. package/dist/types/utils/abi/typechain/Multicall3.d.ts +293 -0
  193. package/dist/types/utils/abi/typechain/Multicall3.d.ts.map +1 -0
  194. package/dist/types/utils/abi/typechain/common.d.ts +22 -0
  195. package/dist/types/utils/abi/typechain/common.d.ts.map +1 -0
  196. package/dist/types/utils/abi/typechain/factories/Multicall3__factory.d.ts +340 -0
  197. package/dist/types/utils/abi/typechain/factories/Multicall3__factory.d.ts.map +1 -0
  198. package/dist/types/utils/abi/typechain/factories/index.d.ts +2 -0
  199. package/dist/types/utils/abi/typechain/factories/index.d.ts.map +1 -0
  200. package/dist/types/utils/abi/typechain/index.d.ts +4 -0
  201. package/dist/types/utils/abi/typechain/index.d.ts.map +1 -0
  202. package/package.json +6 -8
  203. package/src/clients/BundleDataClient/BundleDataClient.ts +1311 -0
  204. package/src/clients/BundleDataClient/index.ts +2 -0
  205. package/src/clients/BundleDataClient/utils/DataworkerUtils.ts +268 -0
  206. package/src/clients/BundleDataClient/utils/FillUtils.ts +46 -0
  207. package/src/clients/BundleDataClient/utils/MerkleTreeUtils.ts +26 -0
  208. package/src/clients/BundleDataClient/utils/PoolRebalanceUtils.ts +238 -0
  209. package/src/clients/BundleDataClient/utils/SuperstructUtils.ts +132 -0
  210. package/src/clients/BundleDataClient/utils/index.ts +6 -0
  211. package/src/clients/BundleDataClient/utils/shims.ts +10 -0
  212. package/src/clients/index.ts +1 -0
  213. package/src/interfaces/BundleData.ts +68 -0
  214. package/src/interfaces/index.ts +1 -0
  215. package/src/providers/alchemy.ts +6 -6
  216. package/src/providers/drpc.ts +19 -0
  217. package/src/providers/infura.ts +6 -6
  218. package/src/providers/types.ts +1 -1
  219. package/src/providers/utils.ts +3 -1
  220. package/src/utils/AddressUtils.ts +15 -1
  221. package/src/utils/ContractUtils.ts +8 -0
  222. package/src/utils/Multicall.ts +38 -30
  223. package/src/utils/ObjectUtils.ts +23 -0
  224. package/src/utils/abi/contracts/index.ts +1 -0
  225. package/src/utils/abi/typechain/Multicall3.ts +433 -0
  226. package/src/utils/abi/typechain/common.ts +30 -0
  227. package/src/utils/abi/typechain/factories/Multicall3__factory.ts +458 -0
  228. package/src/utils/abi/typechain/factories/index.ts +4 -0
  229. package/src/utils/abi/typechain/index.ts +6 -0
@@ -0,0 +1,1097 @@
1
+ import { __assign, __awaiter, __generator } from "tslib";
2
+ import _ from "lodash";
3
+ import { FillType, FillStatus, } from "../../interfaces";
4
+ import { bnZero, queryHistoricalDepositForFill, assign, assert, fixedPointAdjustment, isDefined, toBN, forEachAsync, getBlockRangeForChain, getImpliedBundleBlockRanges, isSlowFill, mapAsync, relayFillStatus, bnUint32Max, } from "../../utils";
5
+ import { BigNumber } from "ethers";
6
+ import { _buildPoolRebalanceRoot, BundleDataSS, getEndBlockBuffers, getRefundInformationFromFill, getRefundsFromBundle, getWidestPossibleExpectedBlockRange, isChainDisabled, prettyPrintV3SpokePoolEvents, } from "./utils";
7
+ // max(uint256) - 1
8
+ export var INFINITE_FILL_DEADLINE = bnUint32Max;
9
+ // V3 dictionary helper functions
10
+ function updateExpiredDepositsV3(dict, deposit) {
11
+ var _a;
12
+ var originChainId = deposit.originChainId, inputToken = deposit.inputToken;
13
+ if (!((_a = dict === null || dict === void 0 ? void 0 : dict[originChainId]) === null || _a === void 0 ? void 0 : _a[inputToken])) {
14
+ assign(dict, [originChainId, inputToken], []);
15
+ }
16
+ dict[originChainId][inputToken].push(deposit);
17
+ }
18
+ function updateBundleDepositsV3(dict, deposit) {
19
+ var _a;
20
+ var originChainId = deposit.originChainId, inputToken = deposit.inputToken;
21
+ if (!((_a = dict === null || dict === void 0 ? void 0 : dict[originChainId]) === null || _a === void 0 ? void 0 : _a[inputToken])) {
22
+ assign(dict, [originChainId, inputToken], []);
23
+ }
24
+ dict[originChainId][inputToken].push(deposit);
25
+ }
26
+ function updateBundleFillsV3(dict, fill, lpFeePct, repaymentChainId, repaymentToken) {
27
+ var _a, _b;
28
+ if (!((_a = dict === null || dict === void 0 ? void 0 : dict[repaymentChainId]) === null || _a === void 0 ? void 0 : _a[repaymentToken])) {
29
+ assign(dict, [repaymentChainId, repaymentToken], {
30
+ fills: [],
31
+ totalRefundAmount: bnZero,
32
+ realizedLpFees: bnZero,
33
+ refunds: {},
34
+ });
35
+ }
36
+ var bundleFill = __assign(__assign({}, fill), { lpFeePct: lpFeePct });
37
+ // Add all fills, slow and fast, to dictionary.
38
+ assign(dict, [repaymentChainId, repaymentToken, "fills"], [bundleFill]);
39
+ // All fills update the bundle LP fees.
40
+ var refundObj = dict[repaymentChainId][repaymentToken];
41
+ var realizedLpFee = fill.inputAmount.mul(bundleFill.lpFeePct).div(fixedPointAdjustment);
42
+ refundObj.realizedLpFees = refundObj.realizedLpFees ? refundObj.realizedLpFees.add(realizedLpFee) : realizedLpFee;
43
+ // Only fast fills get refunded.
44
+ if (!isSlowFill(fill)) {
45
+ var refundAmount = fill.inputAmount.mul(fixedPointAdjustment.sub(lpFeePct)).div(fixedPointAdjustment);
46
+ refundObj.totalRefundAmount = refundObj.totalRefundAmount
47
+ ? refundObj.totalRefundAmount.add(refundAmount)
48
+ : refundAmount;
49
+ // Instantiate dictionary if it doesn't exist.
50
+ (_b = refundObj.refunds) !== null && _b !== void 0 ? _b : (refundObj.refunds = {});
51
+ if (refundObj.refunds[fill.relayer]) {
52
+ refundObj.refunds[fill.relayer] = refundObj.refunds[fill.relayer].add(refundAmount);
53
+ }
54
+ else {
55
+ refundObj.refunds[fill.relayer] = refundAmount;
56
+ }
57
+ }
58
+ }
59
+ function updateBundleExcessSlowFills(dict, deposit) {
60
+ var _a;
61
+ var destinationChainId = deposit.destinationChainId, outputToken = deposit.outputToken;
62
+ if (!((_a = dict === null || dict === void 0 ? void 0 : dict[destinationChainId]) === null || _a === void 0 ? void 0 : _a[outputToken])) {
63
+ assign(dict, [destinationChainId, outputToken], []);
64
+ }
65
+ dict[destinationChainId][outputToken].push(deposit);
66
+ }
67
+ function updateBundleSlowFills(dict, deposit) {
68
+ var _a;
69
+ var destinationChainId = deposit.destinationChainId, outputToken = deposit.outputToken;
70
+ if (!((_a = dict === null || dict === void 0 ? void 0 : dict[destinationChainId]) === null || _a === void 0 ? void 0 : _a[outputToken])) {
71
+ assign(dict, [destinationChainId, outputToken], []);
72
+ }
73
+ dict[destinationChainId][outputToken].push(deposit);
74
+ }
75
+ // @notice Shared client for computing data needed to construct or validate a bundle.
76
+ var BundleDataClient = /** @class */ (function () {
77
+ // eslint-disable-next-line no-useless-constructor
78
+ function BundleDataClient(logger, clients, spokePoolClients, chainIdListForBundleEvaluationBlockNumbers, blockRangeEndBlockBuffer) {
79
+ if (blockRangeEndBlockBuffer === void 0) { blockRangeEndBlockBuffer = {}; }
80
+ this.logger = logger;
81
+ this.clients = clients;
82
+ this.spokePoolClients = spokePoolClients;
83
+ this.chainIdListForBundleEvaluationBlockNumbers = chainIdListForBundleEvaluationBlockNumbers;
84
+ this.blockRangeEndBlockBuffer = blockRangeEndBlockBuffer;
85
+ this.loadDataCache = {};
86
+ this.arweaveDataCache = {};
87
+ this.bundleTimestampCache = {};
88
+ }
89
+ // This should be called whenever it's possible that the loadData information for a block range could have changed.
90
+ // For instance, if the spoke or hub clients have been updated, it probably makes sense to clear this to be safe.
91
+ BundleDataClient.prototype.clearCache = function () {
92
+ this.loadDataCache = {};
93
+ };
94
+ BundleDataClient.prototype.loadDataFromCache = function (key) {
95
+ return __awaiter(this, void 0, void 0, function () {
96
+ var _a, _b;
97
+ return __generator(this, function (_c) {
98
+ switch (_c.label) {
99
+ case 0:
100
+ _b = (_a = _).cloneDeep;
101
+ return [4 /*yield*/, this.loadDataCache[key]];
102
+ case 1:
103
+ // Always return a deep cloned copy of object stored in cache. Since JS passes by reference instead of value, we
104
+ // want to minimize the risk that the programmer accidentally mutates data in the cache.
105
+ return [2 /*return*/, _b.apply(_a, [_c.sent()])];
106
+ }
107
+ });
108
+ });
109
+ };
110
+ BundleDataClient.prototype.getBundleTimestampsFromCache = function (key) {
111
+ if (this.bundleTimestampCache[key]) {
112
+ return _.cloneDeep(this.bundleTimestampCache[key]);
113
+ }
114
+ return undefined;
115
+ };
116
+ BundleDataClient.prototype.setBundleTimestampsInCache = function (key, timestamps) {
117
+ this.bundleTimestampCache[key] = timestamps;
118
+ };
119
+ BundleDataClient.prototype.getArweaveClientKey = function (blockRangesForChains) {
120
+ return "bundles-".concat(blockRangesForChains);
121
+ };
122
+ BundleDataClient.prototype.loadPersistedDataFromArweave = function (blockRangesForChains) {
123
+ var _a;
124
+ return __awaiter(this, void 0, void 0, function () {
125
+ var start, persistedData, convertTypedStringRecordIntoNumericRecord, data, bundleData;
126
+ return __generator(this, function (_b) {
127
+ switch (_b.label) {
128
+ case 0:
129
+ if (!isDefined((_a = this.clients) === null || _a === void 0 ? void 0 : _a.arweaveClient)) {
130
+ return [2 /*return*/, undefined];
131
+ }
132
+ start = performance.now();
133
+ return [4 /*yield*/, this.clients.arweaveClient.getByTopic(this.getArweaveClientKey(blockRangesForChains), BundleDataSS)];
134
+ case 1:
135
+ persistedData = _b.sent();
136
+ // If there is no data or the data is empty, return undefined because we couldn't
137
+ // pull info from the Arweave persistence layer.
138
+ if (!isDefined(persistedData) || persistedData.length < 1) {
139
+ return [2 /*return*/, undefined];
140
+ }
141
+ convertTypedStringRecordIntoNumericRecord = function (data) {
142
+ return Object.keys(data).reduce(function (acc, chainId) {
143
+ acc[Number(chainId)] = data[chainId];
144
+ return acc;
145
+ }, {});
146
+ };
147
+ data = persistedData[0].data;
148
+ bundleData = {
149
+ bundleFillsV3: convertTypedStringRecordIntoNumericRecord(data.bundleFillsV3),
150
+ expiredDepositsToRefundV3: convertTypedStringRecordIntoNumericRecord(data.expiredDepositsToRefundV3),
151
+ bundleDepositsV3: convertTypedStringRecordIntoNumericRecord(data.bundleDepositsV3),
152
+ unexecutableSlowFills: convertTypedStringRecordIntoNumericRecord(data.unexecutableSlowFills),
153
+ bundleSlowFillsV3: convertTypedStringRecordIntoNumericRecord(data.bundleSlowFillsV3),
154
+ };
155
+ this.logger.debug({
156
+ at: "BundleDataClient#loadPersistedDataFromArweave",
157
+ message: "Loaded persisted data from Arweave in ".concat(Math.round(performance.now() - start) / 1000, "s."),
158
+ blockRanges: JSON.stringify(blockRangesForChains),
159
+ bundleData: prettyPrintV3SpokePoolEvents(bundleData.bundleDepositsV3, bundleData.bundleFillsV3, [], // Invalid fills are not persisted to Arweave.
160
+ bundleData.bundleSlowFillsV3, bundleData.expiredDepositsToRefundV3, bundleData.unexecutableSlowFills),
161
+ });
162
+ return [2 /*return*/, bundleData];
163
+ }
164
+ });
165
+ });
166
+ };
167
+ // @dev This function should probably be moved to the InventoryClient since it bypasses loadData completely now.
168
+ BundleDataClient.prototype.getPendingRefundsFromValidBundles = function () {
169
+ return __awaiter(this, void 0, void 0, function () {
170
+ var refunds, bundle, _a, _b;
171
+ return __generator(this, function (_c) {
172
+ switch (_c.label) {
173
+ case 0:
174
+ refunds = [];
175
+ if (!this.clients.hubPoolClient.isUpdated) {
176
+ throw new Error("BundleDataClient::getPendingRefundsFromValidBundles HubPoolClient not updated.");
177
+ }
178
+ bundle = this.clients.hubPoolClient.getLatestFullyExecutedRootBundle(this.clients.hubPoolClient.latestBlockSearched);
179
+ if (!(bundle !== undefined)) return [3 /*break*/, 2];
180
+ _b = (_a = refunds).push;
181
+ return [4 /*yield*/, this.getPendingRefundsFromBundle(bundle)];
182
+ case 1:
183
+ _b.apply(_a, [_c.sent()]);
184
+ _c.label = 2;
185
+ case 2: // No more valid bundles in history!
186
+ return [2 /*return*/, refunds];
187
+ }
188
+ });
189
+ });
190
+ };
191
+ // @dev This function should probably be moved to the InventoryClient since it bypasses loadData completely now.
192
+ // Return refunds from input bundle.
193
+ BundleDataClient.prototype.getPendingRefundsFromBundle = function (bundle) {
194
+ return __awaiter(this, void 0, void 0, function () {
195
+ var nextBundleMainnetStartBlock, chainIds, bundleEvaluationBlockRanges, combinedRefunds, arweaveData, bundleFillsV3, expiredDepositsToRefundV3;
196
+ var _this = this;
197
+ return __generator(this, function (_a) {
198
+ switch (_a.label) {
199
+ case 0:
200
+ nextBundleMainnetStartBlock = this.clients.hubPoolClient.getNextBundleStartBlockNumber(this.chainIdListForBundleEvaluationBlockNumbers, this.clients.hubPoolClient.latestBlockSearched, this.clients.hubPoolClient.chainId);
201
+ chainIds = this.clients.configStoreClient.getChainIdIndicesForBlock(nextBundleMainnetStartBlock);
202
+ bundleEvaluationBlockRanges = getImpliedBundleBlockRanges(this.clients.hubPoolClient, this.clients.configStoreClient, bundle);
203
+ return [4 /*yield*/, this.loadArweaveData(bundleEvaluationBlockRanges)];
204
+ case 1:
205
+ arweaveData = _a.sent();
206
+ if (arweaveData === undefined) {
207
+ combinedRefunds = this.getApproximateRefundsForBlockRange(chainIds, bundleEvaluationBlockRanges);
208
+ }
209
+ else {
210
+ bundleFillsV3 = arweaveData.bundleFillsV3, expiredDepositsToRefundV3 = arweaveData.expiredDepositsToRefundV3;
211
+ combinedRefunds = getRefundsFromBundle(bundleFillsV3, expiredDepositsToRefundV3);
212
+ // If we don't have a spoke pool client for a chain, then we won't be able to deduct refunds correctly for this
213
+ // chain. For most of the pending bundle's liveness period, these past refunds are already executed so this is
214
+ // a reasonable assumption. This empty refund chain also matches what the alternative
215
+ // `getApproximateRefundsForBlockRange` would return.
216
+ Object.keys(combinedRefunds).forEach(function (chainId) {
217
+ if (_this.spokePoolClients[Number(chainId)] === undefined) {
218
+ delete combinedRefunds[Number(chainId)];
219
+ }
220
+ });
221
+ }
222
+ // The latest proposed bundle's refund leaves might have already been partially or entirely executed.
223
+ // We have to deduct the executed amounts from the total refund amounts.
224
+ return [2 /*return*/, this.deductExecutedRefunds(combinedRefunds, bundle)];
225
+ }
226
+ });
227
+ });
228
+ };
229
+ // @dev This helper function should probably be moved to the InventoryClient
230
+ BundleDataClient.prototype.getApproximateRefundsForBlockRange = function (chainIds, blockRanges) {
231
+ var _this = this;
232
+ var refundsForChain = {};
233
+ var _loop_1 = function (chainId) {
234
+ if (this_1.spokePoolClients[chainId] === undefined) {
235
+ return "continue";
236
+ }
237
+ var chainIndex = chainIds.indexOf(chainId);
238
+ this_1.spokePoolClients[chainId]
239
+ .getFills()
240
+ .filter(function (fill) {
241
+ if (fill.blockNumber < blockRanges[chainIndex][0] || fill.blockNumber > blockRanges[chainIndex][1]) {
242
+ return false;
243
+ }
244
+ // If origin spoke pool client isn't defined, we can't validate it.
245
+ if (_this.spokePoolClients[fill.originChainId] === undefined) {
246
+ return false;
247
+ }
248
+ var matchingDeposit = _this.spokePoolClients[fill.originChainId].getDeposit(fill.depositId);
249
+ var hasMatchingDeposit = matchingDeposit !== undefined &&
250
+ _this.getRelayHashFromEvent(fill) === _this.getRelayHashFromEvent(matchingDeposit);
251
+ return hasMatchingDeposit;
252
+ })
253
+ .forEach(function (fill) {
254
+ var _a, _b, _c;
255
+ var _d;
256
+ var matchingDeposit = _this.spokePoolClients[fill.originChainId].getDeposit(fill.depositId);
257
+ assert(isDefined(matchingDeposit), "Deposit not found for fill.");
258
+ var _e = getRefundInformationFromFill(fill, _this.clients.hubPoolClient, blockRanges, _this.chainIdListForBundleEvaluationBlockNumbers, matchingDeposit.fromLiteChain // Use ! because we've already asserted that matchingDeposit is defined.
259
+ ), chainToSendRefundTo = _e.chainToSendRefundTo, repaymentToken = _e.repaymentToken;
260
+ // Assume that lp fees are 0 for the sake of speed. In the future we could batch compute
261
+ // these or make hardcoded assumptions based on the origin-repayment chain direction. This might result
262
+ // in slight over estimations of refunds, but its not clear whether underestimating or overestimating is
263
+ // worst from the relayer's perspective.
264
+ var relayer = fill.relayer, refundAmount = fill.inputAmount;
265
+ (_a = refundsForChain[chainToSendRefundTo]) !== null && _a !== void 0 ? _a : (refundsForChain[chainToSendRefundTo] = {});
266
+ (_b = (_d = refundsForChain[chainToSendRefundTo])[repaymentToken]) !== null && _b !== void 0 ? _b : (_d[repaymentToken] = {});
267
+ var existingRefundAmount = (_c = refundsForChain[chainToSendRefundTo][repaymentToken][relayer]) !== null && _c !== void 0 ? _c : bnZero;
268
+ refundsForChain[chainToSendRefundTo][repaymentToken][relayer] = existingRefundAmount.add(refundAmount);
269
+ });
270
+ };
271
+ var this_1 = this;
272
+ for (var _i = 0, chainIds_1 = chainIds; _i < chainIds_1.length; _i++) {
273
+ var chainId = chainIds_1[_i];
274
+ _loop_1(chainId);
275
+ }
276
+ return refundsForChain;
277
+ };
278
+ BundleDataClient.prototype.getUpcomingDepositAmount = function (chainId, l2Token, latestBlockToSearch) {
279
+ if (this.spokePoolClients[chainId] === undefined) {
280
+ return toBN(0);
281
+ }
282
+ return this.spokePoolClients[chainId]
283
+ .getDeposits()
284
+ .filter(function (deposit) { return deposit.blockNumber > latestBlockToSearch && deposit.inputToken === l2Token; })
285
+ .reduce(function (acc, deposit) {
286
+ return acc.add(deposit.inputAmount);
287
+ }, toBN(0));
288
+ };
289
+ BundleDataClient.prototype.getLatestProposedBundleData = function () {
290
+ return __awaiter(this, void 0, void 0, function () {
291
+ var hubPoolClient, bundleBlockRanges;
292
+ var _a;
293
+ return __generator(this, function (_b) {
294
+ switch (_b.label) {
295
+ case 0:
296
+ hubPoolClient = this.clients.hubPoolClient;
297
+ bundleBlockRanges = getImpliedBundleBlockRanges(hubPoolClient, this.clients.configStoreClient, hubPoolClient.hasPendingProposal()
298
+ ? hubPoolClient.getLatestProposedRootBundle()
299
+ : hubPoolClient.getLatestFullyExecutedRootBundle(hubPoolClient.latestBlockSearched) // ! because we know there is a bundle
300
+ );
301
+ _a = {
302
+ blockRanges: bundleBlockRanges
303
+ };
304
+ return [4 /*yield*/, this.loadData(bundleBlockRanges, this.spokePoolClients, true // this bundle data should have been published to arweave
305
+ )];
306
+ case 1: return [2 /*return*/, (_a.bundleData = _b.sent(),
307
+ _a)];
308
+ }
309
+ });
310
+ });
311
+ };
312
+ BundleDataClient.prototype.getLatestPoolRebalanceRoot = function () {
313
+ return __awaiter(this, void 0, void 0, function () {
314
+ var _a, bundleData, blockRanges, hubPoolClient, root;
315
+ return __generator(this, function (_b) {
316
+ switch (_b.label) {
317
+ case 0: return [4 /*yield*/, this.getLatestProposedBundleData()];
318
+ case 1:
319
+ _a = _b.sent(), bundleData = _a.bundleData, blockRanges = _a.blockRanges;
320
+ hubPoolClient = this.clients.hubPoolClient;
321
+ return [4 /*yield*/, _buildPoolRebalanceRoot(hubPoolClient.latestBlockSearched, blockRanges[0][1], bundleData.bundleDepositsV3, bundleData.bundleFillsV3, bundleData.bundleSlowFillsV3, bundleData.unexecutableSlowFills, bundleData.expiredDepositsToRefundV3, {
322
+ hubPoolClient: hubPoolClient,
323
+ configStoreClient: hubPoolClient.configStoreClient,
324
+ })];
325
+ case 2:
326
+ root = _b.sent();
327
+ return [2 /*return*/, {
328
+ root: root,
329
+ blockRanges: blockRanges,
330
+ }];
331
+ }
332
+ });
333
+ });
334
+ };
335
+ // @dev This function should probably be moved to the InventoryClient since it bypasses loadData completely now.
336
+ // Return refunds from the next valid bundle. This will contain any refunds that have been sent but are not included
337
+ // in a valid bundle with all of its leaves executed. This contains refunds from:
338
+ // - Bundles that passed liveness but have not had all of their pool rebalance leaves executed.
339
+ // - Bundles that are pending liveness
340
+ // - Fills sent after the pending, but not validated, bundle
341
+ BundleDataClient.prototype.getNextBundleRefunds = function () {
342
+ return __awaiter(this, void 0, void 0, function () {
343
+ // Return block ranges for blocks after _pendingBlockRanges and up to widestBlockRanges.
344
+ // If a chain is disabled or doesn't have a spoke pool client, return a range of 0
345
+ function getBlockRangeDelta(_pendingBlockRanges) {
346
+ return widestBundleBlockRanges.map(function (blockRange, index) {
347
+ var _a;
348
+ // If pending block range doesn't have an entry for the widest range, which is possible when a new chain
349
+ // is added to the CHAIN_ID_INDICES list, then simply set the initial block range to the widest block range.
350
+ // This will produce a block range delta of 0 where the returned range for this chain is [widest[1], widest[1]].
351
+ var initialBlockRange = (_a = _pendingBlockRanges[index]) !== null && _a !== void 0 ? _a : blockRange;
352
+ // If chain is disabled, return disabled range
353
+ if (initialBlockRange[0] === initialBlockRange[1]) {
354
+ return initialBlockRange;
355
+ }
356
+ // If pending bundle end block exceeds widest end block or if widest end block is undefined
357
+ // (which is possible if the spoke pool client for the chain is not defined), return an empty range since there are no
358
+ // "new" events to consider for this chain.
359
+ if (!isDefined(blockRange[1]) || initialBlockRange[1] >= blockRange[1]) {
360
+ return [initialBlockRange[1], initialBlockRange[1]];
361
+ }
362
+ // If initialBlockRange][0] > widestBlockRange[0], then we'll ignore any blocks
363
+ // between initialBlockRange[0] and widestBlockRange[0] (inclusive) for simplicity reasons. In practice
364
+ // this should not happen.
365
+ return [initialBlockRange[1] + 1, blockRange[1]];
366
+ });
367
+ }
368
+ var hubPoolClient, nextBundleMainnetStartBlock, chainIds, combinedRefunds, widestBundleBlockRanges, pendingBundleBlockRanges, arweaveData, bundleFillsV3, expiredDepositsToRefundV3, start;
369
+ return __generator(this, function (_a) {
370
+ switch (_a.label) {
371
+ case 0:
372
+ hubPoolClient = this.clients.hubPoolClient;
373
+ nextBundleMainnetStartBlock = hubPoolClient.getNextBundleStartBlockNumber(this.chainIdListForBundleEvaluationBlockNumbers, hubPoolClient.latestBlockSearched, hubPoolClient.chainId);
374
+ chainIds = this.clients.configStoreClient.getChainIdIndicesForBlock(nextBundleMainnetStartBlock);
375
+ combinedRefunds = [];
376
+ widestBundleBlockRanges = getWidestPossibleExpectedBlockRange(chainIds, this.spokePoolClients, getEndBlockBuffers(chainIds, this.blockRangeEndBlockBuffer), this.clients, this.clients.hubPoolClient.latestBlockSearched, this.clients.configStoreClient.getEnabledChains(this.clients.hubPoolClient.latestBlockSearched));
377
+ if (!hubPoolClient.hasPendingProposal()) return [3 /*break*/, 2];
378
+ pendingBundleBlockRanges = getImpliedBundleBlockRanges(hubPoolClient, this.clients.configStoreClient, hubPoolClient.getLatestProposedRootBundle());
379
+ return [4 /*yield*/, this.loadArweaveData(pendingBundleBlockRanges)];
380
+ case 1:
381
+ arweaveData = _a.sent();
382
+ if (arweaveData === undefined) {
383
+ combinedRefunds.push(this.getApproximateRefundsForBlockRange(chainIds, pendingBundleBlockRanges));
384
+ }
385
+ else {
386
+ bundleFillsV3 = arweaveData.bundleFillsV3, expiredDepositsToRefundV3 = arweaveData.expiredDepositsToRefundV3;
387
+ combinedRefunds.push(getRefundsFromBundle(bundleFillsV3, expiredDepositsToRefundV3));
388
+ }
389
+ // Shorten the widestBundleBlockRanges now to not double count the pending bundle blocks.
390
+ widestBundleBlockRanges = getBlockRangeDelta(pendingBundleBlockRanges);
391
+ _a.label = 2;
392
+ case 2:
393
+ start = performance.now();
394
+ combinedRefunds.push(this.getApproximateRefundsForBlockRange(chainIds, widestBundleBlockRanges));
395
+ this.logger.debug({
396
+ at: "BundleDataClient#getNextBundleRefunds",
397
+ message: "Loading approximate refunds for next bundle in ".concat(Math.round(performance.now() - start) / 1000, "s."),
398
+ blockRanges: JSON.stringify(widestBundleBlockRanges),
399
+ });
400
+ return [2 /*return*/, combinedRefunds];
401
+ }
402
+ });
403
+ });
404
+ };
405
+ // @dev This helper function should probably be moved to the InventoryClient
406
+ BundleDataClient.prototype.getExecutedRefunds = function (spokePoolClient, relayerRefundRoot) {
407
+ if (!isDefined(spokePoolClient)) {
408
+ return {};
409
+ }
410
+ // @dev Search from right to left since there can be multiple root bundles with the same relayer refund root.
411
+ // The caller should take caution if they're trying to use this function to find matching refunds for older
412
+ // root bundles as opposed to more recent ones.
413
+ var bundle = _.findLast(spokePoolClient.getRootBundleRelays(), function (bundle) { return bundle.relayerRefundRoot === relayerRefundRoot; });
414
+ if (bundle === undefined) {
415
+ return {};
416
+ }
417
+ var executedRefundLeaves = spokePoolClient
418
+ .getRelayerRefundExecutions()
419
+ .filter(function (leaf) { return leaf.rootBundleId === bundle.rootBundleId; });
420
+ var executedRefunds = {};
421
+ for (var _i = 0, executedRefundLeaves_1 = executedRefundLeaves; _i < executedRefundLeaves_1.length; _i++) {
422
+ var refundLeaf = executedRefundLeaves_1[_i];
423
+ var tokenAddress = refundLeaf.l2TokenAddress;
424
+ if (executedRefunds[tokenAddress] === undefined) {
425
+ executedRefunds[tokenAddress] = {};
426
+ }
427
+ var executedTokenRefunds = executedRefunds[tokenAddress];
428
+ for (var i = 0; i < refundLeaf.refundAddresses.length; i++) {
429
+ var relayer = refundLeaf.refundAddresses[i];
430
+ var refundAmount = refundLeaf.refundAmounts[i];
431
+ if (executedTokenRefunds[relayer] === undefined) {
432
+ executedTokenRefunds[relayer] = bnZero;
433
+ }
434
+ executedTokenRefunds[relayer] = executedTokenRefunds[relayer].add(refundAmount);
435
+ }
436
+ }
437
+ return executedRefunds;
438
+ };
439
+ // @dev This helper function should probably be moved to the InventoryClient
440
+ BundleDataClient.prototype.deductExecutedRefunds = function (allRefunds, bundleContainingRefunds) {
441
+ for (var _i = 0, _a = Object.keys(allRefunds); _i < _a.length; _i++) {
442
+ var chainIdStr = _a[_i];
443
+ var chainId = Number(chainIdStr);
444
+ if (!isDefined(this.spokePoolClients[chainId])) {
445
+ continue;
446
+ }
447
+ var executedRefunds = this.getExecutedRefunds(this.spokePoolClients[chainId], bundleContainingRefunds.relayerRefundRoot);
448
+ for (var _b = 0, _c = Object.keys(allRefunds[chainId]); _b < _c.length; _b++) {
449
+ var tokenAddress = _c[_b];
450
+ var refunds = allRefunds[chainId][tokenAddress];
451
+ if (executedRefunds[tokenAddress] === undefined || refunds === undefined) {
452
+ continue;
453
+ }
454
+ for (var _d = 0, _e = Object.keys(refunds); _d < _e.length; _d++) {
455
+ var relayer = _e[_d];
456
+ var executedAmount = executedRefunds[tokenAddress][relayer];
457
+ if (executedAmount === undefined) {
458
+ continue;
459
+ }
460
+ // Since there should only be a single executed relayer refund leaf for each relayer-token-chain combination,
461
+ // we can deduct this refund and mark it as executed if the executed amount is > 0.
462
+ refunds[relayer] = bnZero;
463
+ }
464
+ }
465
+ }
466
+ return allRefunds;
467
+ };
468
+ BundleDataClient.prototype.getRefundsFor = function (bundleRefunds, relayer, chainId, token) {
469
+ if (!bundleRefunds[chainId] || !bundleRefunds[chainId][token]) {
470
+ return BigNumber.from(0);
471
+ }
472
+ var allRefunds = bundleRefunds[chainId][token];
473
+ return allRefunds && allRefunds[relayer] ? allRefunds[relayer] : BigNumber.from(0);
474
+ };
475
+ BundleDataClient.prototype.getTotalRefund = function (refunds, relayer, chainId, refundToken) {
476
+ var _this = this;
477
+ return refunds.reduce(function (totalRefund, refunds) {
478
+ return totalRefund.add(_this.getRefundsFor(refunds, relayer, chainId, refundToken));
479
+ }, bnZero);
480
+ };
481
+ BundleDataClient.prototype.loadArweaveData = function (blockRangesForChains) {
482
+ return __awaiter(this, void 0, void 0, function () {
483
+ var arweaveKey, arweaveData, _a, _b;
484
+ return __generator(this, function (_c) {
485
+ switch (_c.label) {
486
+ case 0:
487
+ arweaveKey = this.getArweaveClientKey(blockRangesForChains);
488
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
489
+ if (!this.arweaveDataCache[arweaveKey]) {
490
+ this.arweaveDataCache[arweaveKey] = this.loadPersistedDataFromArweave(blockRangesForChains);
491
+ }
492
+ _b = (_a = _).cloneDeep;
493
+ return [4 /*yield*/, this.arweaveDataCache[arweaveKey]];
494
+ case 1:
495
+ arweaveData = _b.apply(_a, [_c.sent()]);
496
+ return [2 /*return*/, arweaveData];
497
+ }
498
+ });
499
+ });
500
+ };
501
+ // Common data re-formatting logic shared across all data worker public functions.
502
+ // User must pass in spoke pool to search event data against. This allows the user to refund relays and fill deposits
503
+ // on deprecated spoke pools.
504
+ BundleDataClient.prototype.loadData = function (blockRangesForChains, spokePoolClients, attemptArweaveLoad) {
505
+ if (attemptArweaveLoad === void 0) { attemptArweaveLoad = false; }
506
+ return __awaiter(this, void 0, void 0, function () {
507
+ var key, arweaveData, data;
508
+ return __generator(this, function (_a) {
509
+ switch (_a.label) {
510
+ case 0:
511
+ key = JSON.stringify(blockRangesForChains);
512
+ if (!!this.loadDataCache[key]) return [3 /*break*/, 4];
513
+ arweaveData = void 0;
514
+ if (!attemptArweaveLoad) return [3 /*break*/, 2];
515
+ return [4 /*yield*/, this.loadArweaveData(blockRangesForChains)];
516
+ case 1:
517
+ arweaveData = _a.sent();
518
+ return [3 /*break*/, 3];
519
+ case 2:
520
+ arweaveData = undefined;
521
+ _a.label = 3;
522
+ case 3:
523
+ data = isDefined(arweaveData)
524
+ ? // We can return the data to a Promise to keep the return type consistent.
525
+ // Note: this is now a fast operation since we've already loaded the data from Arweave.
526
+ Promise.resolve(arweaveData)
527
+ : this.loadDataFromScratch(blockRangesForChains, spokePoolClients);
528
+ this.loadDataCache[key] = data;
529
+ _a.label = 4;
530
+ case 4: return [2 /*return*/, this.loadDataFromCache(key)];
531
+ }
532
+ });
533
+ });
534
+ };
535
+ BundleDataClient.prototype.loadDataFromScratch = function (blockRangesForChains, spokePoolClients) {
536
+ return __awaiter(this, void 0, void 0, function () {
537
+ var start, key, chainIds, bundleDepositsV3, bundleFillsV3, bundleInvalidFillsV3, bundleSlowFillsV3, expiredDepositsToRefundV3, unexecutableSlowFills, _isChainDisabled, allChainIds, _cachedBundleTimestamps, bundleBlockTimestamps, v3RelayHashes, expiredBundleDepositHashes, olderDepositHashes, depositCounter, _loop_2, _i, allChainIds_1, originChainId, validatedBundleV3Fills, validatedBundleSlowFills, validatedBundleUnexecutableSlowFills, fillCounter, _loop_3, _a, allChainIds_2, originChainId, promises, _b, v3FillLpFees, v3SlowFillLpFees, v3UnexecutableSlowFillLpFees, v3SpokeEventsReadable;
538
+ var _this = this;
539
+ return __generator(this, function (_c) {
540
+ switch (_c.label) {
541
+ case 0:
542
+ start = performance.now();
543
+ key = JSON.stringify(blockRangesForChains);
544
+ if (!this.clients.configStoreClient.isUpdated) {
545
+ throw new Error("ConfigStoreClient not updated");
546
+ }
547
+ else if (!this.clients.hubPoolClient.isUpdated) {
548
+ throw new Error("HubPoolClient not updated");
549
+ }
550
+ chainIds = this.clients.configStoreClient.getChainIdIndicesForBlock(blockRangesForChains[0][0]);
551
+ if (blockRangesForChains.length > chainIds.length) {
552
+ throw new Error("Unexpected block range list length of ".concat(blockRangesForChains.length, ", should be <= ").concat(chainIds.length));
553
+ }
554
+ bundleDepositsV3 = {};
555
+ bundleFillsV3 = {};
556
+ bundleInvalidFillsV3 = [];
557
+ bundleSlowFillsV3 = {};
558
+ expiredDepositsToRefundV3 = {};
559
+ unexecutableSlowFills = {};
560
+ _isChainDisabled = function (chainId) {
561
+ var blockRangeForChain = getBlockRangeForChain(blockRangesForChains, chainId, chainIds);
562
+ return isChainDisabled(blockRangeForChain);
563
+ };
564
+ allChainIds = blockRangesForChains
565
+ .map(function (_blockRange, index) { return chainIds[index]; })
566
+ .filter(function (chainId) { return !_isChainDisabled(chainId) && spokePoolClients[chainId] !== undefined; });
567
+ allChainIds.forEach(function (chainId) {
568
+ var spokePoolClient = spokePoolClients[chainId];
569
+ if (!spokePoolClient.isUpdated) {
570
+ throw new Error("SpokePoolClient for chain ".concat(chainId, " not updated."));
571
+ }
572
+ });
573
+ _cachedBundleTimestamps = this.getBundleTimestampsFromCache(key);
574
+ bundleBlockTimestamps = {};
575
+ if (!!_cachedBundleTimestamps) return [3 /*break*/, 2];
576
+ return [4 /*yield*/, this.getBundleBlockTimestamps(chainIds, blockRangesForChains, spokePoolClients)];
577
+ case 1:
578
+ bundleBlockTimestamps = _c.sent();
579
+ this.setBundleTimestampsInCache(key, bundleBlockTimestamps);
580
+ this.logger.debug({
581
+ at: "BundleDataClient#loadData",
582
+ message: "Bundle block timestamps",
583
+ bundleBlockTimestamps: bundleBlockTimestamps,
584
+ blockRangesForChains: JSON.stringify(blockRangesForChains),
585
+ });
586
+ return [3 /*break*/, 3];
587
+ case 2:
588
+ bundleBlockTimestamps = _cachedBundleTimestamps;
589
+ _c.label = 3;
590
+ case 3:
591
+ v3RelayHashes = {};
592
+ expiredBundleDepositHashes = new Set();
593
+ olderDepositHashes = new Set();
594
+ depositCounter = 0;
595
+ _loop_2 = function (originChainId) {
596
+ var originClient = spokePoolClients[originChainId];
597
+ var originChainBlockRange = getBlockRangeForChain(blockRangesForChains, originChainId, chainIds);
598
+ var _loop_4 = function (destinationChainId) {
599
+ if (originChainId === destinationChainId) {
600
+ return "continue";
601
+ }
602
+ originClient.getDepositsForDestinationChain(destinationChainId).forEach(function (deposit) {
603
+ depositCounter++;
604
+ var relayDataHash = _this.getRelayHashFromEvent(deposit);
605
+ if (v3RelayHashes[relayDataHash]) {
606
+ // If we've seen this deposit before, then skip this deposit. This can happen if our RPC provider
607
+ // gives us bad data.
608
+ return;
609
+ }
610
+ // Even if deposit is not in bundle block range, store all deposits we can see in memory in this
611
+ // convenient dictionary.
612
+ v3RelayHashes[relayDataHash] = {
613
+ deposit: deposit,
614
+ fill: undefined,
615
+ slowFillRequest: undefined,
616
+ };
617
+ // If deposit block is within origin chain bundle block range, then save as bundle deposit.
618
+ // If deposit is in bundle and it has expired, additionally save it as an expired deposit.
619
+ // If deposit is not in the bundle block range, then save it as an older deposit that
620
+ // may have expired.
621
+ if (deposit.blockNumber >= originChainBlockRange[0] && deposit.blockNumber <= originChainBlockRange[1]) {
622
+ // Deposit is a V3 deposit in this origin chain's bundle block range and is not a duplicate.
623
+ updateBundleDepositsV3(bundleDepositsV3, deposit);
624
+ // We don't check that fillDeadline >= bundleBlockTimestamps[destinationChainId][0] because
625
+ // that would eliminate any deposits in this bundle with a very low fillDeadline like equal to 0
626
+ // for example. Those should be impossible to create but technically should be included in this
627
+ // bundle of refunded deposits.
628
+ if (deposit.fillDeadline < bundleBlockTimestamps[destinationChainId][1]) {
629
+ expiredBundleDepositHashes.add(relayDataHash);
630
+ }
631
+ }
632
+ else if (deposit.blockNumber < originChainBlockRange[0]) {
633
+ olderDepositHashes.add(relayDataHash);
634
+ }
635
+ });
636
+ };
637
+ for (var _d = 0, allChainIds_3 = allChainIds; _d < allChainIds_3.length; _d++) {
638
+ var destinationChainId = allChainIds_3[_d];
639
+ _loop_4(destinationChainId);
640
+ }
641
+ };
642
+ for (_i = 0, allChainIds_1 = allChainIds; _i < allChainIds_1.length; _i++) {
643
+ originChainId = allChainIds_1[_i];
644
+ _loop_2(originChainId);
645
+ }
646
+ this.logger.debug({
647
+ at: "BundleDataClient#loadData",
648
+ message: "Processed ".concat(depositCounter, " deposits in ").concat(performance.now() - start, "ms."),
649
+ });
650
+ start = performance.now();
651
+ validatedBundleV3Fills = [];
652
+ validatedBundleSlowFills = [];
653
+ validatedBundleUnexecutableSlowFills = [];
654
+ fillCounter = 0;
655
+ _loop_3 = function (originChainId) {
656
+ var originClient, _loop_5, _e, allChainIds_4, destinationChainId;
657
+ return __generator(this, function (_f) {
658
+ switch (_f.label) {
659
+ case 0:
660
+ originClient = spokePoolClients[originChainId];
661
+ _loop_5 = function (destinationChainId) {
662
+ var destinationClient, destinationChainBlockRange, fastFillsReplacingSlowFills;
663
+ return __generator(this, function (_g) {
664
+ switch (_g.label) {
665
+ case 0:
666
+ if (originChainId === destinationChainId) {
667
+ return [2 /*return*/, "continue"];
668
+ }
669
+ destinationClient = spokePoolClients[destinationChainId];
670
+ destinationChainBlockRange = getBlockRangeForChain(blockRangesForChains, destinationChainId, chainIds);
671
+ fastFillsReplacingSlowFills = [];
672
+ return [4 /*yield*/, forEachAsync(destinationClient
673
+ .getFillsForOriginChain(originChainId)
674
+ .filter(function (fill) { return fill.blockNumber <= destinationChainBlockRange[1]; }), function (fill) { return __awaiter(_this, void 0, void 0, function () {
675
+ var relayDataHash, historicalDeposit, matchedDeposit;
676
+ return __generator(this, function (_a) {
677
+ switch (_a.label) {
678
+ case 0:
679
+ relayDataHash = this.getRelayHashFromEvent(fill);
680
+ fillCounter++;
681
+ if (v3RelayHashes[relayDataHash]) {
682
+ if (!v3RelayHashes[relayDataHash].fill) {
683
+ assert(isDefined(v3RelayHashes[relayDataHash].deposit), "Deposit should exist in relay hash dictionary.");
684
+ // At this point, the v3RelayHashes entry already existed meaning that there is a matching deposit,
685
+ // so this fill is validated.
686
+ v3RelayHashes[relayDataHash].fill = fill;
687
+ if (fill.blockNumber >= destinationChainBlockRange[0]) {
688
+ validatedBundleV3Fills.push(__assign(__assign({}, fill), { quoteTimestamp: v3RelayHashes[relayDataHash].deposit.quoteTimestamp }));
689
+ // If fill replaced a slow fill request, then mark it as one that might have created an
690
+ // unexecutable slow fill. We can't know for sure until we check the slow fill request
691
+ // events.
692
+ if (fill.relayExecutionInfo.fillType === FillType.ReplacedSlowFill) {
693
+ fastFillsReplacingSlowFills.push(relayDataHash);
694
+ }
695
+ }
696
+ }
697
+ return [2 /*return*/];
698
+ }
699
+ // At this point, there is no relay hash dictionary entry for this fill, so we need to
700
+ // instantiate the entry.
701
+ v3RelayHashes[relayDataHash] = {
702
+ deposit: undefined,
703
+ fill: fill,
704
+ slowFillRequest: undefined,
705
+ };
706
+ if (!(fill.blockNumber >= destinationChainBlockRange[0])) return [3 /*break*/, 2];
707
+ // Fill has a non-infinite expiry, and we can assume our spoke pool clients have old enough deposits
708
+ // to conclude that this fill is invalid if we haven't found a matching deposit in memory, so
709
+ // skip the historical query.
710
+ if (!INFINITE_FILL_DEADLINE.eq(fill.fillDeadline)) {
711
+ bundleInvalidFillsV3.push(fill);
712
+ return [2 /*return*/];
713
+ }
714
+ return [4 /*yield*/, queryHistoricalDepositForFill(originClient, fill)];
715
+ case 1:
716
+ historicalDeposit = _a.sent();
717
+ if (!historicalDeposit.found) {
718
+ bundleInvalidFillsV3.push(fill);
719
+ }
720
+ else {
721
+ matchedDeposit = historicalDeposit.deposit;
722
+ // @dev Since queryHistoricalDepositForFill validates the fill by checking individual
723
+ // object property values against the deposit's, we
724
+ // sanity check it here by comparing the full relay hashes. If there's an error here then the
725
+ // historical deposit query is not working as expected.
726
+ assert(this.getRelayHashFromEvent(matchedDeposit) === relayDataHash, "Relay hashes should match.");
727
+ validatedBundleV3Fills.push(__assign(__assign({}, fill), { quoteTimestamp: matchedDeposit.quoteTimestamp }));
728
+ v3RelayHashes[relayDataHash].deposit = matchedDeposit;
729
+ if (fill.relayExecutionInfo.fillType === FillType.ReplacedSlowFill) {
730
+ fastFillsReplacingSlowFills.push(relayDataHash);
731
+ }
732
+ }
733
+ _a.label = 2;
734
+ case 2: return [2 /*return*/];
735
+ }
736
+ });
737
+ }); })];
738
+ case 1:
739
+ _g.sent();
740
+ return [4 /*yield*/, forEachAsync(destinationClient
741
+ .getSlowFillRequestsForOriginChain(originChainId)
742
+ .filter(function (request) { return request.blockNumber <= destinationChainBlockRange[1]; }), function (slowFillRequest) { return __awaiter(_this, void 0, void 0, function () {
743
+ var relayDataHash, matchedDeposit, historicalDeposit, matchedDeposit;
744
+ var _a, _b;
745
+ return __generator(this, function (_c) {
746
+ switch (_c.label) {
747
+ case 0:
748
+ relayDataHash = this.getRelayHashFromEvent(slowFillRequest);
749
+ if (v3RelayHashes[relayDataHash]) {
750
+ if (!v3RelayHashes[relayDataHash].slowFillRequest) {
751
+ // At this point, the v3RelayHashes entry already existed meaning that there is either a matching
752
+ // fill or deposit.
753
+ v3RelayHashes[relayDataHash].slowFillRequest = slowFillRequest;
754
+ if (v3RelayHashes[relayDataHash].fill) {
755
+ // If there is a fill matching the relay hash, then this slow fill request can't be used
756
+ // to create a slow fill for a filled deposit.
757
+ return [2 /*return*/];
758
+ }
759
+ assert(isDefined(v3RelayHashes[relayDataHash].deposit), "Deposit should exist in relay hash dictionary.");
760
+ matchedDeposit = v3RelayHashes[relayDataHash].deposit;
761
+ // Input and Output tokens must be equivalent on the deposit for this to be slow filled.
762
+ if (!this.clients.hubPoolClient.areTokensEquivalent(matchedDeposit.inputToken, matchedDeposit.originChainId, matchedDeposit.outputToken, matchedDeposit.destinationChainId, matchedDeposit.quoteBlockNumber)) {
763
+ return [2 /*return*/];
764
+ }
765
+ // slow fill requests for deposits from or to lite chains are considered invalid
766
+ if (((_a = v3RelayHashes[relayDataHash].deposit) === null || _a === void 0 ? void 0 : _a.fromLiteChain) ||
767
+ ((_b = v3RelayHashes[relayDataHash].deposit) === null || _b === void 0 ? void 0 : _b.toLiteChain)) {
768
+ return [2 /*return*/];
769
+ }
770
+ // If there is no fill matching the relay hash, then this might be a valid slow fill request
771
+ // that we should produce a slow fill leaf for. Check if the slow fill request is in the
772
+ // destination chain block range and that the underlying deposit has not expired yet.
773
+ if (slowFillRequest.blockNumber >= destinationChainBlockRange[0] &&
774
+ // Deposit must not have expired in this bundle.
775
+ slowFillRequest.fillDeadline >= bundleBlockTimestamps[destinationChainId][1]) {
776
+ // At this point, the v3RelayHashes entry already existed meaning that there is a matching deposit,
777
+ // so this slow fill request relay data is correct.
778
+ validatedBundleSlowFills.push(matchedDeposit);
779
+ }
780
+ }
781
+ return [2 /*return*/];
782
+ }
783
+ // Instantiate dictionary if there is neither a deposit nor fill matching it.
784
+ v3RelayHashes[relayDataHash] = {
785
+ deposit: undefined,
786
+ fill: undefined,
787
+ slowFillRequest: slowFillRequest,
788
+ };
789
+ if (!(INFINITE_FILL_DEADLINE.eq(slowFillRequest.fillDeadline) &&
790
+ slowFillRequest.blockNumber >= destinationChainBlockRange[0])) return [3 /*break*/, 2];
791
+ return [4 /*yield*/, queryHistoricalDepositForFill(originClient, slowFillRequest)];
792
+ case 1:
793
+ historicalDeposit = _c.sent();
794
+ if (!historicalDeposit.found) {
795
+ // TODO: Invalid slow fill request. Maybe worth logging.
796
+ return [2 /*return*/];
797
+ }
798
+ matchedDeposit = historicalDeposit.deposit;
799
+ // @dev Since queryHistoricalDepositForFill validates the slow fill request by checking individual
800
+ // object property values against the deposit's, we
801
+ // sanity check it here by comparing the full relay hashes. If there's an error here then the
802
+ // historical deposit query is not working as expected.
803
+ assert(this.getRelayHashFromEvent(matchedDeposit) === relayDataHash, "Deposit relay hashes should match.");
804
+ // slow fill requests for deposits from or to lite chains are considered invalid
805
+ if (matchedDeposit.fromLiteChain || matchedDeposit.toLiteChain) {
806
+ return [2 /*return*/];
807
+ }
808
+ v3RelayHashes[relayDataHash].deposit = matchedDeposit;
809
+ // Note: we don't need to query for a historical fill at this point because a fill
810
+ // cannot precede a slow fill request and if the fill came after the slow fill request,
811
+ // we would have seen it already because we would have processed it in the loop above.
812
+ if (
813
+ // Input and Output tokens must be equivalent on the deposit for this to be slow filled.
814
+ !this.clients.hubPoolClient.areTokensEquivalent(matchedDeposit.inputToken, matchedDeposit.originChainId, matchedDeposit.outputToken, matchedDeposit.destinationChainId, matchedDeposit.quoteBlockNumber) ||
815
+ // Deposit must not have expired in this bundle.
816
+ slowFillRequest.fillDeadline < bundleBlockTimestamps[destinationChainId][1]) {
817
+ // TODO: Invalid slow fill request. Maybe worth logging.
818
+ return [2 /*return*/];
819
+ }
820
+ validatedBundleSlowFills.push(matchedDeposit);
821
+ _c.label = 2;
822
+ case 2: return [2 /*return*/];
823
+ }
824
+ });
825
+ }); })];
826
+ case 2:
827
+ _g.sent();
828
+ // For all fills that came after a slow fill request, we can now check if the slow fill request
829
+ // was a valid one and whether it was created in a previous bundle. If so, then it created a slow fill
830
+ // leaf that is now unexecutable.
831
+ fastFillsReplacingSlowFills.forEach(function (relayDataHash) {
832
+ var _a = v3RelayHashes[relayDataHash], deposit = _a.deposit, slowFillRequest = _a.slowFillRequest, fill = _a.fill;
833
+ assert((fill === null || fill === void 0 ? void 0 : fill.relayExecutionInfo.fillType) === FillType.ReplacedSlowFill, "Fill type should be ReplacedSlowFill.");
834
+ // Needed for TSC - are implicitely checking that deposit exists by making it to this point.
835
+ if (!deposit) {
836
+ throw new Error("Deposit should exist in relay hash dictionary.");
837
+ }
838
+ var destinationBlockRange = getBlockRangeForChain(blockRangesForChains, destinationChainId, chainIds);
839
+ if (
840
+ // If the slow fill request that was replaced by this fill was in an older bundle, then we don't
841
+ // need to check if the slow fill request was valid since we can assume all bundles in the past
842
+ // were validated. However, we might as well double check.
843
+ _this.clients.hubPoolClient.areTokensEquivalent(deposit.inputToken, deposit.originChainId, deposit.outputToken, deposit.destinationChainId, deposit.quoteBlockNumber) &&
844
+ // If there is a slow fill request in this bundle that matches the relay hash, then there was no slow fill
845
+ // created that would be considered excess.
846
+ (!slowFillRequest || slowFillRequest.blockNumber < destinationBlockRange[0])) {
847
+ validatedBundleUnexecutableSlowFills.push(deposit);
848
+ }
849
+ });
850
+ return [2 /*return*/];
851
+ }
852
+ });
853
+ };
854
+ _e = 0, allChainIds_4 = allChainIds;
855
+ _f.label = 1;
856
+ case 1:
857
+ if (!(_e < allChainIds_4.length)) return [3 /*break*/, 4];
858
+ destinationChainId = allChainIds_4[_e];
859
+ return [5 /*yield**/, _loop_5(destinationChainId)];
860
+ case 2:
861
+ _f.sent();
862
+ _f.label = 3;
863
+ case 3:
864
+ _e++;
865
+ return [3 /*break*/, 1];
866
+ case 4: return [2 /*return*/];
867
+ }
868
+ });
869
+ };
870
+ _a = 0, allChainIds_2 = allChainIds;
871
+ _c.label = 4;
872
+ case 4:
873
+ if (!(_a < allChainIds_2.length)) return [3 /*break*/, 7];
874
+ originChainId = allChainIds_2[_a];
875
+ return [5 /*yield**/, _loop_3(originChainId)];
876
+ case 5:
877
+ _c.sent();
878
+ _c.label = 6;
879
+ case 6:
880
+ _a++;
881
+ return [3 /*break*/, 4];
882
+ case 7:
883
+ this.logger.debug({
884
+ at: "BundleDataClient#loadData",
885
+ message: "Processed ".concat(fillCounter, " fills in ").concat(performance.now() - start, "ms."),
886
+ });
887
+ start = performance.now();
888
+ // Go through expired deposits in this bundle and now prune those that we have seen a fill for to construct
889
+ // the list of expired deposits we need to refund in this bundle.
890
+ expiredBundleDepositHashes.forEach(function (relayDataHash) {
891
+ var _a = v3RelayHashes[relayDataHash], deposit = _a.deposit, fill = _a.fill;
892
+ assert(isDefined(deposit), "Deposit should exist in relay hash dictionary.");
893
+ if (!fill &&
894
+ isDefined(deposit) // Needed for TSC - we check this above.
895
+ ) {
896
+ updateExpiredDepositsV3(expiredDepositsToRefundV3, deposit);
897
+ }
898
+ });
899
+ // For all deposits older than this bundle, we need to check if they expired in this bundle and if they did,
900
+ // whether there was a slow fill created for it in a previous bundle that is now unexecutable and replaced
901
+ // by a new expired deposit refund.
902
+ return [4 /*yield*/, forEachAsync(Array.from(olderDepositHashes), function (relayDataHash) { return __awaiter(_this, void 0, void 0, function () {
903
+ var _a, deposit, slowFillRequest, fill, destinationChainId, destinationBlockRange, fillStatus;
904
+ return __generator(this, function (_b) {
905
+ switch (_b.label) {
906
+ case 0:
907
+ _a = v3RelayHashes[relayDataHash], deposit = _a.deposit, slowFillRequest = _a.slowFillRequest, fill = _a.fill;
908
+ assert(isDefined(deposit), "Deposit should exist in relay hash dictionary.");
909
+ destinationChainId = deposit.destinationChainId;
910
+ destinationBlockRange = getBlockRangeForChain(blockRangesForChains, destinationChainId, chainIds);
911
+ if (!
912
+ // If there is a valid fill that we saw matching this deposit, then it does not need a refund.
913
+ (!fill &&
914
+ isDefined(deposit) && // Needed for TSC - we check this above.
915
+ deposit.fillDeadline < bundleBlockTimestamps[destinationChainId][1] &&
916
+ deposit.fillDeadline >= bundleBlockTimestamps[destinationChainId][0] &&
917
+ spokePoolClients[destinationChainId] !== undefined))
918
+ // If there is a valid fill that we saw matching this deposit, then it does not need a refund.
919
+ return [3 /*break*/, 2];
920
+ return [4 /*yield*/, relayFillStatus(spokePoolClients[destinationChainId].spokePool, deposit,
921
+ // We can assume that in production
922
+ // the block ranges passed into this function would never contain blocks where the spoke pool client
923
+ // hasn't queried. This is because this function will usually be called
924
+ // in production with block ranges that were validated by
925
+ // DataworkerUtils.blockRangesAreInvalidForSpokeClients
926
+ Math.min(destinationBlockRange[1], spokePoolClients[destinationChainId].latestBlockSearched), destinationChainId)];
927
+ case 1:
928
+ fillStatus = _b.sent();
929
+ // If there is no matching fill and the deposit expired in this bundle and the fill status on-chain is not
930
+ // Filled, then we can to refund it as an expired deposit.
931
+ if (fillStatus !== FillStatus.Filled) {
932
+ updateExpiredDepositsV3(expiredDepositsToRefundV3, deposit);
933
+ }
934
+ // If fill status is RequestedSlowFill, then we might need to mark down an unexecutable
935
+ // slow fill that we're going to replace with an expired deposit refund.
936
+ // If deposit cannot be slow filled, then exit early.
937
+ if (fillStatus !== FillStatus.RequestedSlowFill) {
938
+ return [2 /*return*/];
939
+ }
940
+ // Now, check if there was a slow fill created for this deposit in a previous bundle which would now be
941
+ // unexecutable. Mark this deposit as having created an unexecutable slow fill if there is no matching
942
+ // slow fill request or the matching slow fill request took place in a previous bundle.
943
+ // If there is a slow fill request in this bundle, then the expired deposit refund will supercede
944
+ // the slow fill request. If there is no slow fill request seen or its older than this bundle, then we can
945
+ // assume a slow fill leaf was created for it because its tokens are equivalent. The slow fill request was
946
+ // also sent before the fill deadline expired since we checked that above.
947
+ if (
948
+ // Since this deposit was requested for a slow fill in an older bundle at this point, we don't
949
+ // technically need to check if the slow fill request was valid since we can assume all bundles in the past
950
+ // were validated. However, we might as well double check.
951
+ this.clients.hubPoolClient.areTokensEquivalent(deposit.inputToken, deposit.originChainId, deposit.outputToken, deposit.destinationChainId, deposit.quoteBlockNumber) &&
952
+ (!slowFillRequest || slowFillRequest.blockNumber < destinationBlockRange[0])) {
953
+ validatedBundleUnexecutableSlowFills.push(deposit);
954
+ }
955
+ _b.label = 2;
956
+ case 2: return [2 /*return*/];
957
+ }
958
+ });
959
+ }); })];
960
+ case 8:
961
+ // For all deposits older than this bundle, we need to check if they expired in this bundle and if they did,
962
+ // whether there was a slow fill created for it in a previous bundle that is now unexecutable and replaced
963
+ // by a new expired deposit refund.
964
+ _c.sent();
965
+ // Batch compute V3 lp fees.
966
+ start = performance.now();
967
+ promises = [
968
+ validatedBundleV3Fills.length > 0
969
+ ? this.clients.hubPoolClient.batchComputeRealizedLpFeePct(validatedBundleV3Fills.map(function (fill) {
970
+ var matchedDeposit = v3RelayHashes[_this.getRelayHashFromEvent(fill)].deposit;
971
+ assert(isDefined(matchedDeposit), "Deposit should exist in relay hash dictionary.");
972
+ var paymentChainId = getRefundInformationFromFill(fill, _this.clients.hubPoolClient, blockRangesForChains, chainIds, matchedDeposit.fromLiteChain).chainToSendRefundTo;
973
+ return __assign(__assign({}, fill), { paymentChainId: paymentChainId });
974
+ }))
975
+ : [],
976
+ validatedBundleSlowFills.length > 0
977
+ ? this.clients.hubPoolClient.batchComputeRealizedLpFeePct(validatedBundleSlowFills.map(function (deposit) {
978
+ return __assign(__assign({}, deposit), { paymentChainId: deposit.destinationChainId });
979
+ }))
980
+ : [],
981
+ validatedBundleUnexecutableSlowFills.length > 0
982
+ ? this.clients.hubPoolClient.batchComputeRealizedLpFeePct(validatedBundleUnexecutableSlowFills.map(function (deposit) {
983
+ return __assign(__assign({}, deposit), { paymentChainId: deposit.destinationChainId });
984
+ }))
985
+ : [],
986
+ ];
987
+ return [4 /*yield*/, Promise.all(promises)];
988
+ case 9:
989
+ _b = _c.sent(), v3FillLpFees = _b[0], v3SlowFillLpFees = _b[1], v3UnexecutableSlowFillLpFees = _b[2];
990
+ this.logger.debug({
991
+ at: "BundleDataClient#loadData",
992
+ message: "Computed batch async LP fees in ".concat(performance.now() - start, "ms."),
993
+ });
994
+ v3FillLpFees.forEach(function (_a, idx) {
995
+ var realizedLpFeePct = _a.realizedLpFeePct;
996
+ var fill = validatedBundleV3Fills[idx];
997
+ var associatedDeposit = v3RelayHashes[_this.getRelayHashFromEvent(fill)].deposit;
998
+ assert(isDefined(associatedDeposit), "Deposit should exist in relay hash dictionary.");
999
+ var _b = getRefundInformationFromFill(fill, _this.clients.hubPoolClient, blockRangesForChains, chainIds, associatedDeposit.fromLiteChain), chainToSendRefundTo = _b.chainToSendRefundTo, repaymentToken = _b.repaymentToken;
1000
+ updateBundleFillsV3(bundleFillsV3, fill, realizedLpFeePct, chainToSendRefundTo, repaymentToken);
1001
+ });
1002
+ v3SlowFillLpFees.forEach(function (_a, idx) {
1003
+ var lpFeePct = _a.realizedLpFeePct;
1004
+ var deposit = validatedBundleSlowFills[idx];
1005
+ updateBundleSlowFills(bundleSlowFillsV3, __assign(__assign({}, deposit), { lpFeePct: lpFeePct }));
1006
+ });
1007
+ v3UnexecutableSlowFillLpFees.forEach(function (_a, idx) {
1008
+ var lpFeePct = _a.realizedLpFeePct;
1009
+ var deposit = validatedBundleUnexecutableSlowFills[idx];
1010
+ updateBundleExcessSlowFills(unexecutableSlowFills, __assign(__assign({}, deposit), { lpFeePct: lpFeePct }));
1011
+ });
1012
+ v3SpokeEventsReadable = prettyPrintV3SpokePoolEvents(bundleDepositsV3, bundleFillsV3, bundleInvalidFillsV3, bundleSlowFillsV3, expiredDepositsToRefundV3, unexecutableSlowFills);
1013
+ if (bundleInvalidFillsV3.length > 0) {
1014
+ this.logger.debug({
1015
+ at: "BundleDataClient#loadData",
1016
+ message: "Finished loading V3 spoke pool data and found some invalid V3 fills in range",
1017
+ blockRangesForChains: blockRangesForChains,
1018
+ bundleInvalidFillsV3: bundleInvalidFillsV3,
1019
+ });
1020
+ }
1021
+ this.logger.debug({
1022
+ at: "BundleDataClient#loadDataFromScratch",
1023
+ message: "Computed bundle data in ".concat(Math.round(performance.now() - start) / 1000, "s."),
1024
+ blockRangesForChains: JSON.stringify(blockRangesForChains),
1025
+ v3SpokeEventsReadable: v3SpokeEventsReadable,
1026
+ });
1027
+ return [2 /*return*/, {
1028
+ bundleDepositsV3: bundleDepositsV3,
1029
+ expiredDepositsToRefundV3: expiredDepositsToRefundV3,
1030
+ bundleFillsV3: bundleFillsV3,
1031
+ unexecutableSlowFills: unexecutableSlowFills,
1032
+ bundleSlowFillsV3: bundleSlowFillsV3,
1033
+ }];
1034
+ }
1035
+ });
1036
+ });
1037
+ };
1038
+ // Internal function to uniquely identify a bridge event. This is preferred over `SDK.getRelayDataHash` which returns
1039
+ // keccak256 hash of the relay data, which can be used as input into the on-chain `fillStatuses()` function in the
1040
+ // spoke pool contract. However, this internal function is used to uniquely identify a bridging event
1041
+ // for speed since its easier to build a string from the event data than to hash it.
1042
+ BundleDataClient.prototype.getRelayHashFromEvent = function (event) {
1043
+ return "".concat(event.depositor, "-").concat(event.recipient, "-").concat(event.exclusiveRelayer, "-").concat(event.inputToken, "-").concat(event.outputToken, "-").concat(event.inputAmount, "-").concat(event.outputAmount, "-").concat(event.originChainId, "-").concat(event.depositId, "-").concat(event.fillDeadline, "-").concat(event.exclusivityDeadline, "-").concat(event.message, "-").concat(event.destinationChainId);
1044
+ };
1045
+ BundleDataClient.prototype.getBundleBlockTimestamps = function (chainIds, blockRangesForChains, spokePoolClients) {
1046
+ return __awaiter(this, void 0, void 0, function () {
1047
+ var _a, _b;
1048
+ var _this = this;
1049
+ return __generator(this, function (_c) {
1050
+ switch (_c.label) {
1051
+ case 0:
1052
+ _b = (_a = Object).fromEntries;
1053
+ return [4 /*yield*/, mapAsync(chainIds, function (chainId, index) { return __awaiter(_this, void 0, void 0, function () {
1054
+ var blockRangeForChain, _startBlockForChain, _endBlockForChain, spokePoolClient, startBlockForChain, endBlockForChain, _a, startTime, endTime, _b, _c, _d;
1055
+ return __generator(this, function (_e) {
1056
+ switch (_e.label) {
1057
+ case 0:
1058
+ blockRangeForChain = blockRangesForChains[index];
1059
+ if (!isDefined(blockRangeForChain) || isChainDisabled(blockRangeForChain)) {
1060
+ return [2 /*return*/];
1061
+ }
1062
+ _startBlockForChain = blockRangeForChain[0], _endBlockForChain = blockRangeForChain[1];
1063
+ spokePoolClient = spokePoolClients[chainId];
1064
+ // Relayer instances using the BundleDataClient for repayment estimates may only relay on a subset of chains.
1065
+ if (!isDefined(spokePoolClient)) {
1066
+ return [2 /*return*/];
1067
+ }
1068
+ startBlockForChain = Math.min(_startBlockForChain, spokePoolClient.latestBlockSearched);
1069
+ endBlockForChain = Math.min(_endBlockForChain, spokePoolClient.latestBlockSearched);
1070
+ _b = Number;
1071
+ return [4 /*yield*/, spokePoolClient.spokePool.provider.getBlock(startBlockForChain)];
1072
+ case 1:
1073
+ _c = [
1074
+ _b.apply(void 0, [(_e.sent()).timestamp])
1075
+ ];
1076
+ _d = Number;
1077
+ return [4 /*yield*/, spokePoolClient.spokePool.provider.getBlock(endBlockForChain)];
1078
+ case 2:
1079
+ _a = _c.concat([
1080
+ _d.apply(void 0, [(_e.sent()).timestamp])
1081
+ ]), startTime = _a[0], endTime = _a[1];
1082
+ // Sanity checks:
1083
+ assert(endTime >= startTime, "End time should be greater than start time.");
1084
+ assert(startTime > 0, "Start time should be greater than 0.");
1085
+ return [2 /*return*/, [chainId, [startTime, endTime]]];
1086
+ }
1087
+ });
1088
+ }); })];
1089
+ case 1: return [2 /*return*/, _b.apply(_a, [(_c.sent()).filter(isDefined)])];
1090
+ }
1091
+ });
1092
+ });
1093
+ };
1094
+ return BundleDataClient;
1095
+ }());
1096
+ export { BundleDataClient };
1097
+ //# sourceMappingURL=BundleDataClient.js.map