@across-protocol/sdk 4.1.32 → 4.1.33

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 (96) hide show
  1. package/dist/cjs/arch/evm/index.d.ts +1 -0
  2. package/dist/cjs/arch/evm/index.js +5 -0
  3. package/dist/cjs/arch/evm/index.js.map +1 -0
  4. package/dist/cjs/arch/index.d.ts +2 -0
  5. package/dist/cjs/arch/index.js +7 -0
  6. package/dist/cjs/arch/index.js.map +1 -0
  7. package/dist/cjs/arch/svm/index.d.ts +1 -0
  8. package/dist/cjs/arch/svm/index.js +5 -0
  9. package/dist/cjs/arch/svm/index.js.map +1 -0
  10. package/dist/cjs/clients/BundleDataClient/BundleDataClient.js +24 -3
  11. package/dist/cjs/clients/BundleDataClient/BundleDataClient.js.map +1 -1
  12. package/dist/cjs/clients/BundleDataClient/utils/SuperstructUtils.d.ts +2 -2
  13. package/dist/cjs/clients/SpokePoolClient/EVMSpokePoolClient.d.ts +19 -0
  14. package/dist/cjs/clients/SpokePoolClient/EVMSpokePoolClient.js +170 -0
  15. package/dist/cjs/clients/SpokePoolClient/EVMSpokePoolClient.js.map +1 -0
  16. package/dist/cjs/clients/{SpokePoolClient.d.ts → SpokePoolClient/SpokePoolClient.d.ts} +17 -22
  17. package/dist/cjs/clients/{SpokePoolClient.js → SpokePoolClient/SpokePoolClient.js} +24 -174
  18. package/dist/cjs/clients/SpokePoolClient/SpokePoolClient.js.map +1 -0
  19. package/dist/cjs/clients/SpokePoolClient/index.d.ts +5 -0
  20. package/dist/cjs/clients/SpokePoolClient/index.js +13 -0
  21. package/dist/cjs/clients/SpokePoolClient/index.js.map +1 -0
  22. package/dist/cjs/clients/index.d.ts +1 -1
  23. package/dist/cjs/clients/index.js +2 -1
  24. package/dist/cjs/clients/index.js.map +1 -1
  25. package/dist/cjs/clients/mocks/MockSpokePoolClient.d.ts +2 -2
  26. package/dist/cjs/clients/mocks/MockSpokePoolClient.js +1 -1
  27. package/dist/cjs/clients/mocks/MockSpokePoolClient.js.map +1 -1
  28. package/dist/cjs/utils/BundleUtils.js +7 -7
  29. package/dist/cjs/utils/BundleUtils.js.map +1 -1
  30. package/dist/esm/arch/evm/index.d.ts +1 -0
  31. package/dist/esm/arch/evm/index.js +2 -0
  32. package/dist/esm/arch/evm/index.js.map +1 -0
  33. package/dist/esm/arch/index.d.ts +2 -0
  34. package/dist/esm/arch/index.js +5 -0
  35. package/dist/esm/arch/index.js.map +1 -0
  36. package/dist/esm/arch/svm/index.d.ts +1 -0
  37. package/dist/esm/arch/svm/index.js +2 -0
  38. package/dist/esm/arch/svm/index.js.map +1 -0
  39. package/dist/esm/clients/BundleDataClient/BundleDataClient.js +30 -3
  40. package/dist/esm/clients/BundleDataClient/BundleDataClient.js.map +1 -1
  41. package/dist/esm/clients/BundleDataClient/utils/SuperstructUtils.d.ts +2 -2
  42. package/dist/esm/clients/SpokePoolClient/EVMSpokePoolClient.d.ts +22 -0
  43. package/dist/esm/clients/SpokePoolClient/EVMSpokePoolClient.js +174 -0
  44. package/dist/esm/clients/SpokePoolClient/EVMSpokePoolClient.js.map +1 -0
  45. package/dist/{types/clients → esm/clients/SpokePoolClient}/SpokePoolClient.d.ts +58 -57
  46. package/dist/esm/clients/{SpokePoolClient.js → SpokePoolClient/SpokePoolClient.js} +22 -212
  47. package/dist/esm/clients/SpokePoolClient/SpokePoolClient.js.map +1 -0
  48. package/dist/esm/clients/SpokePoolClient/index.d.ts +10 -0
  49. package/dist/esm/clients/SpokePoolClient/index.js +12 -0
  50. package/dist/esm/clients/SpokePoolClient/index.js.map +1 -0
  51. package/dist/esm/clients/index.d.ts +1 -1
  52. package/dist/esm/clients/index.js +1 -1
  53. package/dist/esm/clients/index.js.map +1 -1
  54. package/dist/esm/clients/mocks/MockSpokePoolClient.d.ts +2 -2
  55. package/dist/esm/clients/mocks/MockSpokePoolClient.js +2 -2
  56. package/dist/esm/clients/mocks/MockSpokePoolClient.js.map +1 -1
  57. package/dist/esm/utils/BundleUtils.js +7 -7
  58. package/dist/esm/utils/BundleUtils.js.map +1 -1
  59. package/dist/esm/utils/abi/typechain/Multicall3.d.ts +1 -4
  60. package/dist/esm/utils/abi/typechain/factories/Multicall3__factory.js.map +1 -1
  61. package/dist/types/arch/evm/index.d.ts +2 -0
  62. package/dist/types/arch/evm/index.d.ts.map +1 -0
  63. package/dist/types/arch/index.d.ts +3 -0
  64. package/dist/types/arch/index.d.ts.map +1 -0
  65. package/dist/types/arch/svm/index.d.ts +2 -0
  66. package/dist/types/arch/svm/index.d.ts.map +1 -0
  67. package/dist/types/clients/BundleDataClient/BundleDataClient.d.ts.map +1 -1
  68. package/dist/types/clients/BundleDataClient/utils/SuperstructUtils.d.ts +2 -2
  69. package/dist/types/clients/SpokePoolClient/EVMSpokePoolClient.d.ts +23 -0
  70. package/dist/types/clients/SpokePoolClient/EVMSpokePoolClient.d.ts.map +1 -0
  71. package/dist/{esm/clients → types/clients/SpokePoolClient}/SpokePoolClient.d.ts +59 -56
  72. package/dist/types/clients/SpokePoolClient/SpokePoolClient.d.ts.map +1 -0
  73. package/dist/types/clients/SpokePoolClient/index.d.ts +11 -0
  74. package/dist/types/clients/SpokePoolClient/index.d.ts.map +1 -0
  75. package/dist/types/clients/index.d.ts +1 -1
  76. package/dist/types/clients/index.d.ts.map +1 -1
  77. package/dist/types/clients/mocks/MockSpokePoolClient.d.ts +2 -2
  78. package/dist/types/clients/mocks/MockSpokePoolClient.d.ts.map +1 -1
  79. package/dist/types/utils/abi/typechain/Multicall3.d.ts +1 -4
  80. package/dist/types/utils/abi/typechain/Multicall3.d.ts.map +1 -1
  81. package/dist/types/utils/abi/typechain/common.d.ts.map +1 -1
  82. package/dist/types/utils/abi/typechain/factories/Multicall3__factory.d.ts.map +1 -1
  83. package/package.json +4 -3
  84. package/src/arch/evm/index.ts +1 -0
  85. package/src/arch/index.ts +2 -0
  86. package/src/arch/svm/index.ts +1 -0
  87. package/src/clients/BundleDataClient/BundleDataClient.ts +29 -1
  88. package/src/clients/SpokePoolClient/EVMSpokePoolClient.ts +206 -0
  89. package/src/clients/{SpokePoolClient.ts → SpokePoolClient/SpokePoolClient.ts} +87 -237
  90. package/src/clients/SpokePoolClient/index.ts +14 -0
  91. package/src/clients/index.ts +1 -1
  92. package/src/clients/mocks/MockSpokePoolClient.ts +2 -2
  93. package/src/utils/BundleUtils.ts +6 -6
  94. package/dist/cjs/clients/SpokePoolClient.js.map +0 -1
  95. package/dist/esm/clients/SpokePoolClient.js.map +0 -1
  96. package/dist/types/clients/SpokePoolClient.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Multicall3__factory.d.ts","sourceRoot":"","sources":["../../../../../../src/utils/abi/typechain/factories/Multicall3__factory.ts"],"names":[],"mappings":"AAIA,OAAO,EAAY,MAAM,EAAS,MAAM,QAAQ,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AA2brE,qBAAa,mBAAmB;IAC9B,MAAM,CAAC,QAAQ,CAAC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAAQ;IAC3B,MAAM,CAAC,eAAe,IAAI,mBAAmB;IAG7C,MAAM,CAAC,OAAO,CACZ,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,MAAM,GAAG,QAAQ,GAClC,UAAU;CAGd"}
1
+ {"version":3,"file":"Multicall3__factory.d.ts","sourceRoot":"","sources":["../../../../../../src/utils/abi/typechain/factories/Multicall3__factory.ts"],"names":[],"mappings":"AAIA,OAAO,EAAY,MAAM,EAAS,MAAM,QAAQ,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AA2brE,qBAAa,mBAAmB;IAC9B,MAAM,CAAC,QAAQ,CAAC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAAQ;IAC3B,MAAM,CAAC,eAAe,IAAI,mBAAmB;IAG7C,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU;CAGjF"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@across-protocol/sdk",
3
3
  "author": "UMA Team",
4
- "version": "4.1.32",
4
+ "version": "4.1.33",
5
5
  "license": "AGPL-3.0",
6
6
  "homepage": "https://docs.across.to/reference/sdk",
7
7
  "files": [
@@ -16,8 +16,8 @@
16
16
  "build-bigint-buffer": "node scripts/build-bigint-buffer.js",
17
17
  "postinstall": "node scripts/build-bigint-buffer.js",
18
18
  "start": "yarn typechain && nodemon -e ts,tsx,json,js,jsx --watch ./src --ignore ./dist --exec 'yarn dev'",
19
- "build": "yarn run clean && yarn typechain && yarn run build:cjs & yarn run build:esm & yarn run build:types; wait",
20
- "dev": "yarn run build:cjs & yarn run build:esm & yarn run build:types; wait",
19
+ "build": "yarn run clean && yarn typechain && yarn dev",
20
+ "dev": "concurrently --kill-others-on-fail --names 'cjs,esm,types' --prefix-colors 'blue,magenta,green' 'yarn run build:cjs' 'yarn run build:esm' 'yarn run build:types'",
21
21
  "build:cjs": "tsc --project tsconfig.build.json --module commonjs --outDir ./dist/cjs --removeComments --verbatimModuleSyntax false && echo > ./dist/cjs/package.json '{\"type\":\"commonjs\"}'",
22
22
  "build:esm": "tsc --project tsconfig.build.json --module es2015 --outDir ./dist/esm && echo > ./dist/esm/package.json '{\"type\":\"module\",\"sideEffects\":false}'",
23
23
  "build:types": "tsc --project tsconfig.build.json --module esnext --declarationDir ./dist/types --emitDeclarationOnly --declaration --declarationMap",
@@ -71,6 +71,7 @@
71
71
  "arlocal": "^1.1.65",
72
72
  "chai": "^4.3.8",
73
73
  "chai-exclude": "^2.1.0",
74
+ "concurrently": "^9.1.2",
74
75
  "dotenv": "^16.0.0",
75
76
  "eslint": "^8.49.0",
76
77
  "eslint-config-prettier": "^9.0.0",
@@ -0,0 +1 @@
1
+ export const platform = "evm"; // Placeholder for actual exports.
@@ -0,0 +1,2 @@
1
+ export * as evm from "./evm";
2
+ export * as svm from "./svm";
@@ -0,0 +1 @@
1
+ export const platform = "svm"; // Placeholder for actual exports.
@@ -58,6 +58,7 @@ import {
58
58
  verifyFillRepayment,
59
59
  } from "./utils";
60
60
  import { UNDEFINED_MESSAGE_HASH } from "../../constants";
61
+ import { isEVMSpokePoolClient } from "../SpokePoolClient";
61
62
 
62
63
  // max(uint256) - 1
63
64
  export const INFINITE_FILL_DEADLINE = bnUint32Max;
@@ -388,9 +389,15 @@ export class BundleDataClient {
388
389
  await forEachAsync(fillsToCount, async (_fill) => {
389
390
  const matchingDeposit = this.spokePoolClients[_fill.originChainId].getDeposit(_fill.depositId);
390
391
  assert(isDefined(matchingDeposit), "Deposit not found for fill.");
392
+
393
+ const spokeClient = this.spokePoolClients[_fill.destinationChainId];
394
+ if (!isEVMSpokePoolClient(spokeClient)) {
395
+ // FIXME: Handle non-EVM chains.
396
+ throw new Error("Destination chain is not an EVM chain.");
397
+ }
391
398
  const fill = await verifyFillRepayment(
392
399
  _fill,
393
- this.spokePoolClients[_fill.destinationChainId].spokePool.provider,
400
+ spokeClient.spokePool.provider,
394
401
  matchingDeposit,
395
402
  this.clients.hubPoolClient
396
403
  );
@@ -890,6 +897,10 @@ export class BundleDataClient {
890
897
  assert(isDefined(deposits) && deposits.length > 0, "Deposit should exist in relay hash dictionary.");
891
898
  v3RelayHashes[relayDataHash].fill = fill;
892
899
  if (fill.blockNumber >= destinationChainBlockRange[0]) {
900
+ if (!isEVMSpokePoolClient(destinationClient)) {
901
+ // FIXME: Handle non-EVM chains.
902
+ throw new Error("Destination chain is not an EVM chain.");
903
+ }
893
904
  const fillToRefund = await verifyFillRepayment(
894
905
  fill,
895
906
  destinationClient.spokePool.provider,
@@ -989,6 +1000,11 @@ export class BundleDataClient {
989
1000
  }
990
1001
  v3RelayHashes[relayDataHash].deposits = [matchedDeposit];
991
1002
 
1003
+ if (!isEVMSpokePoolClient(destinationClient)) {
1004
+ // FIXME: Handle non-EVM chains.
1005
+ throw new Error("Destination chain is not an EVM chain.");
1006
+ }
1007
+
992
1008
  const fillToRefund = await verifyFillRepayment(
993
1009
  fill,
994
1010
  destinationClient.spokePool.provider,
@@ -1163,6 +1179,10 @@ export class BundleDataClient {
1163
1179
  // include this pre fill if the fill is in an older bundle.
1164
1180
  if (fill) {
1165
1181
  if (fill.blockNumber < destinationChainBlockRange[0]) {
1182
+ if (!isEVMSpokePoolClient(destinationClient)) {
1183
+ // FIXME: Handle non-EVM chains.
1184
+ throw new Error("Destination chain is not an EVM chain.");
1185
+ }
1166
1186
  const fillToRefund = await verifyFillRepayment(
1167
1187
  fill,
1168
1188
  destinationClient.spokePool.provider,
@@ -1215,6 +1235,10 @@ export class BundleDataClient {
1215
1235
  const prefill = await this.findMatchingFillEvent(deposit, destinationClient);
1216
1236
  assert(isDefined(prefill), `findFillEvent# Cannot find prefill: ${relayDataHash}`);
1217
1237
  assert(getRelayEventKey(prefill) === relayDataHash, "Relay hashes should match.");
1238
+ if (!isEVMSpokePoolClient(destinationClient)) {
1239
+ // FIXME: Handle non-EVM chains.
1240
+ throw new Error("Destination chain is not an EVM chain.");
1241
+ }
1218
1242
  const verifiedFill = await verifyFillRepayment(
1219
1243
  prefill,
1220
1244
  destinationClient.spokePool.provider,
@@ -1511,6 +1535,10 @@ export class BundleDataClient {
1511
1535
  deposit: DepositWithBlock,
1512
1536
  spokePoolClient: SpokePoolClient
1513
1537
  ): Promise<FillWithBlock | undefined> {
1538
+ if (!isEVMSpokePoolClient(spokePoolClient)) {
1539
+ // FIXME: Handle non-EVM chains.
1540
+ throw new Error("Destination chain is not an EVM chain.");
1541
+ }
1514
1542
  return await findFillEvent(
1515
1543
  spokePoolClient.spokePool,
1516
1544
  deposit,
@@ -0,0 +1,206 @@
1
+ import { Contract, EventFilter } from "ethers";
2
+ import { BigNumber, DepositSearchResult, getNetworkName, InvalidFill, MakeOptional, toBN } from "../../utils";
3
+ import {
4
+ EventSearchConfig,
5
+ paginatedEventQuery,
6
+ sortEventsAscendingInPlace,
7
+ spreadEventWithBlockNumber,
8
+ } from "../../utils/EventUtils";
9
+ import { isUpdateFailureReason } from "../BaseAbstractClient";
10
+ import { knownEventNames, SpokePoolClient, SpokePoolUpdate } from "./SpokePoolClient";
11
+ import winston from "winston";
12
+ import { HubPoolClient } from "../HubPoolClient";
13
+ import {
14
+ findDepositBlock,
15
+ getMaxFillDeadlineInRange as getMaxFillDeadline,
16
+ getTimeAt as _getTimeAt,
17
+ relayFillStatus,
18
+ isZeroAddress,
19
+ getTimestampForBlock as _getTimestampForBlock,
20
+ } from "../../utils/SpokeUtils";
21
+ import { DepositWithBlock, FillStatus, RelayData } from "../../interfaces";
22
+
23
+ /**
24
+ * An EVM-specific SpokePoolClient.
25
+ */
26
+ export class EVMSpokePoolClient extends SpokePoolClient {
27
+ constructor(
28
+ logger: winston.Logger,
29
+ public readonly spokePool: Contract,
30
+ hubPoolClient: HubPoolClient | null,
31
+ chainId: number,
32
+ deploymentBlock: number,
33
+ eventSearchConfig: MakeOptional<EventSearchConfig, "toBlock"> = { fromBlock: 0, maxBlockLookBack: 0 }
34
+ ) {
35
+ super(logger, hubPoolClient, chainId, deploymentBlock, eventSearchConfig);
36
+ }
37
+
38
+ public override relayFillStatus(
39
+ relayData: RelayData,
40
+ blockTag?: number | "latest",
41
+ destinationChainId?: number
42
+ ): Promise<FillStatus> {
43
+ return relayFillStatus(this.spokePool, relayData, blockTag, destinationChainId);
44
+ }
45
+
46
+ public override getMaxFillDeadlineInRange(startBlock: number, endBlock: number): Promise<number> {
47
+ return getMaxFillDeadline(this.spokePool, startBlock, endBlock);
48
+ }
49
+
50
+ private _availableEventsOnSpoke(eventNames: string[] = knownEventNames): { [eventName: string]: EventFilter } {
51
+ return Object.fromEntries(
52
+ this.spokePool.interface.fragments
53
+ .filter(({ name, type }) => type === "event" && eventNames.includes(name))
54
+ .map(({ name }) => [name, this.spokePool.filters[name]()])
55
+ );
56
+ }
57
+
58
+ public override _queryableEventNames(): string[] {
59
+ return Object.keys(this._availableEventsOnSpoke(knownEventNames));
60
+ }
61
+
62
+ protected override async _update(eventsToQuery: string[]): Promise<SpokePoolUpdate> {
63
+ const searchConfig = await this.updateSearchConfig(this.spokePool.provider);
64
+ if (isUpdateFailureReason(searchConfig)) {
65
+ const reason = searchConfig;
66
+ return { success: false, reason };
67
+ }
68
+
69
+ const eventSearchConfigs = eventsToQuery.map((eventName) => {
70
+ if (!this._queryableEventNames().includes(eventName)) {
71
+ throw new Error(`SpokePoolClient: Cannot query unrecognised SpokePool event name: ${eventName}`);
72
+ }
73
+
74
+ const _searchConfig = { ...searchConfig }; // shallow copy
75
+
76
+ // By default, an event's query range is controlled by the `eventSearchConfig` passed in during instantiation.
77
+ // However, certain events have special overriding requirements to their search ranges:
78
+ // - EnabledDepositRoute: The full history is always required, so override the requested fromBlock.
79
+ if (eventName === "EnabledDepositRoute" && !this.isUpdated) {
80
+ _searchConfig.fromBlock = this.deploymentBlock;
81
+ }
82
+
83
+ return {
84
+ filter: this._availableEventsOnSpoke()[eventName],
85
+ searchConfig: _searchConfig,
86
+ };
87
+ });
88
+
89
+ const { spokePool } = this;
90
+ this.log("debug", `Updating SpokePool client for chain ${this.chainId}`, {
91
+ eventsToQuery,
92
+ searchConfig,
93
+ spokePool: spokePool.address,
94
+ });
95
+
96
+ const timerStart = Date.now();
97
+ const multicallFunctions = ["getCurrentTime"];
98
+ const [multicallOutput, ...events] = await Promise.all([
99
+ spokePool.callStatic.multicall(
100
+ multicallFunctions.map((f) => spokePool.interface.encodeFunctionData(f)),
101
+ { blockTag: searchConfig.toBlock }
102
+ ),
103
+ ...eventSearchConfigs.map((config) => paginatedEventQuery(this.spokePool, config.filter, config.searchConfig)),
104
+ ]);
105
+ this.log("debug", `Time to query new events from RPC for ${this.chainId}: ${Date.now() - timerStart} ms`);
106
+
107
+ const [currentTime] = multicallFunctions.map(
108
+ (fn, idx) => spokePool.interface.decodeFunctionResult(fn, multicallOutput[idx])[0]
109
+ );
110
+
111
+ if (!BigNumber.isBigNumber(currentTime) || currentTime.lt(this.currentTime)) {
112
+ const errMsg = BigNumber.isBigNumber(currentTime)
113
+ ? `currentTime: ${currentTime} < ${toBN(this.currentTime)}`
114
+ : `currentTime is not a BigNumber: ${JSON.stringify(currentTime)}`;
115
+ throw new Error(`SpokePoolClient::update: ${errMsg}`);
116
+ }
117
+
118
+ // Sort all events to ensure they are stored in a consistent order.
119
+ events.forEach((events) => sortEventsAscendingInPlace(events));
120
+
121
+ return {
122
+ success: true,
123
+ currentTime: currentTime.toNumber(), // uint32
124
+ searchEndBlock: searchConfig.toBlock,
125
+ events,
126
+ };
127
+ }
128
+
129
+ public override getTimeAt(blockNumber: number): Promise<number> {
130
+ return _getTimeAt(this.spokePool, blockNumber);
131
+ }
132
+
133
+ public override async findDeposit(depositId: BigNumber): Promise<DepositSearchResult> {
134
+ let deposit = this.getDeposit(depositId);
135
+ if (deposit) {
136
+ return { found: true, deposit };
137
+ }
138
+
139
+ // No deposit found; revert to searching for it.
140
+ const upperBound = this.latestBlockSearched || undefined; // Don't permit block 0 as the high block.
141
+ const fromBlock = await findDepositBlock(this.spokePool, depositId, this.deploymentBlock, upperBound);
142
+ const chain = getNetworkName(this.chainId);
143
+ if (!fromBlock) {
144
+ const reason =
145
+ `Unable to find ${chain} depositId ${depositId}` +
146
+ ` within blocks [${this.deploymentBlock}, ${upperBound ?? "latest"}].`;
147
+ return { found: false, code: InvalidFill.DepositIdNotFound, reason };
148
+ }
149
+
150
+ const toBlock = fromBlock;
151
+ const tStart = Date.now();
152
+ // Check both V3FundsDeposited and FundsDeposited events to look for a specified depositId.
153
+ const { maxBlockLookBack } = this.eventSearchConfig;
154
+ const query = (
155
+ await Promise.all([
156
+ paginatedEventQuery(
157
+ this.spokePool,
158
+ this.spokePool.filters.V3FundsDeposited(null, null, null, null, null, depositId),
159
+ { fromBlock, toBlock, maxBlockLookBack }
160
+ ),
161
+ paginatedEventQuery(
162
+ this.spokePool,
163
+ this.spokePool.filters.FundsDeposited(null, null, null, null, null, depositId),
164
+ { fromBlock, toBlock, maxBlockLookBack }
165
+ ),
166
+ ])
167
+ ).flat();
168
+ const tStop = Date.now();
169
+
170
+ const event = query.find(({ args }) => args["depositId"].eq(depositId));
171
+ if (event === undefined) {
172
+ return {
173
+ found: false,
174
+ code: InvalidFill.DepositIdNotFound,
175
+ reason: `${chain} depositId ${depositId} not found at block ${fromBlock}.`,
176
+ };
177
+ }
178
+
179
+ deposit = {
180
+ ...spreadEventWithBlockNumber(event),
181
+ originChainId: this.chainId,
182
+ quoteBlockNumber: await this.getBlockNumber(Number(event.args["quoteTimestamp"])),
183
+ fromLiteChain: true, // To be updated immediately afterwards.
184
+ toLiteChain: true, // To be updated immediately afterwards.
185
+ } as DepositWithBlock;
186
+
187
+ if (isZeroAddress(deposit.outputToken)) {
188
+ deposit.outputToken = this.getDestinationTokenForDeposit(deposit);
189
+ }
190
+ deposit.fromLiteChain = this.isOriginLiteChain(deposit);
191
+ deposit.toLiteChain = this.isDestinationLiteChain(deposit);
192
+
193
+ this.logger.debug({
194
+ at: "SpokePoolClient#findDeposit",
195
+ message: "Located V3 deposit outside of SpokePoolClient's search range",
196
+ deposit,
197
+ elapsedMs: tStop - tStart,
198
+ });
199
+
200
+ return { found: true, deposit };
201
+ }
202
+
203
+ public override getTimestampForBlock(blockNumber: number): Promise<number> {
204
+ return _getTimestampForBlock(this.spokePool.provider, blockNumber);
205
+ }
206
+ }