@across-protocol/sdk 4.3.53 → 4.3.55
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.
- package/dist/cjs/arch/evm/SpokeUtils.js +2 -3
- package/dist/cjs/arch/evm/SpokeUtils.js.map +1 -1
- package/dist/cjs/arch/svm/SpokeUtils.d.ts +1 -1
- package/dist/cjs/arch/svm/SpokeUtils.js +24 -23
- package/dist/cjs/arch/svm/SpokeUtils.js.map +1 -1
- package/dist/cjs/clients/BundleDataClient/utils/SuperstructUtils.d.ts +60 -60
- package/dist/cjs/clients/HubPoolClient.js +28 -32
- package/dist/cjs/clients/HubPoolClient.js.map +1 -1
- package/dist/cjs/clients/SpokePoolClient/EVMSpokePoolClient.js +12 -17
- package/dist/cjs/clients/SpokePoolClient/EVMSpokePoolClient.js.map +1 -1
- package/dist/cjs/clients/SpokePoolClient/SVMSpokePoolClient.js +4 -3
- package/dist/cjs/clients/SpokePoolClient/SVMSpokePoolClient.js.map +1 -1
- package/dist/cjs/clients/SpokePoolClient/SpokePoolClient.d.ts +4 -4
- package/dist/cjs/clients/SpokePoolClient/SpokePoolClient.js +15 -23
- package/dist/cjs/clients/SpokePoolClient/SpokePoolClient.js.map +1 -1
- package/dist/cjs/constants.d.ts +1 -1
- package/dist/cjs/constants.js +1 -1
- package/dist/cjs/utils/SpokeUtils.d.ts +3 -1
- package/dist/cjs/utils/SpokeUtils.js +12 -1
- package/dist/cjs/utils/SpokeUtils.js.map +1 -1
- package/dist/esm/arch/evm/SpokeUtils.js +5 -6
- package/dist/esm/arch/evm/SpokeUtils.js.map +1 -1
- package/dist/esm/arch/svm/SpokeUtils.d.ts +1 -1
- package/dist/esm/arch/svm/SpokeUtils.js +26 -26
- package/dist/esm/arch/svm/SpokeUtils.js.map +1 -1
- package/dist/esm/clients/BundleDataClient/utils/SuperstructUtils.d.ts +60 -60
- package/dist/esm/clients/HubPoolClient.js +29 -34
- package/dist/esm/clients/HubPoolClient.js.map +1 -1
- package/dist/esm/clients/SpokePoolClient/EVMSpokePoolClient.js +13 -18
- package/dist/esm/clients/SpokePoolClient/EVMSpokePoolClient.js.map +1 -1
- package/dist/esm/clients/SpokePoolClient/SVMSpokePoolClient.js +4 -6
- package/dist/esm/clients/SpokePoolClient/SVMSpokePoolClient.js.map +1 -1
- package/dist/esm/clients/SpokePoolClient/SpokePoolClient.d.ts +4 -4
- package/dist/esm/clients/SpokePoolClient/SpokePoolClient.js +16 -24
- package/dist/esm/clients/SpokePoolClient/SpokePoolClient.js.map +1 -1
- package/dist/esm/constants.d.ts +1 -1
- package/dist/esm/constants.js +1 -1
- package/dist/esm/utils/SpokeUtils.d.ts +16 -1
- package/dist/esm/utils/SpokeUtils.js +24 -2
- package/dist/esm/utils/SpokeUtils.js.map +1 -1
- package/dist/types/arch/evm/SpokeUtils.d.ts.map +1 -1
- package/dist/types/arch/svm/SpokeUtils.d.ts +1 -1
- package/dist/types/arch/svm/SpokeUtils.d.ts.map +1 -1
- package/dist/types/clients/BundleDataClient/utils/SuperstructUtils.d.ts +60 -60
- package/dist/types/clients/HubPoolClient.d.ts.map +1 -1
- package/dist/types/clients/SpokePoolClient/EVMSpokePoolClient.d.ts.map +1 -1
- package/dist/types/clients/SpokePoolClient/SVMSpokePoolClient.d.ts.map +1 -1
- package/dist/types/clients/SpokePoolClient/SpokePoolClient.d.ts +4 -4
- package/dist/types/clients/SpokePoolClient/SpokePoolClient.d.ts.map +1 -1
- package/dist/types/constants.d.ts +1 -1
- package/dist/types/utils/SpokeUtils.d.ts +16 -1
- package/dist/types/utils/SpokeUtils.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/arch/evm/SpokeUtils.ts +4 -35
- package/src/arch/svm/SpokeUtils.ts +26 -59
- package/src/clients/HubPoolClient.ts +34 -28
- package/src/clients/SpokePoolClient/EVMSpokePoolClient.ts +12 -31
- package/src/clients/SpokePoolClient/SVMSpokePoolClient.ts +5 -4
- package/src/clients/SpokePoolClient/SpokePoolClient.ts +31 -92
- package/src/constants.ts +1 -1
- package/src/utils/SpokeUtils.ts +98 -2
|
@@ -193,14 +193,14 @@ export class HubPoolClient extends BaseAbstractClient {
|
|
|
193
193
|
destinationChainId: number,
|
|
194
194
|
latestHubBlock = Number.MAX_SAFE_INTEGER
|
|
195
195
|
): Address {
|
|
196
|
-
if (!this.l1TokensToDestinationTokensWithBlock?.[l1Token.
|
|
196
|
+
if (!this.l1TokensToDestinationTokensWithBlock?.[l1Token.toNative()]?.[destinationChainId]) {
|
|
197
197
|
const chain = getNetworkName(destinationChainId);
|
|
198
198
|
const { symbol } = this.l1Tokens.find(({ address }) => address.eq(l1Token)) ?? { symbol: l1Token.toString() };
|
|
199
199
|
throw new Error(`Could not find SpokePool mapping for ${symbol} on ${chain} and L1 token ${l1Token}`);
|
|
200
200
|
}
|
|
201
201
|
// Find the last mapping published before the target block.
|
|
202
202
|
const l2Token: DestinationTokenWithBlock | undefined = sortEventsDescending(
|
|
203
|
-
this.l1TokensToDestinationTokensWithBlock[l1Token.
|
|
203
|
+
this.l1TokensToDestinationTokensWithBlock[l1Token.toNative()][destinationChainId]
|
|
204
204
|
).find((mapping: DestinationTokenWithBlock) => mapping.blockNumber <= latestHubBlock);
|
|
205
205
|
if (!l2Token) {
|
|
206
206
|
const chain = getNetworkName(destinationChainId);
|
|
@@ -250,13 +250,13 @@ export class HubPoolClient extends BaseAbstractClient {
|
|
|
250
250
|
}
|
|
251
251
|
|
|
252
252
|
l2TokenEnabledForL1Token(l1Token: EvmAddress, destinationChainId: number): boolean {
|
|
253
|
-
return this.l1TokensToDestinationTokens?.[l1Token.
|
|
253
|
+
return this.l1TokensToDestinationTokens?.[l1Token.toNative()]?.[destinationChainId] != undefined;
|
|
254
254
|
}
|
|
255
255
|
|
|
256
256
|
l2TokenEnabledForL1TokenAtBlock(l1Token: EvmAddress, destinationChainId: number, hubBlockNumber: number): boolean {
|
|
257
257
|
// Find the last mapping published before the target block.
|
|
258
258
|
const l2Token: DestinationTokenWithBlock | undefined = sortEventsDescending(
|
|
259
|
-
this.l1TokensToDestinationTokensWithBlock?.[l1Token.
|
|
259
|
+
this.l1TokensToDestinationTokensWithBlock?.[l1Token.toNative()]?.[destinationChainId] ?? []
|
|
260
260
|
).find((mapping: DestinationTokenWithBlock) => mapping.blockNumber <= hubBlockNumber);
|
|
261
261
|
return l2Token !== undefined;
|
|
262
262
|
}
|
|
@@ -340,18 +340,14 @@ export class HubPoolClient extends BaseAbstractClient {
|
|
|
340
340
|
timeToCache: number
|
|
341
341
|
): Promise<BigNumber> {
|
|
342
342
|
// Resolve this function call as an async anonymous function
|
|
343
|
-
const resolver =
|
|
343
|
+
const resolver = () => {
|
|
344
344
|
const overrides = { blockTag: blockNumber };
|
|
345
|
-
|
|
346
|
-
// For zero amount, just get the utilisation at `blockNumber`.
|
|
347
|
-
return await this.hubPool.callStatic.liquidityUtilizationCurrent(hubPoolToken.toEvmAddress(), overrides);
|
|
348
|
-
}
|
|
345
|
+
const token = hubPoolToken.toNative();
|
|
349
346
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
overrides
|
|
354
|
-
);
|
|
347
|
+
// For zero amount, just get the utilisation at `blockNumber`.
|
|
348
|
+
return depositAmount.eq(bnZero)
|
|
349
|
+
? this.hubPool.callStatic.liquidityUtilizationCurrent(token, overrides)
|
|
350
|
+
: this.hubPool.callStatic.liquidityUtilizationPostRelay(token, depositAmount, overrides);
|
|
355
351
|
};
|
|
356
352
|
|
|
357
353
|
// Resolve the cache locally so that we can appease typescript
|
|
@@ -363,11 +359,9 @@ export class HubPoolClient extends BaseAbstractClient {
|
|
|
363
359
|
}
|
|
364
360
|
|
|
365
361
|
// Otherwise, let's resolve the key
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
? `utilization_${hubPoolToken.toEvmAddress()}_${blockNumber}`
|
|
370
|
-
: `utilization_${hubPoolToken.toEvmAddress()}_${blockNumber}_${depositAmount.toString()}_`;
|
|
362
|
+
const key = depositAmount.eq(bnZero)
|
|
363
|
+
? `utilization_${hubPoolToken.toNative()}_${blockNumber}`
|
|
364
|
+
: `utilization_${hubPoolToken.toNative()}_${blockNumber}_${depositAmount.toString()}`;
|
|
371
365
|
const result = await cache.get<string>(key);
|
|
372
366
|
if (isDefined(result)) {
|
|
373
367
|
return BigNumber.from(result);
|
|
@@ -409,9 +403,19 @@ export class HubPoolClient extends BaseAbstractClient {
|
|
|
409
403
|
const tokenKey = `${deposit.originChainId}-${deposit.inputToken}`;
|
|
410
404
|
if (this.l2TokenHasPoolRebalanceRoute(deposit.inputToken, deposit.originChainId, quoteBlockNumber)) {
|
|
411
405
|
return (hubPoolTokens[tokenKey] ??= this.getL1TokenForDeposit({ ...deposit, quoteBlockNumber }));
|
|
412
|
-
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
return undefined;
|
|
413
409
|
};
|
|
414
|
-
|
|
410
|
+
|
|
411
|
+
// Filter hubPoolTokens for duplicates by reverting to their native string
|
|
412
|
+
// representation. This is required for deduplication to work reliably.
|
|
413
|
+
const getHubPoolTokens = (): EvmAddress[] =>
|
|
414
|
+
dedupArray(
|
|
415
|
+
Object.values(hubPoolTokens)
|
|
416
|
+
.filter(isDefined)
|
|
417
|
+
.map((token) => token.toNative())
|
|
418
|
+
).map((token) => EvmAddress.from(token));
|
|
415
419
|
|
|
416
420
|
// Helper to resolve the unqiue hubPoolToken & quoteTimestamp mappings.
|
|
417
421
|
const resolveUniqueQuoteTimestamps = (deposit: LpFeeRequest): void => {
|
|
@@ -425,9 +429,10 @@ export class HubPoolClient extends BaseAbstractClient {
|
|
|
425
429
|
}
|
|
426
430
|
|
|
427
431
|
// Append the quoteTimestamp for this HubPool token, if it isn't already enqueued.
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
432
|
+
const token = hubPoolToken.toNative();
|
|
433
|
+
utilizationTimestamps[token] ??= [];
|
|
434
|
+
if (!utilizationTimestamps[token].includes(quoteTimestamp)) {
|
|
435
|
+
utilizationTimestamps[token].push(quoteTimestamp);
|
|
431
436
|
}
|
|
432
437
|
};
|
|
433
438
|
|
|
@@ -435,7 +440,7 @@ export class HubPoolClient extends BaseAbstractClient {
|
|
|
435
440
|
// Produces a mapping of blockNumber -> utilization for a specific token.
|
|
436
441
|
const resolveUtilization = async (hubPoolToken: EvmAddress): Promise<Record<number, BigNumber>> => {
|
|
437
442
|
return Object.fromEntries(
|
|
438
|
-
await mapAsync(utilizationTimestamps[hubPoolToken.
|
|
443
|
+
await mapAsync(utilizationTimestamps[hubPoolToken.toNative()], async (quoteTimestamp) => {
|
|
439
444
|
const blockNumber = quoteBlocks[quoteTimestamp];
|
|
440
445
|
const utilization = await this.getUtilization(
|
|
441
446
|
hubPoolToken,
|
|
@@ -471,7 +476,7 @@ export class HubPoolClient extends BaseAbstractClient {
|
|
|
471
476
|
quoteBlock
|
|
472
477
|
);
|
|
473
478
|
|
|
474
|
-
const preUtilization = utilization[hubPoolToken.
|
|
479
|
+
const preUtilization = utilization[hubPoolToken.toNative()][quoteBlock];
|
|
475
480
|
const postUtilization = await this.getUtilization(
|
|
476
481
|
hubPoolToken,
|
|
477
482
|
quoteBlock,
|
|
@@ -500,7 +505,7 @@ export class HubPoolClient extends BaseAbstractClient {
|
|
|
500
505
|
// This can be reused for each deposit with the same HubPool token and quoteTimestamp pair.
|
|
501
506
|
utilization = Object.fromEntries(
|
|
502
507
|
await mapAsync(getHubPoolTokens(), async (hubPoolToken) => [
|
|
503
|
-
hubPoolToken.
|
|
508
|
+
hubPoolToken.toNative(),
|
|
504
509
|
await resolveUtilization(hubPoolToken),
|
|
505
510
|
])
|
|
506
511
|
);
|
|
@@ -529,7 +534,7 @@ export class HubPoolClient extends BaseAbstractClient {
|
|
|
529
534
|
}
|
|
530
535
|
|
|
531
536
|
getLpTokenInfoForL1Token(l1Token: EvmAddress): LpToken | undefined {
|
|
532
|
-
return this.lpTokens[l1Token.
|
|
537
|
+
return this.lpTokens[l1Token.toNative()];
|
|
533
538
|
}
|
|
534
539
|
|
|
535
540
|
areTokensEquivalent(
|
|
@@ -925,6 +930,7 @@ export class HubPoolClient extends BaseAbstractClient {
|
|
|
925
930
|
if (!this.configStoreClient.isUpdated) {
|
|
926
931
|
throw new Error("ConfigStoreClient not updated");
|
|
927
932
|
}
|
|
933
|
+
|
|
928
934
|
const update = await this._update(eventsToQuery);
|
|
929
935
|
if (!update.success) {
|
|
930
936
|
if (update.reason !== UpdateFailureReason.AlreadyUpdated) {
|
|
@@ -11,13 +11,12 @@ import { DepositWithBlock, FillStatus, RelayData } from "../../interfaces";
|
|
|
11
11
|
import {
|
|
12
12
|
BigNumber,
|
|
13
13
|
DepositSearchResult,
|
|
14
|
-
getMessageHash,
|
|
15
14
|
getNetworkName,
|
|
16
15
|
InvalidFill,
|
|
17
16
|
MakeOptional,
|
|
18
17
|
toBN,
|
|
19
18
|
EvmAddress,
|
|
20
|
-
|
|
19
|
+
unpackDepositEvent,
|
|
21
20
|
} from "../../utils";
|
|
22
21
|
import {
|
|
23
22
|
EventSearchConfig,
|
|
@@ -195,37 +194,19 @@ export class EVMSpokePoolClient extends SpokePoolClient {
|
|
|
195
194
|
};
|
|
196
195
|
}
|
|
197
196
|
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
outputToken: string;
|
|
204
|
-
depositor: string;
|
|
205
|
-
recipient: string;
|
|
206
|
-
exclusiveRelayer: string;
|
|
207
|
-
};
|
|
197
|
+
const partialDeposit = unpackDepositEvent(spreadEventWithBlockNumber(event), this.chainId);
|
|
198
|
+
const quoteBlockNumber = await this.getBlockNumber(partialDeposit.quoteTimestamp);
|
|
199
|
+
const outputToken = partialDeposit.outputToken.isZeroAddress()
|
|
200
|
+
? this.getDestinationTokenForDeposit({ ...partialDeposit, quoteBlockNumber })
|
|
201
|
+
: partialDeposit.outputToken;
|
|
208
202
|
|
|
209
|
-
const originChainId = this.chainId;
|
|
210
203
|
deposit = {
|
|
211
|
-
...
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
exclusiveRelayer: toAddressType(spreadEvent.exclusiveRelayer, spreadEvent.destinationChainId),
|
|
218
|
-
quoteBlockNumber: await this.getBlockNumber(spreadEvent.quoteTimestamp),
|
|
219
|
-
messageHash: getMessageHash(spreadEvent.message),
|
|
220
|
-
fromLiteChain: true, // To be updated immediately afterwards.
|
|
221
|
-
toLiteChain: true, // To be updated immediately afterwards.
|
|
222
|
-
};
|
|
223
|
-
|
|
224
|
-
if (deposit.outputToken.isZeroAddress()) {
|
|
225
|
-
deposit.outputToken = this.getDestinationTokenForDeposit(deposit);
|
|
226
|
-
}
|
|
227
|
-
deposit.fromLiteChain = this.isOriginLiteChain(deposit);
|
|
228
|
-
deposit.toLiteChain = this.isDestinationLiteChain(deposit);
|
|
204
|
+
...partialDeposit,
|
|
205
|
+
outputToken,
|
|
206
|
+
quoteBlockNumber,
|
|
207
|
+
fromLiteChain: this.isOriginLiteChain(partialDeposit),
|
|
208
|
+
toLiteChain: this.isDestinationLiteChain(partialDeposit),
|
|
209
|
+
} satisfies DepositWithBlock;
|
|
229
210
|
|
|
230
211
|
this.logger.debug({
|
|
231
212
|
at: "SpokePoolClient#findDeposit",
|
|
@@ -227,15 +227,16 @@ export class SVMSpokePoolClient extends SpokePoolClient {
|
|
|
227
227
|
};
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
-
// Because we have additional context about this deposit, we can enrich it
|
|
231
|
-
//
|
|
230
|
+
// Because we have additional context about this deposit, we can enrich it with additional information.
|
|
231
|
+
// outputToken is known to not be 0x0 on SVM SpokePool implementations.
|
|
232
|
+
const originChainId = this.chainId;
|
|
232
233
|
return {
|
|
233
234
|
found: true,
|
|
234
235
|
deposit: {
|
|
235
236
|
...deposit,
|
|
237
|
+
originChainId,
|
|
236
238
|
quoteBlockNumber: await this.getBlockNumber(Number(deposit.quoteTimestamp)),
|
|
237
|
-
|
|
238
|
-
fromLiteChain: this.isOriginLiteChain(deposit),
|
|
239
|
+
fromLiteChain: this.isOriginLiteChain({ ...deposit, originChainId }),
|
|
239
240
|
toLiteChain: this.isDestinationLiteChain(deposit),
|
|
240
241
|
},
|
|
241
242
|
};
|
|
@@ -13,13 +13,14 @@ import {
|
|
|
13
13
|
assign,
|
|
14
14
|
getRelayEventKey,
|
|
15
15
|
isDefined,
|
|
16
|
-
getMessageHash,
|
|
17
16
|
isSlowFill,
|
|
18
17
|
validateFillForDeposit,
|
|
19
18
|
chainIsEvm,
|
|
20
19
|
chainIsProd,
|
|
21
20
|
Address,
|
|
22
21
|
toAddressType,
|
|
22
|
+
unpackDepositEvent,
|
|
23
|
+
unpackFillEvent,
|
|
23
24
|
} from "../../utils";
|
|
24
25
|
import { duplicateEvent, sortEventsAscendingInPlace } from "../../utils/EventUtils";
|
|
25
26
|
import { CHAIN_IDs, ZERO_ADDRESS } from "../../constants";
|
|
@@ -39,7 +40,6 @@ import {
|
|
|
39
40
|
SortableEvent,
|
|
40
41
|
SpeedUpWithBlock,
|
|
41
42
|
TokensBridged,
|
|
42
|
-
RelayExecutionEventInfo,
|
|
43
43
|
} from "../../interfaces";
|
|
44
44
|
import { BaseAbstractClient, UpdateFailureReason } from "../BaseAbstractClient";
|
|
45
45
|
import { AcrossConfigStoreClient } from "../AcrossConfigStoreClient";
|
|
@@ -463,7 +463,9 @@ export abstract class SpokePoolClient extends BaseAbstractClient {
|
|
|
463
463
|
return `${event.depositId.toString()}-${event.originChainId}`;
|
|
464
464
|
}
|
|
465
465
|
|
|
466
|
-
protected canResolveZeroAddressOutputToken(
|
|
466
|
+
protected canResolveZeroAddressOutputToken(
|
|
467
|
+
deposit: Pick<DepositWithBlock, "originChainId" | "inputToken" | "quoteBlockNumber" | "destinationChainId">
|
|
468
|
+
): boolean {
|
|
467
469
|
if (
|
|
468
470
|
!this.hubPoolClient?.l2TokenHasPoolRebalanceRoute(
|
|
469
471
|
deposit.inputToken,
|
|
@@ -519,39 +521,10 @@ export abstract class SpokePoolClient extends BaseAbstractClient {
|
|
|
519
521
|
}
|
|
520
522
|
|
|
521
523
|
// Performs the indexing of a deposit-like spoke pool event.
|
|
522
|
-
const originChainId = this.chainId;
|
|
523
524
|
const queryDepositEvents = async (eventName: string) => {
|
|
524
|
-
const depositEvents = (queryResults[eventsToQuery.indexOf(eventName)] ?? []).map((
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
"originChainId" | "depositor" | "recipient" | "inputToken" | "outputToken" | "exclusiveRelayer"
|
|
528
|
-
> & {
|
|
529
|
-
depositor: string;
|
|
530
|
-
recipient: string;
|
|
531
|
-
inputToken: string;
|
|
532
|
-
outputToken: string;
|
|
533
|
-
exclusiveRelayer: string;
|
|
534
|
-
};
|
|
535
|
-
return {
|
|
536
|
-
...event,
|
|
537
|
-
originChainId,
|
|
538
|
-
depositor: toAddressType(event.depositor, originChainId),
|
|
539
|
-
recipient: toAddressType(event.recipient, event.destinationChainId),
|
|
540
|
-
inputToken: toAddressType(event.inputToken, originChainId),
|
|
541
|
-
outputToken: toAddressType(event.outputToken, event.destinationChainId),
|
|
542
|
-
exclusiveRelayer: toAddressType(event.exclusiveRelayer, event.destinationChainId),
|
|
543
|
-
messageHash: getMessageHash(event.message),
|
|
544
|
-
} satisfies Omit<DepositWithBlock, "quoteBlockNumber" | "fromLiteChain" | "toLiteChain">;
|
|
545
|
-
});
|
|
546
|
-
if (depositEvents.length > 0) {
|
|
547
|
-
this.log(
|
|
548
|
-
"debug",
|
|
549
|
-
`Using ${depositEvents.length} newly queried ${eventName} deposit events for chain ${this.chainId}`,
|
|
550
|
-
{
|
|
551
|
-
earliestEvent: depositEvents[0].blockNumber,
|
|
552
|
-
}
|
|
553
|
-
);
|
|
554
|
-
}
|
|
525
|
+
const depositEvents = (queryResults[eventsToQuery.indexOf(eventName)] ?? []).map((event) =>
|
|
526
|
+
unpackDepositEvent(event, this.chainId)
|
|
527
|
+
);
|
|
555
528
|
|
|
556
529
|
// For each deposit, resolve its quoteTimestamp to a block number on the HubPool.
|
|
557
530
|
// Don't bother filtering for uniqueness; the HubPoolClient handles this efficienctly.
|
|
@@ -560,16 +533,17 @@ export abstract class SpokePoolClient extends BaseAbstractClient {
|
|
|
560
533
|
const quoteBlockNumber = quoteBlockNumbers[Number(event.quoteTimestamp)];
|
|
561
534
|
|
|
562
535
|
// Derive and append the common properties that are not part of the onchain event.
|
|
536
|
+
const outputToken = event.outputToken.isZeroAddress()
|
|
537
|
+
? this.getDestinationTokenForDeposit({ ...event, quoteBlockNumber })
|
|
538
|
+
: event.outputToken;
|
|
539
|
+
|
|
563
540
|
const deposit = {
|
|
564
541
|
...event,
|
|
542
|
+
outputToken,
|
|
565
543
|
quoteBlockNumber,
|
|
566
544
|
fromLiteChain: this.isOriginLiteChain(event),
|
|
567
545
|
toLiteChain: this.isDestinationLiteChain(event),
|
|
568
|
-
};
|
|
569
|
-
|
|
570
|
-
if (deposit.outputToken.isZeroAddress()) {
|
|
571
|
-
deposit.outputToken = this.getDestinationTokenForDeposit(deposit);
|
|
572
|
-
}
|
|
546
|
+
} satisfies DepositWithBlock;
|
|
573
547
|
|
|
574
548
|
if (this.depositHashes[getRelayEventKey(deposit)] !== undefined) {
|
|
575
549
|
// Sanity check that this event is not a duplicate, even though the relay data hash is a duplicate.
|
|
@@ -645,6 +619,7 @@ export abstract class SpokePoolClient extends BaseAbstractClient {
|
|
|
645
619
|
|
|
646
620
|
// Performs indexing of "requested slow fill"-like events.
|
|
647
621
|
const queryRequestedSlowFillEvents = (eventName: string) => {
|
|
622
|
+
const destinationChainId = this.chainId;
|
|
648
623
|
const slowFillRequests = (queryResults[eventsToQuery.indexOf(eventName)] ?? []).map((_event) => {
|
|
649
624
|
const event = _event as Omit<
|
|
650
625
|
SlowFillRequestWithBlock,
|
|
@@ -658,24 +633,21 @@ export abstract class SpokePoolClient extends BaseAbstractClient {
|
|
|
658
633
|
};
|
|
659
634
|
return {
|
|
660
635
|
...event,
|
|
636
|
+
destinationChainId,
|
|
661
637
|
depositor: toAddressType(event.depositor, event.originChainId),
|
|
662
|
-
recipient: toAddressType(event.recipient,
|
|
638
|
+
recipient: toAddressType(event.recipient, destinationChainId),
|
|
663
639
|
inputToken: toAddressType(event.inputToken, event.originChainId),
|
|
664
|
-
outputToken: toAddressType(event.outputToken,
|
|
665
|
-
exclusiveRelayer: toAddressType(event.exclusiveRelayer,
|
|
666
|
-
}
|
|
640
|
+
outputToken: toAddressType(event.outputToken, destinationChainId),
|
|
641
|
+
exclusiveRelayer: toAddressType(event.exclusiveRelayer, destinationChainId),
|
|
642
|
+
} satisfies SlowFillRequestWithBlock;
|
|
667
643
|
});
|
|
668
|
-
for (const event of slowFillRequests) {
|
|
669
|
-
const slowFillRequest = {
|
|
670
|
-
...event,
|
|
671
|
-
destinationChainId: this.chainId,
|
|
672
|
-
};
|
|
673
644
|
|
|
674
|
-
|
|
645
|
+
for (const slowFillRequest of slowFillRequests) {
|
|
646
|
+
const depositHash = getRelayEventKey(slowFillRequest);
|
|
675
647
|
|
|
676
648
|
// Sanity check that this event is not a duplicate.
|
|
677
649
|
if (this.slowFillRequests[depositHash] !== undefined) {
|
|
678
|
-
duplicateEvents.push(
|
|
650
|
+
duplicateEvents.push(slowFillRequest);
|
|
679
651
|
continue;
|
|
680
652
|
}
|
|
681
653
|
|
|
@@ -690,45 +662,10 @@ export abstract class SpokePoolClient extends BaseAbstractClient {
|
|
|
690
662
|
});
|
|
691
663
|
|
|
692
664
|
// Performs indexing of filled relay-like events.
|
|
693
|
-
const destinationChainId = this.chainId;
|
|
694
665
|
const queryFilledRelayEvents = (eventName: string) => {
|
|
695
|
-
const fillEvents = (queryResults[eventsToQuery.indexOf(eventName)] ?? []).map((
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
| "destinationChainId"
|
|
699
|
-
| "depositor"
|
|
700
|
-
| "recipient"
|
|
701
|
-
| "inputToken"
|
|
702
|
-
| "outputToken"
|
|
703
|
-
| "exclusiveRelayer"
|
|
704
|
-
| "relayer"
|
|
705
|
-
| "relayExecutionInfo"
|
|
706
|
-
> & {
|
|
707
|
-
depositor: string;
|
|
708
|
-
recipient: string;
|
|
709
|
-
inputToken: string;
|
|
710
|
-
outputToken: string;
|
|
711
|
-
exclusiveRelayer: string;
|
|
712
|
-
relayer: string;
|
|
713
|
-
relayExecutionInfo: Omit<RelayExecutionEventInfo, "updatedRecipient"> & { updatedRecipient: string };
|
|
714
|
-
};
|
|
715
|
-
|
|
716
|
-
return {
|
|
717
|
-
...event,
|
|
718
|
-
destinationChainId,
|
|
719
|
-
depositor: toAddressType(event.depositor, event.originChainId),
|
|
720
|
-
recipient: toAddressType(event.recipient, destinationChainId),
|
|
721
|
-
inputToken: toAddressType(event.inputToken, event.originChainId),
|
|
722
|
-
outputToken: toAddressType(event.outputToken, destinationChainId),
|
|
723
|
-
exclusiveRelayer: toAddressType(event.exclusiveRelayer, destinationChainId),
|
|
724
|
-
relayer: toAddressType(event.relayer, event.repaymentChainId),
|
|
725
|
-
relayExecutionInfo: {
|
|
726
|
-
...event.relayExecutionInfo,
|
|
727
|
-
updatedRecipient: toAddressType(event.relayExecutionInfo.updatedRecipient, this.chainId),
|
|
728
|
-
},
|
|
729
|
-
} satisfies FillWithBlock;
|
|
730
|
-
});
|
|
731
|
-
|
|
666
|
+
const fillEvents = (queryResults[eventsToQuery.indexOf(eventName)] ?? []).map((event) =>
|
|
667
|
+
unpackFillEvent(event, this.chainId)
|
|
668
|
+
);
|
|
732
669
|
if (fillEvents.length > 0) {
|
|
733
670
|
this.log("debug", `Using ${fillEvents.length} newly queried ${eventName} events for chain ${this.chainId}`, {
|
|
734
671
|
earliestEvent: fillEvents[0].blockNumber,
|
|
@@ -858,7 +795,9 @@ export abstract class SpokePoolClient extends BaseAbstractClient {
|
|
|
858
795
|
* @param deposit The deposit to retrieve the destination token for.
|
|
859
796
|
* @returns The destination token.
|
|
860
797
|
*/
|
|
861
|
-
protected getDestinationTokenForDeposit(
|
|
798
|
+
protected getDestinationTokenForDeposit(
|
|
799
|
+
deposit: Pick<DepositWithBlock, "originChainId" | "inputToken" | "quoteBlockNumber" | "destinationChainId">
|
|
800
|
+
): Address {
|
|
862
801
|
if (!this.canResolveZeroAddressOutputToken(deposit)) {
|
|
863
802
|
return toAddressType(ZERO_ADDRESS, CHAIN_IDs.MAINNET);
|
|
864
803
|
}
|
|
@@ -900,7 +839,7 @@ export abstract class SpokePoolClient extends BaseAbstractClient {
|
|
|
900
839
|
* @returns True if the deposit originates from a lite chain, false otherwise. If the hub pool client is not defined,
|
|
901
840
|
* this method will return false.
|
|
902
841
|
*/
|
|
903
|
-
protected isOriginLiteChain(deposit: DepositWithBlock): boolean {
|
|
842
|
+
protected isOriginLiteChain(deposit: Pick<DepositWithBlock, "originChainId" | "quoteTimestamp">): boolean {
|
|
904
843
|
return this.configStoreClient?.isChainLiteChainAtTimestamp(deposit.originChainId, deposit.quoteTimestamp) ?? false;
|
|
905
844
|
}
|
|
906
845
|
|
|
@@ -910,7 +849,7 @@ export abstract class SpokePoolClient extends BaseAbstractClient {
|
|
|
910
849
|
* @returns True if the deposit is destined to a lite chain, false otherwise. If the hub pool client is not defined,
|
|
911
850
|
* this method will return false.
|
|
912
851
|
*/
|
|
913
|
-
protected isDestinationLiteChain(deposit: DepositWithBlock): boolean {
|
|
852
|
+
protected isDestinationLiteChain(deposit: Pick<DepositWithBlock, "destinationChainId" | "quoteTimestamp">): boolean {
|
|
914
853
|
return (
|
|
915
854
|
this.configStoreClient?.isChainLiteChainAtTimestamp(deposit.destinationChainId, deposit.quoteTimestamp) ?? false
|
|
916
855
|
);
|
package/src/constants.ts
CHANGED
|
@@ -57,7 +57,7 @@ export const DEFAULT_CACHING_TTL = 60 * 60 * 24 * 7 * 2; // 2 Weeks
|
|
|
57
57
|
export const DEFAULT_CACHING_SAFE_LAG = 60 * 60; // 1 hour
|
|
58
58
|
|
|
59
59
|
export const DEFAULT_SIMULATED_RELAYER_ADDRESS = "0x07aE8551Be970cB1cCa11Dd7a11F47Ae82e70E67";
|
|
60
|
-
export const DEFAULT_SIMULATED_RELAYER_ADDRESS_SVM = "
|
|
60
|
+
export const DEFAULT_SIMULATED_RELAYER_ADDRESS_SVM = "E4bX4nCwe2GcKqt9NpofnXVrCeRp37PAMaiZtV9x3kxC";
|
|
61
61
|
export const DEFAULT_SIMULATED_RELAYER_ADDRESS_TEST = "0x9A8f92a830A5cB89a3816e3D267CB7791c16b04D"; // Görli, ...
|
|
62
62
|
|
|
63
63
|
export const DEFAULT_ARWEAVE_STORAGE_ADDRESS = "Z6hjBM8FHu90lYWB8o5jR1dfX92FlV2WBaND9xgp8Lg";
|
package/src/utils/SpokeUtils.ts
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import { encodeAbiParameters, Hex, keccak256 } from "viem";
|
|
2
2
|
import { fixedPointAdjustment as fixedPoint } from "./common";
|
|
3
3
|
import { MAX_SAFE_DEPOSIT_ID, ZERO_BYTES } from "../constants";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
DepositWithBlock,
|
|
6
|
+
Fill,
|
|
7
|
+
FillWithBlock,
|
|
8
|
+
FillType,
|
|
9
|
+
RelayData,
|
|
10
|
+
RelayExecutionEventInfo,
|
|
11
|
+
SlowFillLeaf,
|
|
12
|
+
SortableEvent,
|
|
13
|
+
} from "../interfaces";
|
|
14
|
+
import { svm } from "../arch";
|
|
5
15
|
import { BigNumber } from "./BigNumberUtils";
|
|
6
16
|
import { isMessageEmpty } from "./DepositUtils";
|
|
7
17
|
import { chainIsSvm } from "./NetworkUtils";
|
|
8
|
-
import {
|
|
18
|
+
import { toAddressType } from "./AddressUtils";
|
|
9
19
|
|
|
10
20
|
export function isSlowFill(fill: Fill): boolean {
|
|
11
21
|
return fill.relayExecutionInfo.fillType === FillType.SlowFill;
|
|
@@ -15,6 +25,92 @@ export function getSlowFillLeafLpFeePct(leaf: SlowFillLeaf): BigNumber {
|
|
|
15
25
|
const { relayData, updatedOutputAmount } = leaf;
|
|
16
26
|
return relayData.inputAmount.sub(updatedOutputAmount).mul(fixedPoint).div(relayData.inputAmount);
|
|
17
27
|
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Given a SortableEvent type, unpack the available FundsDeposited fields.
|
|
31
|
+
* @note Some fields cannot be evaluated without additional context - i.e. quoteBlockNumber, {from,to}LiteChain.
|
|
32
|
+
* @param rawEvent emitted by FundsDeposited event.
|
|
33
|
+
* @param originChainId Deposit originChainId
|
|
34
|
+
* @returns A mostly-populated DepositWithBlock event.
|
|
35
|
+
*/
|
|
36
|
+
export function unpackDepositEvent(
|
|
37
|
+
rawEvent: SortableEvent,
|
|
38
|
+
originChainId: number
|
|
39
|
+
): Omit<DepositWithBlock, "quoteBlockNumber" | "fromLiteChain" | "toLiteChain"> {
|
|
40
|
+
const event = rawEvent as Omit<
|
|
41
|
+
DepositWithBlock,
|
|
42
|
+
| "originChainId"
|
|
43
|
+
| "depositor"
|
|
44
|
+
| "recipient"
|
|
45
|
+
| "inputToken"
|
|
46
|
+
| "outputToken"
|
|
47
|
+
| "exclusiveRelayer"
|
|
48
|
+
| "quoteBlockNumber"
|
|
49
|
+
| "fromLiteChain"
|
|
50
|
+
| "toLiteChain"
|
|
51
|
+
> & {
|
|
52
|
+
depositor: string;
|
|
53
|
+
recipient: string;
|
|
54
|
+
inputToken: string;
|
|
55
|
+
outputToken: string;
|
|
56
|
+
exclusiveRelayer: string;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
...event,
|
|
61
|
+
originChainId,
|
|
62
|
+
depositor: toAddressType(event.depositor, originChainId),
|
|
63
|
+
recipient: toAddressType(event.recipient, event.destinationChainId),
|
|
64
|
+
inputToken: toAddressType(event.inputToken, originChainId),
|
|
65
|
+
outputToken: toAddressType(event.outputToken, event.destinationChainId),
|
|
66
|
+
exclusiveRelayer: toAddressType(event.exclusiveRelayer, event.destinationChainId),
|
|
67
|
+
messageHash: getMessageHash(event.message),
|
|
68
|
+
} satisfies Omit<DepositWithBlock, "quoteBlockNumber" | "fromLiteChain" | "toLiteChain">;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Given a SortableEvent type, unpack the complete set of FilledRelay fields.
|
|
73
|
+
* @param rawEvent emitted by FundsDeposited event.
|
|
74
|
+
* @param originChainId Deposit originChainId
|
|
75
|
+
* @returns A mostly-populated DepositWithBlock event.
|
|
76
|
+
*/
|
|
77
|
+
export function unpackFillEvent(rawEvent: SortableEvent, destinationChainId: number): FillWithBlock {
|
|
78
|
+
const event = rawEvent as Omit<
|
|
79
|
+
FillWithBlock,
|
|
80
|
+
| "destinationChainId"
|
|
81
|
+
| "depositor"
|
|
82
|
+
| "recipient"
|
|
83
|
+
| "inputToken"
|
|
84
|
+
| "outputToken"
|
|
85
|
+
| "exclusiveRelayer"
|
|
86
|
+
| "relayer"
|
|
87
|
+
| "relayerExecutionInfo"
|
|
88
|
+
> & {
|
|
89
|
+
depositor: string;
|
|
90
|
+
recipient: string;
|
|
91
|
+
inputToken: string;
|
|
92
|
+
outputToken: string;
|
|
93
|
+
exclusiveRelayer: string;
|
|
94
|
+
relayer: string;
|
|
95
|
+
relayExecutionInfo: Omit<RelayExecutionEventInfo, "updatedRecipient"> & { updatedRecipient: string };
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
...event,
|
|
100
|
+
destinationChainId,
|
|
101
|
+
depositor: toAddressType(event.depositor, event.originChainId),
|
|
102
|
+
recipient: toAddressType(event.recipient, destinationChainId),
|
|
103
|
+
inputToken: toAddressType(event.inputToken, event.originChainId),
|
|
104
|
+
outputToken: toAddressType(event.outputToken, destinationChainId),
|
|
105
|
+
exclusiveRelayer: toAddressType(event.exclusiveRelayer, destinationChainId),
|
|
106
|
+
relayer: toAddressType(event.relayer, event.repaymentChainId),
|
|
107
|
+
relayExecutionInfo: {
|
|
108
|
+
...event.relayExecutionInfo,
|
|
109
|
+
updatedRecipient: toAddressType(event.relayExecutionInfo.updatedRecipient, destinationChainId),
|
|
110
|
+
},
|
|
111
|
+
} satisfies FillWithBlock;
|
|
112
|
+
}
|
|
113
|
+
|
|
18
114
|
/**
|
|
19
115
|
* Compute the RelayData hash for a fill. This can be used to determine the fill status.
|
|
20
116
|
* @param relayData RelayData information that is used to complete a fill.
|