@across-protocol/sdk 4.1.63-beta.1 → 4.1.63-beta.3

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 (224) hide show
  1. package/dist/cjs/arch/evm/BlockUtils.d.ts +15 -0
  2. package/dist/cjs/arch/evm/BlockUtils.js +218 -0
  3. package/dist/cjs/arch/evm/BlockUtils.js.map +1 -0
  4. package/dist/cjs/arch/evm/index.d.ts +1 -0
  5. package/dist/cjs/arch/evm/index.js +1 -0
  6. package/dist/cjs/arch/evm/index.js.map +1 -1
  7. package/dist/cjs/arch/svm/SpokeUtils.d.ts +3 -2
  8. package/dist/cjs/arch/svm/SpokeUtils.js +42 -12
  9. package/dist/cjs/arch/svm/SpokeUtils.js.map +1 -1
  10. package/dist/cjs/arch/svm/eventsClient.js +6 -6
  11. package/dist/cjs/arch/svm/eventsClient.js.map +1 -1
  12. package/dist/cjs/arch/svm/utils.d.ts +1 -0
  13. package/dist/cjs/arch/svm/utils.js +10 -2
  14. package/dist/cjs/arch/svm/utils.js.map +1 -1
  15. package/dist/cjs/clients/HubPoolClient.d.ts +3 -2
  16. package/dist/cjs/clients/HubPoolClient.js +2 -1
  17. package/dist/cjs/clients/HubPoolClient.js.map +1 -1
  18. package/dist/cjs/clients/SpokePoolClient/SVMSpokePoolClient.d.ts +1 -1
  19. package/dist/cjs/clients/SpokePoolClient/SVMSpokePoolClient.js +29 -2
  20. package/dist/cjs/clients/SpokePoolClient/SVMSpokePoolClient.js.map +1 -1
  21. package/dist/cjs/clients/SpokePoolClient/SpokePoolClient.js +4 -3
  22. package/dist/cjs/clients/SpokePoolClient/SpokePoolClient.js.map +1 -1
  23. package/dist/cjs/clients/mocks/MockSvmCpiEventsClient.d.ts +33 -0
  24. package/dist/cjs/clients/mocks/MockSvmCpiEventsClient.js +184 -0
  25. package/dist/cjs/clients/mocks/MockSvmCpiEventsClient.js.map +1 -0
  26. package/dist/cjs/clients/mocks/MockSvmSpokePoolClient.d.ts +30 -0
  27. package/dist/cjs/clients/mocks/MockSvmSpokePoolClient.js +90 -0
  28. package/dist/cjs/clients/mocks/MockSvmSpokePoolClient.js.map +1 -0
  29. package/dist/cjs/clients/mocks/index.d.ts +2 -0
  30. package/dist/cjs/clients/mocks/index.js +2 -0
  31. package/dist/cjs/clients/mocks/index.js.map +1 -1
  32. package/dist/cjs/constants.d.ts +1 -0
  33. package/dist/cjs/constants.js +2 -1
  34. package/dist/cjs/constants.js.map +1 -1
  35. package/dist/cjs/providers/index.d.ts +1 -1
  36. package/dist/cjs/providers/index.js +1 -2
  37. package/dist/cjs/providers/index.js.map +1 -1
  38. package/dist/cjs/providers/mocks/MockCachedSolanaRpcFactory.d.ts +5 -0
  39. package/dist/cjs/providers/mocks/MockCachedSolanaRpcFactory.js +21 -0
  40. package/dist/cjs/providers/mocks/MockCachedSolanaRpcFactory.js.map +1 -0
  41. package/dist/cjs/providers/mocks/MockRateLimitedSolanaRpcFactory.d.ts +5 -0
  42. package/dist/cjs/providers/mocks/MockRateLimitedSolanaRpcFactory.js +20 -0
  43. package/dist/cjs/providers/mocks/MockRateLimitedSolanaRpcFactory.js.map +1 -0
  44. package/dist/cjs/providers/mocks/MockSolanaRpcFactory.d.ts +13 -0
  45. package/dist/cjs/providers/mocks/MockSolanaRpcFactory.js +76 -0
  46. package/dist/cjs/providers/mocks/MockSolanaRpcFactory.js.map +1 -0
  47. package/dist/cjs/providers/mocks/index.d.ts +4 -0
  48. package/dist/cjs/providers/mocks/index.js +8 -0
  49. package/dist/cjs/providers/mocks/index.js.map +1 -0
  50. package/dist/cjs/providers/{mockProvider.js → mocks/mockEthersProvider.js} +2 -2
  51. package/dist/cjs/providers/mocks/mockEthersProvider.js.map +1 -0
  52. package/dist/cjs/relayFeeCalculator/chain-queries/baseQuery.js +5 -4
  53. package/dist/cjs/relayFeeCalculator/chain-queries/baseQuery.js.map +1 -1
  54. package/dist/cjs/relayFeeCalculator/chain-queries/factory.d.ts +9 -0
  55. package/dist/cjs/relayFeeCalculator/chain-queries/factory.js +1 -1
  56. package/dist/cjs/relayFeeCalculator/chain-queries/factory.js.map +1 -1
  57. package/dist/cjs/relayFeeCalculator/chain-queries/svmQuery.d.ts +6 -0
  58. package/dist/cjs/relayFeeCalculator/chain-queries/svmQuery.js +69 -34
  59. package/dist/cjs/relayFeeCalculator/chain-queries/svmQuery.js.map +1 -1
  60. package/dist/cjs/relayFeeCalculator/relayFeeCalculator.d.ts +11 -0
  61. package/dist/cjs/relayFeeCalculator/relayFeeCalculator.js +9 -3
  62. package/dist/cjs/relayFeeCalculator/relayFeeCalculator.js.map +1 -1
  63. package/dist/cjs/utils/BlockFinder.d.ts +22 -0
  64. package/dist/cjs/utils/BlockFinder.js +10 -0
  65. package/dist/cjs/utils/BlockFinder.js.map +1 -0
  66. package/dist/cjs/utils/BlockUtils.d.ts +2 -27
  67. package/dist/cjs/utils/BlockUtils.js +2 -208
  68. package/dist/cjs/utils/BlockUtils.js.map +1 -1
  69. package/dist/cjs/utils/TokenUtils.d.ts +18 -0
  70. package/dist/cjs/utils/index.d.ts +1 -0
  71. package/dist/cjs/utils/index.js +1 -0
  72. package/dist/cjs/utils/index.js.map +1 -1
  73. package/dist/esm/arch/evm/BlockUtils.d.ts +24 -0
  74. package/dist/esm/arch/evm/BlockUtils.js +250 -0
  75. package/dist/esm/arch/evm/BlockUtils.js.map +1 -0
  76. package/dist/esm/arch/evm/index.d.ts +1 -0
  77. package/dist/esm/arch/evm/index.js +1 -0
  78. package/dist/esm/arch/evm/index.js.map +1 -1
  79. package/dist/esm/arch/svm/SpokeUtils.d.ts +37 -2
  80. package/dist/esm/arch/svm/SpokeUtils.js +80 -13
  81. package/dist/esm/arch/svm/SpokeUtils.js.map +1 -1
  82. package/dist/esm/arch/svm/eventsClient.js +6 -6
  83. package/dist/esm/arch/svm/eventsClient.js.map +1 -1
  84. package/dist/esm/arch/svm/utils.d.ts +4 -0
  85. package/dist/esm/arch/svm/utils.js +11 -1
  86. package/dist/esm/arch/svm/utils.js.map +1 -1
  87. package/dist/esm/clients/HubPoolClient.d.ts +3 -2
  88. package/dist/esm/clients/HubPoolClient.js +3 -2
  89. package/dist/esm/clients/HubPoolClient.js.map +1 -1
  90. package/dist/esm/clients/SpokePoolClient/SVMSpokePoolClient.d.ts +1 -2
  91. package/dist/esm/clients/SpokePoolClient/SVMSpokePoolClient.js +34 -5
  92. package/dist/esm/clients/SpokePoolClient/SVMSpokePoolClient.js.map +1 -1
  93. package/dist/esm/clients/SpokePoolClient/SpokePoolClient.js +6 -4
  94. package/dist/esm/clients/SpokePoolClient/SpokePoolClient.js.map +1 -1
  95. package/dist/esm/clients/mocks/MockSvmCpiEventsClient.d.ts +33 -0
  96. package/dist/esm/clients/mocks/MockSvmCpiEventsClient.js +183 -0
  97. package/dist/esm/clients/mocks/MockSvmCpiEventsClient.js.map +1 -0
  98. package/dist/esm/clients/mocks/MockSvmSpokePoolClient.d.ts +30 -0
  99. package/dist/esm/clients/mocks/MockSvmSpokePoolClient.js +89 -0
  100. package/dist/esm/clients/mocks/MockSvmSpokePoolClient.js.map +1 -0
  101. package/dist/esm/clients/mocks/index.d.ts +2 -0
  102. package/dist/esm/clients/mocks/index.js +2 -0
  103. package/dist/esm/clients/mocks/index.js.map +1 -1
  104. package/dist/esm/constants.d.ts +1 -0
  105. package/dist/esm/constants.js +1 -0
  106. package/dist/esm/constants.js.map +1 -1
  107. package/dist/esm/providers/index.d.ts +1 -1
  108. package/dist/esm/providers/index.js +1 -2
  109. package/dist/esm/providers/index.js.map +1 -1
  110. package/dist/esm/providers/mocks/MockCachedSolanaRpcFactory.d.ts +5 -0
  111. package/dist/esm/providers/mocks/MockCachedSolanaRpcFactory.js +19 -0
  112. package/dist/esm/providers/mocks/MockCachedSolanaRpcFactory.js.map +1 -0
  113. package/dist/esm/providers/mocks/MockRateLimitedSolanaRpcFactory.d.ts +5 -0
  114. package/dist/esm/providers/mocks/MockRateLimitedSolanaRpcFactory.js +18 -0
  115. package/dist/esm/providers/mocks/MockRateLimitedSolanaRpcFactory.js.map +1 -0
  116. package/dist/esm/providers/mocks/MockSolanaRpcFactory.d.ts +13 -0
  117. package/dist/esm/providers/mocks/MockSolanaRpcFactory.js +74 -0
  118. package/dist/esm/providers/mocks/MockSolanaRpcFactory.js.map +1 -0
  119. package/dist/esm/providers/mocks/index.d.ts +4 -0
  120. package/dist/esm/providers/mocks/index.js +5 -0
  121. package/dist/esm/providers/mocks/index.js.map +1 -0
  122. package/dist/esm/providers/{mockProvider.js → mocks/mockEthersProvider.js} +2 -2
  123. package/dist/esm/providers/mocks/mockEthersProvider.js.map +1 -0
  124. package/dist/esm/relayFeeCalculator/chain-queries/baseQuery.js +6 -5
  125. package/dist/esm/relayFeeCalculator/chain-queries/baseQuery.js.map +1 -1
  126. package/dist/esm/relayFeeCalculator/chain-queries/factory.d.ts +9 -0
  127. package/dist/esm/relayFeeCalculator/chain-queries/factory.js +3 -3
  128. package/dist/esm/relayFeeCalculator/chain-queries/factory.js.map +1 -1
  129. package/dist/esm/relayFeeCalculator/chain-queries/svmQuery.d.ts +18 -0
  130. package/dist/esm/relayFeeCalculator/chain-queries/svmQuery.js +83 -36
  131. package/dist/esm/relayFeeCalculator/chain-queries/svmQuery.js.map +1 -1
  132. package/dist/esm/relayFeeCalculator/relayFeeCalculator.d.ts +21 -1
  133. package/dist/esm/relayFeeCalculator/relayFeeCalculator.js +9 -4
  134. package/dist/esm/relayFeeCalculator/relayFeeCalculator.js.map +1 -1
  135. package/dist/esm/utils/BlockFinder.d.ts +22 -0
  136. package/dist/esm/utils/BlockFinder.js +7 -0
  137. package/dist/esm/utils/BlockFinder.js.map +1 -0
  138. package/dist/esm/utils/BlockUtils.d.ts +2 -36
  139. package/dist/esm/utils/BlockUtils.js +2 -243
  140. package/dist/esm/utils/BlockUtils.js.map +1 -1
  141. package/dist/esm/utils/TokenUtils.d.ts +18 -0
  142. package/dist/esm/utils/index.d.ts +1 -0
  143. package/dist/esm/utils/index.js +1 -0
  144. package/dist/esm/utils/index.js.map +1 -1
  145. package/dist/types/arch/evm/BlockUtils.d.ts +25 -0
  146. package/dist/types/arch/evm/BlockUtils.d.ts.map +1 -0
  147. package/dist/types/arch/evm/index.d.ts +1 -0
  148. package/dist/types/arch/evm/index.d.ts.map +1 -1
  149. package/dist/types/arch/svm/SpokeUtils.d.ts +37 -2
  150. package/dist/types/arch/svm/SpokeUtils.d.ts.map +1 -1
  151. package/dist/types/arch/svm/eventsClient.d.ts.map +1 -1
  152. package/dist/types/arch/svm/utils.d.ts +4 -0
  153. package/dist/types/arch/svm/utils.d.ts.map +1 -1
  154. package/dist/types/clients/HubPoolClient.d.ts +3 -2
  155. package/dist/types/clients/HubPoolClient.d.ts.map +1 -1
  156. package/dist/types/clients/SpokePoolClient/SVMSpokePoolClient.d.ts +1 -2
  157. package/dist/types/clients/SpokePoolClient/SVMSpokePoolClient.d.ts.map +1 -1
  158. package/dist/types/clients/SpokePoolClient/SpokePoolClient.d.ts.map +1 -1
  159. package/dist/types/clients/mocks/MockSvmCpiEventsClient.d.ts +34 -0
  160. package/dist/types/clients/mocks/MockSvmCpiEventsClient.d.ts.map +1 -0
  161. package/dist/types/clients/mocks/MockSvmSpokePoolClient.d.ts +31 -0
  162. package/dist/types/clients/mocks/MockSvmSpokePoolClient.d.ts.map +1 -0
  163. package/dist/types/clients/mocks/index.d.ts +2 -0
  164. package/dist/types/clients/mocks/index.d.ts.map +1 -1
  165. package/dist/types/constants.d.ts +1 -0
  166. package/dist/types/constants.d.ts.map +1 -1
  167. package/dist/types/providers/index.d.ts +1 -1
  168. package/dist/types/providers/index.d.ts.map +1 -1
  169. package/dist/types/providers/mocks/MockCachedSolanaRpcFactory.d.ts +6 -0
  170. package/dist/types/providers/mocks/MockCachedSolanaRpcFactory.d.ts.map +1 -0
  171. package/dist/types/providers/mocks/MockRateLimitedSolanaRpcFactory.d.ts +6 -0
  172. package/dist/types/providers/mocks/MockRateLimitedSolanaRpcFactory.d.ts.map +1 -0
  173. package/dist/types/providers/mocks/MockSolanaRpcFactory.d.ts +14 -0
  174. package/dist/types/providers/mocks/MockSolanaRpcFactory.d.ts.map +1 -0
  175. package/dist/types/providers/mocks/index.d.ts +5 -0
  176. package/dist/types/providers/mocks/index.d.ts.map +1 -0
  177. package/dist/types/providers/{mockProvider.d.ts → mocks/mockEthersProvider.d.ts} +1 -1
  178. package/dist/types/providers/mocks/mockEthersProvider.d.ts.map +1 -0
  179. package/dist/types/relayFeeCalculator/chain-queries/baseQuery.d.ts.map +1 -1
  180. package/dist/types/relayFeeCalculator/chain-queries/factory.d.ts +9 -0
  181. package/dist/types/relayFeeCalculator/chain-queries/factory.d.ts.map +1 -1
  182. package/dist/types/relayFeeCalculator/chain-queries/svmQuery.d.ts +18 -0
  183. package/dist/types/relayFeeCalculator/chain-queries/svmQuery.d.ts.map +1 -1
  184. package/dist/types/relayFeeCalculator/relayFeeCalculator.d.ts +21 -1
  185. package/dist/types/relayFeeCalculator/relayFeeCalculator.d.ts.map +1 -1
  186. package/dist/types/utils/BlockFinder.d.ts +23 -0
  187. package/dist/types/utils/BlockFinder.d.ts.map +1 -0
  188. package/dist/types/utils/BlockUtils.d.ts +2 -36
  189. package/dist/types/utils/BlockUtils.d.ts.map +1 -1
  190. package/dist/types/utils/TokenUtils.d.ts +18 -0
  191. package/dist/types/utils/TokenUtils.d.ts.map +1 -1
  192. package/dist/types/utils/index.d.ts +1 -0
  193. package/dist/types/utils/index.d.ts.map +1 -1
  194. package/package.json +2 -3
  195. package/src/arch/evm/BlockUtils.ts +209 -0
  196. package/src/arch/evm/index.ts +1 -0
  197. package/src/arch/svm/SpokeUtils.ts +87 -17
  198. package/src/arch/svm/eventsClient.ts +13 -5
  199. package/src/arch/svm/utils.ts +12 -1
  200. package/src/clients/HubPoolClient.ts +3 -3
  201. package/src/clients/SpokePoolClient/SVMSpokePoolClient.ts +27 -3
  202. package/src/clients/SpokePoolClient/SpokePoolClient.ts +6 -3
  203. package/src/clients/mocks/MockSvmCpiEventsClient.ts +226 -0
  204. package/src/clients/mocks/MockSvmSpokePoolClient.ts +119 -0
  205. package/src/clients/mocks/index.ts +2 -0
  206. package/src/constants.ts +1 -0
  207. package/src/providers/index.ts +1 -1
  208. package/src/providers/mocks/MockCachedSolanaRpcFactory.ts +15 -0
  209. package/src/providers/mocks/MockRateLimitedSolanaRpcFactory.ts +14 -0
  210. package/src/providers/mocks/MockSolanaRpcFactory.ts +55 -0
  211. package/src/providers/mocks/index.ts +4 -0
  212. package/src/providers/{mockProvider.ts → mocks/mockEthersProvider.ts} +1 -1
  213. package/src/relayFeeCalculator/chain-queries/baseQuery.ts +6 -6
  214. package/src/relayFeeCalculator/chain-queries/factory.ts +3 -3
  215. package/src/relayFeeCalculator/chain-queries/svmQuery.ts +59 -27
  216. package/src/relayFeeCalculator/relayFeeCalculator.ts +15 -3
  217. package/src/utils/BlockFinder.ts +26 -0
  218. package/src/utils/BlockUtils.ts +5 -215
  219. package/src/utils/index.ts +1 -0
  220. package/dist/cjs/providers/mockProvider.js.map +0 -1
  221. package/dist/esm/providers/mockProvider.js.map +0 -1
  222. package/dist/types/providers/mockProvider.d.ts.map +0 -1
  223. /package/dist/cjs/providers/{mockProvider.d.ts → mocks/mockEthersProvider.d.ts} +0 -0
  224. /package/dist/esm/providers/{mockProvider.d.ts → mocks/mockEthersProvider.d.ts} +0 -0
@@ -1,5 +1,9 @@
1
1
  import assert from "assert";
2
- import { DEFAULT_SIMULATED_RELAYER_ADDRESS, TOKEN_SYMBOLS_MAP } from "../constants";
2
+ import {
3
+ DEFAULT_SIMULATED_RELAYER_ADDRESS,
4
+ DEFAULT_SIMULATED_RELAYER_ADDRESS_SVM,
5
+ TOKEN_SYMBOLS_MAP,
6
+ } from "../constants";
3
7
  import { Deposit } from "../interfaces";
4
8
  import {
5
9
  BigNumber,
@@ -18,6 +22,7 @@ import {
18
22
  toBNWei,
19
23
  isZeroAddress,
20
24
  compareAddressesSimple,
25
+ chainIsSvm,
21
26
  } from "../utils";
22
27
  import { Transport } from "viem";
23
28
 
@@ -36,6 +41,7 @@ export interface QueryInterface {
36
41
  }>
37
42
  ) => Promise<TransactionCostEstimate>;
38
43
  getTokenPrice: (tokenSymbol: string) => Promise<number>;
44
+ getNativeGasCost: (deposit: Omit<Deposit, "messageHash">, relayer: string) => Promise<BigNumber>;
39
45
  }
40
46
 
41
47
  export const expectedCapitalCostsKeys = ["lowerBound", "upperBound", "cutoff", "decimals"];
@@ -105,6 +111,12 @@ export const DEFAULT_LOGGER: Logger = {
105
111
  error: (...args) => console.error(args),
106
112
  };
107
113
 
114
+ export function getDefaultSimulatedRelayerAddress(chainId?: number) {
115
+ return isDefined(chainId) && chainIsSvm(chainId)
116
+ ? DEFAULT_SIMULATED_RELAYER_ADDRESS_SVM
117
+ : DEFAULT_SIMULATED_RELAYER_ADDRESS;
118
+ }
119
+
108
120
  // Small amount to simulate filling with. Should be low enough to guarantee a successful fill.
109
121
  const safeOutputAmount = toBN(100);
110
122
 
@@ -241,7 +253,7 @@ export class RelayFeeCalculator {
241
253
  deposit: Deposit,
242
254
  amountToRelay: BigNumberish,
243
255
  simulateZeroFill = false,
244
- relayerAddress = DEFAULT_SIMULATED_RELAYER_ADDRESS,
256
+ relayerAddress = getDefaultSimulatedRelayerAddress(deposit.destinationChainId),
245
257
  _tokenPrice?: number,
246
258
  tokenMapping = TOKEN_SYMBOLS_MAP,
247
259
  gasPrice?: BigNumberish,
@@ -480,7 +492,7 @@ export class RelayFeeCalculator {
480
492
  deposit: Deposit,
481
493
  amountToRelay?: BigNumberish,
482
494
  simulateZeroFill = false,
483
- relayerAddress = DEFAULT_SIMULATED_RELAYER_ADDRESS,
495
+ relayerAddress = getDefaultSimulatedRelayerAddress(deposit.destinationChainId),
484
496
  _tokenPrice?: number,
485
497
  gasPrice?: BigNumberish,
486
498
  gasUnits?: BigNumberish,
@@ -0,0 +1,26 @@
1
+ export type BlockFinderOpts = {
2
+ highBlock?: number;
3
+ highBlockOffset?: number;
4
+ blockRange?: number;
5
+ };
6
+
7
+ export type BlockTimeAverage = {
8
+ average: number;
9
+ blockRange: number;
10
+ timestamp: number;
11
+ };
12
+
13
+ export interface Block {
14
+ hash: string;
15
+ number: number;
16
+ timestamp: number;
17
+ }
18
+
19
+ export type BlockFinderHints = {
20
+ lowBlock?: number;
21
+ highBlock?: number;
22
+ };
23
+
24
+ export abstract class BlockFinder<TBlock extends Block> {
25
+ abstract getBlockForTimestamp(timestamp: number | string, hints: BlockFinderHints): Promise<TBlock>;
26
+ }
@@ -1,219 +1,9 @@
1
- import assert from "assert";
2
- import type { Block, Provider } from "@ethersproject/abstract-provider";
3
- import { clamp, sortedIndexBy } from "lodash";
4
- import { chainIsOPStack, getNetworkName } from "./NetworkUtils";
5
1
  import { isDefined } from "./TypeGuards";
6
2
  import { getCurrentTime } from "./TimeUtils";
7
3
  import { CachingMechanismInterface } from "../interfaces";
8
4
  import { shouldCache } from "./CachingUtils";
9
- import { CHAIN_IDs, DEFAULT_CACHING_SAFE_LAG } from "../constants";
10
-
11
- type Opts = {
12
- highBlock?: number;
13
- highBlockOffset?: number;
14
- blockRange?: number;
15
- };
16
-
17
- type BlockTimeAverage = {
18
- average: number;
19
- blockRange: number;
20
- timestamp: number;
21
- };
22
-
23
- // Archive requests typically commence at 128 blocks past the head of the chain.
24
- // Round down to 120 blocks to avoid slipping into archive territory.
25
- const defaultBlockRange = 120;
26
-
27
- // Default offset to the high block number. This is subtracted from the block number of the high block
28
- // when it is queried from the network, rather than having been specified by the caller. This is useful
29
- // since the supplied Provider instance may be backed by multiple RPC providers, which can lead to some
30
- // providers running slower than others and taking time to synchronise on the latest block.
31
- const defaultHighBlockOffset = 10;
32
-
33
- // Retain computations for 15 minutes.
34
- const cacheTTL = 60 * 15;
35
- const now = getCurrentTime(); // Seed the cache with initial values.
36
- const blockTimes: { [chainId: number]: BlockTimeAverage } = {
37
- [CHAIN_IDs.INK]: { average: 1, timestamp: now, blockRange: 1 },
38
- [CHAIN_IDs.LINEA]: { average: 3, timestamp: now, blockRange: 1 },
39
- [CHAIN_IDs.MAINNET]: { average: 12.5, timestamp: now, blockRange: 1 },
40
- [CHAIN_IDs.OPTIMISM]: { average: 2, timestamp: now, blockRange: 1 },
41
- [CHAIN_IDs.UNICHAIN]: { average: 1, timestamp: now, blockRange: 1 },
42
- };
43
-
44
- /**
45
- * @description Compute the average block time over a block range.
46
- * @returns Average number of seconds per block.
47
- */
48
- export async function averageBlockTime(
49
- provider: Provider,
50
- { highBlock, highBlockOffset, blockRange }: Opts = {}
51
- ): Promise<Pick<BlockTimeAverage, "average" | "blockRange">> {
52
- // Does not block for StaticJsonRpcProvider.
53
- const { chainId } = await provider.getNetwork();
54
-
55
- // OP stack chains inherit Optimism block times, but can be overridden.
56
- const cache = blockTimes[chainId] ?? (chainIsOPStack(chainId) ? blockTimes[CHAIN_IDs.OPTIMISM] : undefined);
57
-
58
- const now = getCurrentTime();
59
- if (isDefined(cache) && now < cache.timestamp + cacheTTL) {
60
- return { average: cache.average, blockRange: cache.blockRange };
61
- }
62
-
63
- // If the caller was not specific about highBlock, resolve it via the RPC provider. Subtract an offset
64
- // to account for various RPC provider sync issues that might occur when querting the latest block.
65
- if (!isDefined(highBlock)) {
66
- highBlock = await provider.getBlockNumber();
67
- highBlock -= highBlockOffset ?? defaultHighBlockOffset;
68
- }
69
- blockRange ??= defaultBlockRange;
70
-
71
- const earliestBlockNumber = highBlock - blockRange;
72
- const [firstBlock, lastBlock] = await Promise.all([
73
- provider.getBlock(earliestBlockNumber),
74
- provider.getBlock(highBlock),
75
- ]);
76
- [firstBlock, lastBlock].forEach((block: Block | undefined) => {
77
- if (!isDefined(block?.timestamp)) {
78
- const network = getNetworkName(chainId);
79
- const blockNumber = block === firstBlock ? earliestBlockNumber : highBlock;
80
- throw new Error(`BlockFinder: Failed to fetch block ${blockNumber} on ${network}`);
81
- }
82
- });
83
-
84
- const average = (lastBlock.timestamp - firstBlock.timestamp) / blockRange;
85
- blockTimes[chainId] = { timestamp: now, average, blockRange };
86
-
87
- return { average, blockRange };
88
- }
89
-
90
- async function estimateBlocksElapsed(seconds: number, cushionPercentage = 0.0, provider: Provider): Promise<number> {
91
- const cushionMultiplier = cushionPercentage + 1.0;
92
- const { average } = await averageBlockTime(provider);
93
- return Math.floor((seconds * cushionMultiplier) / average);
94
- }
95
-
96
- export type BlockFinderHints = {
97
- lowBlock?: number;
98
- highBlock?: number;
99
- };
100
-
101
- export class BlockFinder {
102
- constructor(
103
- private readonly provider: Provider,
104
- private readonly blocks: Block[] = []
105
- ) {}
106
-
107
- /**
108
- * @notice Gets the latest block whose timestamp is <= the provided timestamp.
109
- * @param number Timestamp timestamp to search.
110
- * @param hints Optional low and high block to bound the search space.
111
- */
112
- public async getBlockForTimestamp(timestamp: number | string, hints: BlockFinderHints = {}): Promise<Block> {
113
- timestamp = Number(timestamp);
114
- assert(timestamp !== undefined && timestamp !== null, "timestamp must be provided");
115
- // If the last block we have stored is too early, grab the latest block.
116
- if (this.blocks.length === 0 || this.blocks[this.blocks.length - 1].timestamp < timestamp) {
117
- const block = await this.getLatestBlock();
118
- if (timestamp >= block.timestamp) return block;
119
- }
120
-
121
- // Prime the BlockFinder cache with any supplied hints.
122
- // If the hint is accurate, then this will bypass the subsequent estimation.
123
- await Promise.all(
124
- Object.values(hints)
125
- .filter((blockNumber) => isDefined(blockNumber))
126
- .map((blockNumber) => this.getBlock(blockNumber))
127
- );
128
-
129
- // Check the first block. If it's greater than our timestamp, we need to find an earlier block.
130
- if (this.blocks[0].timestamp > timestamp) {
131
- const initialBlock = this.blocks[0];
132
- // We use a 2x cushion to reduce the number of iterations in the following loop and increase the chance
133
- // that the first block we find sets a floor for the target timestamp. The loop converges on the correct block
134
- // slower than the following incremental search performed by `findBlock`, so we want to minimize the number of
135
- // loop iterations in favor of searching more blocks over the `findBlock` search.
136
- const cushion = 1;
137
- const incrementDistance = Math.max(
138
- // Ensure the increment block distance is _at least_ a single block to prevent an infinite loop.
139
- await estimateBlocksElapsed(initialBlock.timestamp - timestamp, cushion, this.provider),
140
- 1
141
- );
142
-
143
- // Search backwards by a constant increment until we find a block before the timestamp or hit block 0.
144
- for (let multiplier = 1; ; multiplier++) {
145
- const distance = multiplier * incrementDistance;
146
- const blockNumber = Math.max(0, initialBlock.number - distance);
147
- const block = await this.getBlock(blockNumber);
148
- if (block.timestamp <= timestamp) break; // Found an earlier block.
149
- assert(blockNumber > 0, "timestamp is before block 0"); // Block 0 was not earlier than this timestamp. The row.
150
- }
151
- }
152
-
153
- // Find the index where the block would be inserted and use that as the end block (since it is >= the timestamp).
154
- const index = sortedIndexBy(this.blocks, { timestamp } as Block, "timestamp");
155
- return this.findBlock(this.blocks[index - 1], this.blocks[index], timestamp);
156
- }
157
-
158
- // Grabs the most recent block and caches it.
159
- private async getLatestBlock() {
160
- const block = await this.provider.getBlock("latest");
161
- const index = sortedIndexBy(this.blocks, block, "number");
162
- if (this.blocks[index]?.number !== block.number) this.blocks.splice(index, 0, block);
163
- return this.blocks[index];
164
- }
165
-
166
- // Grabs the block for a particular number and caches it.
167
- private async getBlock(number: number) {
168
- let index = sortedIndexBy(this.blocks, { number } as Block, "number");
169
- if (this.blocks[index]?.number === number) return this.blocks[index]; // Return early if block already exists.
170
- const block = await this.provider.getBlock(number);
171
-
172
- // Recompute the index after the async call since the state of this.blocks could have changed!
173
- index = sortedIndexBy(this.blocks, { number } as Block, "number");
174
-
175
- // Rerun this check to avoid duplicate insertion.
176
- if (this.blocks[index]?.number === number) return this.blocks[index];
177
- this.blocks.splice(index, 0, block); // A simple insert at index.
178
- return block;
179
- }
180
-
181
- // Return the latest block, between startBlock and endBlock, whose timestamp is <= timestamp.
182
- // Effectively, this is an interpolation search algorithm to minimize block requests.
183
- // Note: startBlock and endBlock _must_ be different blocks.
184
- private async findBlock(_startBlock: Block, _endBlock: Block, timestamp: number): Promise<Block> {
185
- const [startBlock, endBlock] = [_startBlock, _endBlock];
186
- // In the case of equality, the endBlock is expected to be passed as the one whose timestamp === the requested
187
- // timestamp.
188
- if (endBlock.timestamp === timestamp) return endBlock;
189
-
190
- // If there's no equality, but the blocks are adjacent, return the startBlock, since we want the returned block's
191
- // timestamp to be <= the requested timestamp.
192
- if (endBlock.number === startBlock.number + 1) return startBlock;
193
-
194
- assert(endBlock.number !== startBlock.number, "startBlock cannot equal endBlock");
195
- assert(
196
- timestamp < endBlock.timestamp && timestamp > startBlock.timestamp,
197
- "timestamp not in between start and end blocks"
198
- );
199
-
200
- // Interpolating the timestamp we're searching for to block numbers.
201
- const totalTimeDifference = endBlock.timestamp - startBlock.timestamp;
202
- const totalBlockDistance = endBlock.number - startBlock.number;
203
- const blockPercentile = (timestamp - startBlock.timestamp) / totalTimeDifference;
204
- const estimatedBlock = startBlock.number + Math.round(blockPercentile * totalBlockDistance);
205
-
206
- // Clamp ensures the estimated block is strictly greater than the start block and strictly less than the end block.
207
- const newBlock = await this.getBlock(clamp(estimatedBlock, startBlock.number + 1, endBlock.number - 1));
208
-
209
- // Depending on whether the new block is below or above the timestamp, narrow the search space accordingly.
210
- if (newBlock.timestamp < timestamp) {
211
- return this.findBlock(newBlock, endBlock, timestamp);
212
- } else {
213
- return this.findBlock(startBlock, newBlock, timestamp);
214
- }
215
- }
216
- }
5
+ import { BlockFinderHints, BlockFinder, Block } from "./BlockFinder";
6
+ import { DEFAULT_CACHING_SAFE_LAG } from "../constants";
217
7
 
218
8
  /**
219
9
  * @notice Get the block number for a given timestamp fresh from on-chain data if not found in redis cache.
@@ -224,16 +14,16 @@ export class BlockFinder {
224
14
  * or loading from cache. This is useful for testing primarily.
225
15
  * @returns Block number for the requested timestamp.
226
16
  */
227
- export async function getCachedBlockForTimestamp(
17
+ export async function getCachedBlockForTimestamp<TBlock extends Block>(
228
18
  chainId: number,
229
19
  timestamp: number,
230
- blockFinder: BlockFinder,
20
+ blockFinder: BlockFinder<TBlock>,
231
21
  cache?: CachingMechanismInterface,
232
22
  hints?: BlockFinderHints
233
23
  ): Promise<number> {
234
24
  // Resolve a convenience function to directly compute what we're
235
25
  // looking for.
236
- const resolver = async () => (await blockFinder.getBlockForTimestamp(timestamp, hints)).number;
26
+ const resolver = async () => (await blockFinder.getBlockForTimestamp(timestamp, hints || {})).number;
237
27
 
238
28
  // If no redis client, then request block from blockFinder.
239
29
  if (!isDefined(cache)) {
@@ -2,6 +2,7 @@ export * from "./common";
2
2
  export * from "./abi";
3
3
  export * from "./ArrayUtils";
4
4
  export * from "./BlockUtils";
5
+ export * from "./BlockFinder";
5
6
  export * from "./EventUtils";
6
7
  export * from "./ObjectUtils";
7
8
  export * from "./TimeUtils";
@@ -1 +0,0 @@
1
- {"version":3,"file":"mockProvider.js","sourceRoot":"","sources":["../../../src/providers/mockProvider.ts"],"names":[],"mappings":";;;;AAAA,iCAA8C;AAE9C,0DAAiD;AAMjD;IAAoC,0CAA+B;IAGjE,wBACW,oBAA+B,EAC/B,uBAAkC,EAClC,cAAkB;QAAlB,+BAAA,EAAA,kBAAkB;QAH7B,YAKE,kBAAM,SAAS,EAAE,cAAc,CAAC,SACjC;QALU,0BAAoB,GAApB,oBAAoB,CAAW;QAC/B,6BAAuB,GAAvB,uBAAuB,CAAW;QAClC,oBAAc,GAAd,cAAc,CAAI;QALrB,kBAAY,GAA4C,EAAE,CAAC;;IAQnE,CAAC;IAED,iCAAQ,GAAR,UAAS,oBAAoE;QAC3E,IAAM,SAAS,GAAU;YACvB,YAAY,EAAE,EAAE;YAChB,IAAI,EAAE,IAAI;YACV,UAAU,EAAE,IAAI;YAChB,MAAM,EAAE,CAAC;YACT,KAAK,EAAE,GAAG;YACV,UAAU,EAAE,CAAC;YACb,WAAW,EAAE,uBAAM;YACnB,SAAS,EAAE,CAAC;YACZ,QAAQ,EAAE,uBAAM;YAChB,OAAO,EAAE,uBAAM;YACf,aAAa,EAAE,IAAI,CAAC,oBAAoB;YACxC,KAAK,EAAE,IAAI;YACX,SAAS,EAAE,IAAI;SAChB,CAAC;QACF,OAAO,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACpC,CAAC;IAGD,6BAAI,GAAJ,UAAK,MAAc,EAAE,OAAmB;QACtC,QAAQ,MAAM,EAAE;YACd,KAAK,0BAA0B;gBAC7B,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;YACvD;gBACE,MAAM,IAAI,KAAK,CAAC,+CAAwC,MAAM,CAAE,CAAC,CAAC;SACrE;IACH,CAAC;IAED,mCAAU,GAAV;QACE,OAAO,OAAO,CAAC,OAAO,CAAC;YACrB,iBAAiB,EAAE,IAAI,CAAC,oBAAoB;YAC5C,oBAAoB,EAAE,IAAI,CAAC,uBAAuB;YAElD,YAAY,EAAE,IAAI;YAClB,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;IACL,CAAC;IAED,uCAAc,GAAd,UAAe,IAAY;QACzB,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,oCAAW,GAAX;QACE,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC;IACtF,CAAC;IAED,mCAAU,GAAV;QACE,OAAO,OAAO,CAAC,OAAO,CAAC;YACrB,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,IAAI,CAAC,cAAc;SAC7B,CAAC,CAAC;IACL,CAAC;IAED,wCAAe,GAAf,UAAgB,IAAY,EAAE,WAAgC;QAC5D,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC;IACxC,CAAC;IACH,qBAAC;AAAD,CAAC,AApED,CAAoC,kBAAS,CAAC,qBAAqB,GAoElE;AApEY,wCAAc"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"mockProvider.js","sourceRoot":"","sources":["../../../src/providers/mockProvider.ts"],"names":[],"mappings":";AAAA,OAAO,EAAa,SAAS,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEjD;;;GAGG;AACH;IAAoC,kCAA+B;IAGjE,wBACW,oBAA+B,EAC/B,uBAAkC,EAClC,cAAkB;QAAlB,+BAAA,EAAA,kBAAkB;QAH7B,YAKE,kBAAM,SAAS,EAAE,cAAc,CAAC,SACjC;QALU,0BAAoB,GAApB,oBAAoB,CAAW;QAC/B,6BAAuB,GAAvB,uBAAuB,CAAW;QAClC,oBAAc,GAAd,cAAc,CAAI;QALrB,kBAAY,GAA4C,EAAE,CAAC;;IAQnE,CAAC;IAED,iCAAQ,GAAR,UAAS,oBAAoE;QAC3E,IAAM,SAAS,GAAU;YACvB,YAAY,EAAE,EAAE;YAChB,IAAI,EAAE,IAAI;YACV,UAAU,EAAE,IAAI;YAChB,MAAM,EAAE,CAAC;YACT,KAAK,EAAE,GAAG;YACV,UAAU,EAAE,CAAC;YACb,WAAW,EAAE,MAAM;YACnB,SAAS,EAAE,CAAC;YACZ,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,MAAM;YACf,aAAa,EAAE,IAAI,CAAC,oBAAoB;YACxC,KAAK,EAAE,IAAI;YACX,SAAS,EAAE,IAAI;SAChB,CAAC;QACF,OAAO,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACpC,CAAC;IAED,8DAA8D;IAC9D,6BAAI,GAAJ,UAAK,MAAc,EAAE,OAAmB;QACtC,QAAQ,MAAM,EAAE;YACd,KAAK,0BAA0B;gBAC7B,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;YACvD;gBACE,MAAM,IAAI,KAAK,CAAC,+CAAwC,MAAM,CAAE,CAAC,CAAC;SACrE;IACH,CAAC;IAED,mCAAU,GAAV;QACE,OAAO,OAAO,CAAC,OAAO,CAAC;YACrB,iBAAiB,EAAE,IAAI,CAAC,oBAAoB;YAC5C,oBAAoB,EAAE,IAAI,CAAC,uBAAuB;YAClD,6CAA6C;YAC7C,YAAY,EAAE,IAAI;YAClB,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;IACL,CAAC;IAED,uCAAc,GAAd,UAAe,IAAY;QACzB,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,oCAAW,GAAX;QACE,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC;IACtF,CAAC;IAED,mCAAU,GAAV;QACE,OAAO,OAAO,CAAC,OAAO,CAAC;YACrB,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,IAAI,CAAC,cAAc;SAC7B,CAAC,CAAC;IACL,CAAC;IAED,wCAAe,GAAf,UAAgB,IAAY,EAAE,WAAgC;QAC5D,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC;IACxC,CAAC;IACH,qBAAC;AAAD,CAAC,AApED,CAAoC,SAAS,CAAC,qBAAqB,GAoElE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"mockProvider.d.ts","sourceRoot":"","sources":["../../../src/providers/mockProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAGjG;;;GAGG;AACH,qBAAa,cAAe,SAAQ,SAAS,CAAC,qBAAqB;IAI/D,QAAQ,CAAC,oBAAoB,EAAE,SAAS;IACxC,QAAQ,CAAC,uBAAuB,EAAE,SAAS;IAC3C,QAAQ,CAAC,cAAc;IALzB,OAAO,CAAC,YAAY,CAA+C;gBAGxD,oBAAoB,EAAE,SAAS,EAC/B,uBAAuB,EAAE,SAAS,EAClC,cAAc,SAAI;IAK7B,QAAQ,CAAC,oBAAoB,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC;IAoB9F,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IASvD,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IAU9B,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAI1D,WAAW,IAAI,OAAO,CAAC,SAAS,CAAC;IAIjC,UAAU,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAOxD,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,mBAAmB;CAG/D"}