@across-protocol/sdk 4.3.44 → 4.3.46

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 (91) hide show
  1. package/dist/cjs/arch/svm/SpokeUtils.d.ts +21 -10
  2. package/dist/cjs/arch/svm/SpokeUtils.js +128 -10
  3. package/dist/cjs/arch/svm/SpokeUtils.js.map +1 -1
  4. package/dist/cjs/arch/svm/encoders.d.ts +19 -0
  5. package/dist/cjs/arch/svm/encoders.js +52 -0
  6. package/dist/cjs/arch/svm/encoders.js.map +1 -0
  7. package/dist/cjs/arch/svm/index.d.ts +1 -0
  8. package/dist/cjs/arch/svm/index.js +1 -0
  9. package/dist/cjs/arch/svm/index.js.map +1 -1
  10. package/dist/cjs/clients/BundleDataClient/utils/DataworkerUtils.js +6 -4
  11. package/dist/cjs/clients/BundleDataClient/utils/DataworkerUtils.js.map +1 -1
  12. package/dist/cjs/clients/BundleDataClient/utils/FillUtils.js +5 -0
  13. package/dist/cjs/clients/BundleDataClient/utils/FillUtils.js.map +1 -1
  14. package/dist/cjs/clients/BundleDataClient/utils/PoolRebalanceUtils.js +1 -0
  15. package/dist/cjs/clients/BundleDataClient/utils/PoolRebalanceUtils.js.map +1 -1
  16. package/dist/cjs/clients/HubPoolClient.d.ts +3 -9
  17. package/dist/cjs/clients/HubPoolClient.js +56 -81
  18. package/dist/cjs/clients/HubPoolClient.js.map +1 -1
  19. package/dist/cjs/clients/SpokePoolClient/SpokePoolClient.js +4 -3
  20. package/dist/cjs/clients/SpokePoolClient/SpokePoolClient.js.map +1 -1
  21. package/dist/cjs/clients/mocks/MockHubPoolClient.d.ts +2 -2
  22. package/dist/cjs/clients/mocks/MockHubPoolClient.js +1 -1
  23. package/dist/cjs/clients/mocks/MockHubPoolClient.js.map +1 -1
  24. package/dist/cjs/providers/solana/retryRpcFactory.js +14 -10
  25. package/dist/cjs/providers/solana/retryRpcFactory.js.map +1 -1
  26. package/dist/cjs/utils/BlockExplorerUtils.js +25 -15
  27. package/dist/cjs/utils/BlockExplorerUtils.js.map +1 -1
  28. package/dist/cjs/utils/FormattingUtils.d.ts +1 -1
  29. package/dist/cjs/utils/FormattingUtils.js +4 -4
  30. package/dist/cjs/utils/FormattingUtils.js.map +1 -1
  31. package/dist/esm/arch/svm/SpokeUtils.d.ts +38 -10
  32. package/dist/esm/arch/svm/SpokeUtils.js +151 -10
  33. package/dist/esm/arch/svm/SpokeUtils.js.map +1 -1
  34. package/dist/esm/arch/svm/encoders.d.ts +19 -0
  35. package/dist/esm/arch/svm/encoders.js +43 -0
  36. package/dist/esm/arch/svm/encoders.js.map +1 -0
  37. package/dist/esm/arch/svm/index.d.ts +1 -0
  38. package/dist/esm/arch/svm/index.js +1 -0
  39. package/dist/esm/arch/svm/index.js.map +1 -1
  40. package/dist/esm/clients/BundleDataClient/utils/DataworkerUtils.js +7 -5
  41. package/dist/esm/clients/BundleDataClient/utils/DataworkerUtils.js.map +1 -1
  42. package/dist/esm/clients/BundleDataClient/utils/FillUtils.js +6 -1
  43. package/dist/esm/clients/BundleDataClient/utils/FillUtils.js.map +1 -1
  44. package/dist/esm/clients/BundleDataClient/utils/PoolRebalanceUtils.js +1 -0
  45. package/dist/esm/clients/BundleDataClient/utils/PoolRebalanceUtils.js.map +1 -1
  46. package/dist/esm/clients/HubPoolClient.d.ts +3 -9
  47. package/dist/esm/clients/HubPoolClient.js +60 -87
  48. package/dist/esm/clients/HubPoolClient.js.map +1 -1
  49. package/dist/esm/clients/SpokePoolClient/SpokePoolClient.js +4 -3
  50. package/dist/esm/clients/SpokePoolClient/SpokePoolClient.js.map +1 -1
  51. package/dist/esm/clients/mocks/MockHubPoolClient.d.ts +2 -2
  52. package/dist/esm/clients/mocks/MockHubPoolClient.js +1 -1
  53. package/dist/esm/clients/mocks/MockHubPoolClient.js.map +1 -1
  54. package/dist/esm/providers/solana/retryRpcFactory.js +15 -10
  55. package/dist/esm/providers/solana/retryRpcFactory.js.map +1 -1
  56. package/dist/esm/utils/BlockExplorerUtils.js +27 -19
  57. package/dist/esm/utils/BlockExplorerUtils.js.map +1 -1
  58. package/dist/esm/utils/FormattingUtils.d.ts +3 -3
  59. package/dist/esm/utils/FormattingUtils.js +4 -4
  60. package/dist/esm/utils/FormattingUtils.js.map +1 -1
  61. package/dist/types/arch/svm/SpokeUtils.d.ts +38 -10
  62. package/dist/types/arch/svm/SpokeUtils.d.ts.map +1 -1
  63. package/dist/types/arch/svm/encoders.d.ts +20 -0
  64. package/dist/types/arch/svm/encoders.d.ts.map +1 -0
  65. package/dist/types/arch/svm/index.d.ts +1 -0
  66. package/dist/types/arch/svm/index.d.ts.map +1 -1
  67. package/dist/types/clients/BundleDataClient/utils/DataworkerUtils.d.ts.map +1 -1
  68. package/dist/types/clients/BundleDataClient/utils/FillUtils.d.ts.map +1 -1
  69. package/dist/types/clients/BundleDataClient/utils/PoolRebalanceUtils.d.ts.map +1 -1
  70. package/dist/types/clients/HubPoolClient.d.ts +3 -9
  71. package/dist/types/clients/HubPoolClient.d.ts.map +1 -1
  72. package/dist/types/clients/SpokePoolClient/SpokePoolClient.d.ts.map +1 -1
  73. package/dist/types/clients/mocks/MockHubPoolClient.d.ts +2 -2
  74. package/dist/types/clients/mocks/MockHubPoolClient.d.ts.map +1 -1
  75. package/dist/types/providers/solana/retryRpcFactory.d.ts.map +1 -1
  76. package/dist/types/utils/BlockExplorerUtils.d.ts.map +1 -1
  77. package/dist/types/utils/FormattingUtils.d.ts +3 -3
  78. package/dist/types/utils/FormattingUtils.d.ts.map +1 -1
  79. package/package.json +2 -2
  80. package/src/arch/svm/SpokeUtils.ts +187 -4
  81. package/src/arch/svm/encoders.ts +86 -0
  82. package/src/arch/svm/index.ts +1 -0
  83. package/src/clients/BundleDataClient/utils/DataworkerUtils.ts +14 -20
  84. package/src/clients/BundleDataClient/utils/FillUtils.ts +7 -1
  85. package/src/clients/BundleDataClient/utils/PoolRebalanceUtils.ts +2 -0
  86. package/src/clients/HubPoolClient.ts +50 -79
  87. package/src/clients/SpokePoolClient/SpokePoolClient.ts +15 -11
  88. package/src/clients/mocks/MockHubPoolClient.ts +3 -3
  89. package/src/providers/solana/retryRpcFactory.ts +6 -2
  90. package/src/utils/BlockExplorerUtils.ts +25 -18
  91. package/src/utils/FormattingUtils.ts +4 -4
@@ -37,18 +37,21 @@ export function getRefundInformationFromFill(
37
37
 
38
38
  // Now figure out the equivalent L2 token for the repayment token. If the inputToken doesn't have a
39
39
  // PoolRebalanceRoute, then the repayment chain would have been the originChainId after the getRepaymentChainId()
40
- // call and we would have returned already, so the following call should always succeed.
40
+ // call and we would have returned already, so the following call should always return a valid L1 token.
41
41
  const l1TokenCounterpart = hubPoolClient.getL1TokenForL2TokenAtBlock(
42
42
  relayData.inputToken,
43
43
  relayData.originChainId,
44
44
  bundleEndBlockForMainnet
45
45
  );
46
46
 
47
+ assert(isDefined(l1TokenCounterpart), "getRefundInformationFromFill: l1TokenCounterpart is undefined");
48
+
47
49
  const repaymentToken = hubPoolClient.getL2TokenForL1TokenAtBlock(
48
50
  l1TokenCounterpart,
49
51
  chainToSendRefundTo,
50
52
  bundleEndBlockForMainnet
51
53
  );
54
+ assert(isDefined(repaymentToken), "getRefundInformationFromFill: repaymentToken is undefined");
52
55
 
53
56
  return {
54
57
  chainToSendRefundTo,
@@ -183,6 +186,9 @@ function _repaymentChainTokenIsValid(
183
186
  relayData.originChainId,
184
187
  bundleEndBlockForMainnet
185
188
  );
189
+ if (!l1TokenCounterpart) {
190
+ return false;
191
+ }
186
192
  if (
187
193
  !hubPoolClient.l2TokenEnabledForL1TokenAtBlock(
188
194
  l1TokenCounterpart,
@@ -202,6 +202,8 @@ export function updateRunningBalanceForDeposit(
202
202
  deposit.originChainId,
203
203
  mainnetBundleEndBlock
204
204
  );
205
+ assert(isDefined(l1TokenCounterpart), "updateRunningBalanceForDeposit: l1TokenCounterpart is undefined");
206
+
205
207
  updateRunningBalance(runningBalances, deposit.originChainId, l1TokenCounterpart.toEvmAddress(), updateAmount);
206
208
  }
207
209
 
@@ -34,7 +34,6 @@ import {
34
34
  fetchTokenInfo,
35
35
  getCachedBlockForTimestamp,
36
36
  getCurrentTime,
37
- getNetworkName,
38
37
  isDefined,
39
38
  mapAsync,
40
39
  paginatedEventQuery,
@@ -75,17 +74,11 @@ type HubPoolEvent =
75
74
  | "RootBundleExecuted"
76
75
  | "CrossChainContractsSet";
77
76
 
78
- type L1TokensToDestinationTokens = {
79
- [l1Token: string]: { [destinationChainId: number]: Address };
80
- };
81
-
82
77
  export type LpFeeRequest = Pick<Deposit, "originChainId" | "inputToken" | "inputAmount" | "quoteTimestamp"> & {
83
78
  paymentChainId?: number;
84
79
  };
85
80
 
86
81
  export class HubPoolClient extends BaseAbstractClient {
87
- // L1Token -> destinationChainId -> destinationToken
88
- protected l1TokensToDestinationTokens: L1TokensToDestinationTokens = {};
89
82
  protected l1Tokens: L1TokenInfo[] = []; // L1Tokens and their associated info.
90
83
  // @dev `token` here is a 20-byte hex sting
91
84
  protected lpTokens: { [token: string]: LpToken } = {};
@@ -192,24 +185,16 @@ export class HubPoolClient extends BaseAbstractClient {
192
185
  l1Token: EvmAddress,
193
186
  destinationChainId: number,
194
187
  latestHubBlock = Number.MAX_SAFE_INTEGER
195
- ): Address {
188
+ ): Address | undefined {
196
189
  if (!this.l1TokensToDestinationTokensWithBlock?.[l1Token.toEvmAddress()]?.[destinationChainId]) {
197
- const chain = getNetworkName(destinationChainId);
198
- const { symbol } = this.l1Tokens.find(({ address }) => address.eq(l1Token)) ?? { symbol: l1Token.toString() };
199
- throw new Error(`Could not find SpokePool mapping for ${symbol} on ${chain} and L1 token ${l1Token}`);
190
+ return undefined;
200
191
  }
201
192
  // Find the last mapping published before the target block.
202
- const l2Token: DestinationTokenWithBlock | undefined = sortEventsDescending(
203
- this.l1TokensToDestinationTokensWithBlock[l1Token.toEvmAddress()][destinationChainId]
204
- ).find((mapping: DestinationTokenWithBlock) => mapping.blockNumber <= latestHubBlock);
205
- if (!l2Token) {
206
- const chain = getNetworkName(destinationChainId);
207
- const { symbol } = this.l1Tokens.find(({ address }) => address.eq(l1Token)) ?? { symbol: l1Token.toString() };
208
- throw new Error(
209
- `Could not find SpokePool mapping for ${symbol} on ${chain} at or before HubPool block ${latestHubBlock}!`
210
- );
211
- }
212
- return l2Token.l2Token;
193
+ const l2Token: DestinationTokenWithBlock | undefined = this.l1TokensToDestinationTokensWithBlock[
194
+ l1Token.toEvmAddress()
195
+ ][destinationChainId].find((mapping: DestinationTokenWithBlock) => mapping.blockNumber <= latestHubBlock);
196
+
197
+ return !l2Token || l2Token.l2Token.isZeroAddress() ? undefined : l2Token.l2Token;
213
198
  }
214
199
 
215
200
  // Returns the latest L1 token to use for an L2 token as of the input hub block.
@@ -217,32 +202,27 @@ export class HubPoolClient extends BaseAbstractClient {
217
202
  l2Token: Address,
218
203
  destinationChainId: number,
219
204
  latestHubBlock = Number.MAX_SAFE_INTEGER
220
- ): EvmAddress {
221
- const l2Tokens = Object.keys(this.l1TokensToDestinationTokensWithBlock)
222
- .filter((l1Token) => this.l2TokenEnabledForL1Token(EvmAddress.from(l1Token), destinationChainId))
223
- .map((l1Token) => {
224
- // Return all matching L2 token mappings that are equal to or earlier than the target block.
225
- // @dev Since tokens on L2s (like Solana) can have 32 byte addresses, filter on the lower 20 bytes of the token only.
226
- return this.l1TokensToDestinationTokensWithBlock[l1Token][destinationChainId].filter(
227
- (dstTokenWithBlock) =>
228
- dstTokenWithBlock.l2Token.truncateToBytes20() === l2Token.truncateToBytes20() &&
229
- dstTokenWithBlock.blockNumber <= latestHubBlock
230
- );
231
- })
232
- .flat();
233
- if (l2Tokens.length === 0) {
234
- const chain = getNetworkName(destinationChainId);
235
- throw new Error(
236
- `Could not find HubPool mapping for ${l2Token} on ${chain} at or before HubPool block ${latestHubBlock}!`
205
+ ): EvmAddress | undefined {
206
+ const l2Tokens = Object.keys(this.l1TokensToDestinationTokensWithBlock).flatMap((l1Token) => {
207
+ // Get the latest L2 token mapping for the given L1 token.
208
+ // @dev Since tokens on L2s (like Solana) can have 32 byte addresses, filter on the lower 20 bytes of the token only.
209
+ const sortedL2Tokens = sortEventsDescending(
210
+ (this.l1TokensToDestinationTokensWithBlock[l1Token][destinationChainId] ?? []).filter(
211
+ (dstTokenWithBlock) => dstTokenWithBlock.blockNumber <= latestHubBlock
212
+ )
237
213
  );
238
- }
239
- // Find the last mapping published before the target block.
240
- return sortEventsDescending(l2Tokens)[0].l1Token;
214
+ // If the latest L2 token mapping is equal to the target L2 token, return it.
215
+ return sortedL2Tokens.length > 0 && sortedL2Tokens[0].l2Token.truncateToBytes20() === l2Token.truncateToBytes20()
216
+ ? sortedL2Tokens[0]
217
+ : [];
218
+ });
219
+
220
+ return l2Tokens.length === 0 ? undefined : sortEventsDescending(l2Tokens)[0].l1Token;
241
221
  }
242
222
 
243
223
  protected getL1TokenForDeposit(
244
224
  deposit: Pick<DepositWithBlock, "originChainId" | "inputToken" | "quoteBlockNumber">
245
- ): EvmAddress {
225
+ ): EvmAddress | undefined {
246
226
  // L1-->L2 token mappings are set via PoolRebalanceRoutes which occur on mainnet,
247
227
  // so we use the latest token mapping. This way if a very old deposit is filled, the relayer can use the
248
228
  // latest L2 token mapping to find the L1 token counterpart.
@@ -250,7 +230,7 @@ export class HubPoolClient extends BaseAbstractClient {
250
230
  }
251
231
 
252
232
  l2TokenEnabledForL1Token(l1Token: EvmAddress, destinationChainId: number): boolean {
253
- return this.l1TokensToDestinationTokens?.[l1Token.toEvmAddress()]?.[destinationChainId] != undefined;
233
+ return this.l2TokenEnabledForL1TokenAtBlock(l1Token, destinationChainId, Number.MAX_SAFE_INTEGER);
254
234
  }
255
235
 
256
236
  l2TokenEnabledForL1TokenAtBlock(l1Token: EvmAddress, destinationChainId: number, hubBlockNumber: number): boolean {
@@ -258,21 +238,12 @@ export class HubPoolClient extends BaseAbstractClient {
258
238
  const l2Token: DestinationTokenWithBlock | undefined = sortEventsDescending(
259
239
  this.l1TokensToDestinationTokensWithBlock?.[l1Token.toEvmAddress()]?.[destinationChainId] ?? []
260
240
  ).find((mapping: DestinationTokenWithBlock) => mapping.blockNumber <= hubBlockNumber);
261
- return l2Token !== undefined;
241
+ return l2Token !== undefined && !l2Token.l2Token.isZeroAddress();
262
242
  }
263
243
 
264
244
  l2TokenHasPoolRebalanceRoute(l2Token: Address, l2ChainId: number, hubPoolBlock = this.latestHeightSearched): boolean {
265
- return Object.values(this.l1TokensToDestinationTokensWithBlock).some((destinationTokenMapping) => {
266
- return Object.entries(destinationTokenMapping).some(([_l2ChainId, setPoolRebalanceRouteEvents]) => {
267
- return setPoolRebalanceRouteEvents.some((e) => {
268
- return (
269
- e.blockNumber <= hubPoolBlock &&
270
- e.l2Token.truncateToBytes20() === l2Token.truncateToBytes20() &&
271
- Number(_l2ChainId) === l2ChainId
272
- );
273
- });
274
- });
275
- });
245
+ const l1Token = this.getL1TokenForL2TokenAtBlock(l2Token, l2ChainId, hubPoolBlock);
246
+ return l1Token !== undefined;
276
247
  }
277
248
 
278
249
  /**
@@ -407,9 +378,11 @@ export class HubPoolClient extends BaseAbstractClient {
407
378
  const hubPoolTokens: { [k: string]: EvmAddress } = {};
408
379
  const getHubPoolToken = (deposit: LpFeeRequest, quoteBlockNumber: number): EvmAddress | undefined => {
409
380
  const tokenKey = `${deposit.originChainId}-${deposit.inputToken}`;
410
- if (this.l2TokenHasPoolRebalanceRoute(deposit.inputToken, deposit.originChainId, quoteBlockNumber)) {
411
- return (hubPoolTokens[tokenKey] ??= this.getL1TokenForDeposit({ ...deposit, quoteBlockNumber }));
412
- } else return undefined;
381
+ const l1Token = this.getL1TokenForDeposit({ ...deposit, quoteBlockNumber });
382
+ if (!l1Token) {
383
+ return undefined;
384
+ }
385
+ return (hubPoolTokens[tokenKey] ??= l1Token);
413
386
  };
414
387
  const getHubPoolTokens = (): EvmAddress[] => dedupArray(Object.values(hubPoolTokens).filter(isDefined));
415
388
 
@@ -548,14 +521,14 @@ export class HubPoolClient extends BaseAbstractClient {
548
521
  // Resolve both SpokePool tokens back to their respective HubPool tokens and verify that they match.
549
522
  const l1TokenA = this.getL1TokenForL2TokenAtBlock(tokenA, chainIdA, hubPoolBlock);
550
523
  const l1TokenB = this.getL1TokenForL2TokenAtBlock(tokenB, chainIdB, hubPoolBlock);
551
- if (!l1TokenA.eq(l1TokenB)) {
524
+ if (!l1TokenA || !l1TokenB || !l1TokenA.eq(l1TokenB)) {
552
525
  return false;
553
526
  }
554
527
 
555
528
  // Resolve both HubPool tokens back to a current SpokePool token and verify that they match.
556
529
  const _tokenA = this.getL2TokenForL1TokenAtBlock(l1TokenA, chainIdA, hubPoolBlock);
557
530
  const _tokenB = this.getL2TokenForL1TokenAtBlock(l1TokenB, chainIdB, hubPoolBlock);
558
- return tokenA.eq(_tokenA) && tokenB.eq(_tokenB);
531
+ return _tokenA !== undefined && _tokenB !== undefined && tokenA.eq(_tokenA) && tokenB.eq(_tokenB);
559
532
  }
560
533
 
561
534
  getSpokeActivationBlockForChain(chainId: number): number {
@@ -995,24 +968,22 @@ export class HubPoolClient extends BaseAbstractClient {
995
968
  destinationToken = svmUsdc;
996
969
  }
997
970
 
998
- // If the destination token is set to the zero address in an event, then this means Across should no longer
999
- // rebalance to this chain.
1000
- if (!destinationToken.isZeroAddress()) {
1001
- assign(this.l1TokensToDestinationTokens, [args.l1Token, args.destinationChainId], destinationToken);
1002
- assign(
1003
- this.l1TokensToDestinationTokensWithBlock,
1004
- [args.l1Token, args.destinationChainId],
1005
- [
1006
- {
1007
- l1Token: EvmAddress.from(args.l1Token),
1008
- l2Token: destinationToken,
1009
- blockNumber: args.blockNumber,
1010
- txnIndex: args.txnIndex,
1011
- logIndex: args.logIndex,
1012
- txnRef: args.txnRef,
1013
- },
1014
- ]
1015
- );
971
+ const newRoute: DestinationTokenWithBlock = {
972
+ l1Token: EvmAddress.from(args.l1Token),
973
+ l2Token: destinationToken,
974
+ blockNumber: args.blockNumber,
975
+ txnIndex: args.txnIndex,
976
+ logIndex: args.logIndex,
977
+ txnRef: args.txnRef,
978
+ };
979
+ if (this.l1TokensToDestinationTokensWithBlock[args.l1Token]?.[args.destinationChainId]) {
980
+ // Events are most likely coming in descending orders already but just in case we sort them again.
981
+ this.l1TokensToDestinationTokensWithBlock[args.l1Token][args.destinationChainId] = sortEventsDescending([
982
+ ...this.l1TokensToDestinationTokensWithBlock[args.l1Token][args.destinationChainId],
983
+ newRoute,
984
+ ]);
985
+ } else {
986
+ assign(this.l1TokensToDestinationTokensWithBlock, [args.l1Token, args.destinationChainId], [newRoute]);
1016
987
  }
1017
988
  }
1018
989
  }
@@ -472,18 +472,22 @@ export abstract class SpokePoolClient extends BaseAbstractClient {
472
472
  )
473
473
  ) {
474
474
  return false;
475
- } else {
476
- const l1Token = this.hubPoolClient?.getL1TokenForL2TokenAtBlock(
477
- deposit.inputToken,
478
- deposit.originChainId,
479
- deposit.quoteBlockNumber
480
- );
481
- return this.hubPoolClient.l2TokenEnabledForL1TokenAtBlock(
482
- l1Token,
483
- deposit.destinationChainId,
484
- deposit.quoteBlockNumber
485
- );
486
475
  }
476
+
477
+ const l1Token = this.hubPoolClient?.getL1TokenForL2TokenAtBlock(
478
+ deposit.inputToken,
479
+ deposit.originChainId,
480
+ deposit.quoteBlockNumber
481
+ );
482
+ if (!l1Token) {
483
+ return false;
484
+ }
485
+
486
+ return this.hubPoolClient.l2TokenEnabledForL1TokenAtBlock(
487
+ l1Token,
488
+ deposit.destinationChainId,
489
+ deposit.quoteBlockNumber
490
+ );
487
491
  }
488
492
 
489
493
  /**
@@ -118,9 +118,9 @@ export class MockHubPoolClient extends HubPoolClient {
118
118
  delete this.spokePoolTokens[l1Token]?.[chainId];
119
119
  }
120
120
 
121
- getL1TokenForL2TokenAtBlock(l2Token: Address, chainId: number, blockNumber: number): EvmAddress {
121
+ getL1TokenForL2TokenAtBlock(l2Token: Address, chainId: number, blockNumber: number): EvmAddress | undefined {
122
122
  const l1Token = Object.keys(this.spokePoolTokens).find(
123
- (l1Token) => this.spokePoolTokens[l1Token]?.[chainId].eq(l2Token)
123
+ (l1Token) => this.spokePoolTokens[l1Token]?.[chainId]?.eq(l2Token)
124
124
  );
125
125
  if (isDefined(l1Token)) {
126
126
  return EvmAddress.from(l1Token);
@@ -129,7 +129,7 @@ export class MockHubPoolClient extends HubPoolClient {
129
129
  }
130
130
  }
131
131
 
132
- getL2TokenForL1TokenAtBlock(l1Token: EvmAddress, chainId: number, blockNumber: number): Address {
132
+ getL2TokenForL1TokenAtBlock(l1Token: EvmAddress, chainId: number, blockNumber: number): Address | undefined {
133
133
  const l2Token = this.spokePoolTokens[l1Token.toEvmAddress()]?.[chainId];
134
134
  return l2Token ?? super.getL2TokenForL1TokenAtBlock(l1Token, chainId, blockNumber);
135
135
  }
@@ -1,4 +1,5 @@
1
1
  import { RpcTransport, SOLANA_ERROR__RPC__TRANSPORT_HTTP_ERROR } from "@solana/kit";
2
+ import { getThrowSolanaErrorResponseTransformer } from "@solana/rpc-transformers";
2
3
  import { SolanaClusterRpcFactory } from "./baseRpcFactories";
3
4
  import { RateLimitedSolanaRpcFactory } from "./rateLimitedRpcFactory";
4
5
  import { isSolanaError } from "../../arch/svm";
@@ -56,13 +57,16 @@ export class RetrySolanaRpcFactory extends SolanaClusterRpcFactory {
56
57
  transportCall: () => Promise<TResponse>,
57
58
  args: Parameters<RpcTransport>
58
59
  ): Promise<TResponse> {
59
- const { method } = args[0].payload as { method: string; params?: unknown[] };
60
+ const { method, params } = args[0].payload as { method: string; params?: unknown[] };
60
61
  let retryAttempt = 0;
61
62
 
62
63
  // eslint-disable-next-line no-constant-condition
63
64
  while (true) {
64
65
  try {
65
- return await transportCall();
66
+ const response = await transportCall();
67
+ // Make sure SolanaErrors get thrown
68
+ getThrowSolanaErrorResponseTransformer()(response, { methodName: method, params });
69
+ return response;
66
70
  } catch (error) {
67
71
  if (retryAttempt++ >= this.retries || this.shouldFailImmediate(method, error)) {
68
72
  throw error;
@@ -1,7 +1,9 @@
1
1
  import { ethers } from "ethers";
2
2
  import { PUBLIC_NETWORKS } from "../constants";
3
- import { createShortHexString } from "./FormattingUtils";
3
+ import { createShortenedString } from "./FormattingUtils";
4
+ import { chainIsEvm } from "./NetworkUtils";
4
5
  import { isDefined } from "./TypeGuards";
6
+ import bs58 from "bs58";
5
7
 
6
8
  /**
7
9
  * Creates a block explorer link for a transaction or address on a given network.
@@ -49,32 +51,37 @@ function constructURL(domain: string, parts: string[]): string {
49
51
  * @param chainId The chainId to link to.
50
52
  * @returns A formatted markdown block explorer link to the given transaction hash or address on the given chainId.
51
53
  */
52
- function _createBlockExplorerLinkMarkdown(hex: string, chainId = 1): string | null {
54
+ function _createBlockExplorerLinkMarkdown(addr: string, chainId = 1): string | null {
53
55
  // Attempt to resolve the block explorer domain for the given chainId.
54
56
  const explorerDomain = resolveBlockExplorerDomain(chainId);
55
57
  // If the chainId is not supported, return an unsupported link.
56
58
  if (!isDefined(explorerDomain)) {
57
- return `<unsupported chain/hash ${chainId}:${hex}>}`;
59
+ return `<unsupported chain/hash ${chainId}:${addr}>}`;
58
60
  }
59
61
  // Ensure that the first two characters are "0x". If they are not, append them.
60
- if (hex.substring(0, 2) !== "0x") {
61
- hex = `0x${hex}`;
62
- }
63
- // Ensure that the hex string is a valid hexadecimal string.
64
- if (!ethers.utils.isHexString(hex)) {
65
- return null;
62
+ if (addr.substring(0, 2) !== "0x" && chainIsEvm(chainId)) {
63
+ addr = `0x${addr}`;
64
+ if (!ethers.utils.isHexString(addr)) {
65
+ return null;
66
+ }
66
67
  }
67
68
  // Resolve the short URL string.
68
- const shortURLString = createShortHexString(hex);
69
- // Iterate over the two possible hex lengths.
70
- for (const [length, route] of [
71
- [66, "tx"],
72
- [42, "address"],
73
- ] as [number, string][]) {
74
- // If the hex string is the correct length, return the link.
75
- if (hex.length === length) {
76
- return `<${constructURL(explorerDomain, [route, hex])} | ${shortURLString}>`;
69
+ const shortURLString = createShortenedString(addr);
70
+ if (chainIsEvm(chainId)) {
71
+ // Iterate over the two possible addr lengths.
72
+ for (const [length, route] of [
73
+ [66, "tx"],
74
+ [42, "address"],
75
+ ] as [number, string][]) {
76
+ // If the hex string is the correct length, return the link.
77
+ if (addr.length === length) {
78
+ return `<${constructURL(explorerDomain, [route, addr])} | ${shortURLString}>`;
79
+ }
77
80
  }
81
+ } else {
82
+ const addrLength = bs58.decode(addr).length;
83
+ const route = addrLength === 32 ? "account" : "tx";
84
+ return `<${constructURL(explorerDomain, [route, addr])} | ${shortURLString}>`;
78
85
  }
79
86
  return null;
80
87
  }
@@ -62,9 +62,9 @@ export const formatFeePct = (relayerFeePct: BN): string => {
62
62
  * @param maxLength The maximum length of the shortened string. Defaults to 8.
63
63
  * @param delimiter The delimiter to use in the middle of the shortened string. Defaults to "...".
64
64
  * @returns The shortened hexadecimal string.
65
- * @example createShortHexString("0x772871a444c6e4e9903d8533a5a13101b74037158123e6709470f0afbf6e7d94") -> "0x7787...7d94"
65
+ * @example createShortenedString("0x772871a444c6e4e9903d8533a5a13101b74037158123e6709470f0afbf6e7d94") -> "0x7787...7d94"
66
66
  */
67
- export function createShortHexString(hex: string, maxLength = 8, delimiter = ".."): string {
67
+ export function createShortenedString(hex: string, maxLength = 8, delimiter = ".."): string {
68
68
  // If we have more maxLength then the hex size, we can simply
69
69
  // return the hex directly.
70
70
  if (hex.length <= maxLength) {
@@ -134,10 +134,10 @@ export function formatGwei(weiVal: string): string {
134
134
  * Shortens a list of addresses to a shorter version with only the first 10 characters.
135
135
  * @param addresses A list of addresses to shorten.
136
136
  * @returns A list of shortened addresses.
137
- * @see createShortHexString
137
+ * @see createShortenedString
138
138
  */
139
139
  export function shortenHexStrings(addresses: string[]): string[] {
140
- return addresses.map((h) => createShortHexString(h));
140
+ return addresses.map((h) => createShortenedString(h));
141
141
  }
142
142
 
143
143
  // formatWei converts a string or BN instance from Wei to Ether, e.g., 1e19 -> 10.