@across-protocol/sdk 4.3.44 → 4.3.45
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/clients/BundleDataClient/utils/DataworkerUtils.js +6 -4
- package/dist/cjs/clients/BundleDataClient/utils/DataworkerUtils.js.map +1 -1
- package/dist/cjs/clients/BundleDataClient/utils/FillUtils.js +5 -0
- package/dist/cjs/clients/BundleDataClient/utils/FillUtils.js.map +1 -1
- package/dist/cjs/clients/BundleDataClient/utils/PoolRebalanceUtils.js +1 -0
- package/dist/cjs/clients/BundleDataClient/utils/PoolRebalanceUtils.js.map +1 -1
- package/dist/cjs/clients/HubPoolClient.d.ts +3 -9
- package/dist/cjs/clients/HubPoolClient.js +56 -81
- package/dist/cjs/clients/HubPoolClient.js.map +1 -1
- package/dist/cjs/clients/SpokePoolClient/SpokePoolClient.js +4 -3
- package/dist/cjs/clients/SpokePoolClient/SpokePoolClient.js.map +1 -1
- package/dist/cjs/clients/mocks/MockHubPoolClient.d.ts +2 -2
- package/dist/cjs/clients/mocks/MockHubPoolClient.js +1 -1
- package/dist/cjs/clients/mocks/MockHubPoolClient.js.map +1 -1
- package/dist/cjs/utils/BlockExplorerUtils.js +25 -15
- package/dist/cjs/utils/BlockExplorerUtils.js.map +1 -1
- package/dist/cjs/utils/FormattingUtils.d.ts +1 -1
- package/dist/cjs/utils/FormattingUtils.js +4 -4
- package/dist/cjs/utils/FormattingUtils.js.map +1 -1
- package/dist/esm/clients/BundleDataClient/utils/DataworkerUtils.js +7 -5
- package/dist/esm/clients/BundleDataClient/utils/DataworkerUtils.js.map +1 -1
- package/dist/esm/clients/BundleDataClient/utils/FillUtils.js +6 -1
- package/dist/esm/clients/BundleDataClient/utils/FillUtils.js.map +1 -1
- package/dist/esm/clients/BundleDataClient/utils/PoolRebalanceUtils.js +1 -0
- package/dist/esm/clients/BundleDataClient/utils/PoolRebalanceUtils.js.map +1 -1
- package/dist/esm/clients/HubPoolClient.d.ts +3 -9
- package/dist/esm/clients/HubPoolClient.js +60 -87
- package/dist/esm/clients/HubPoolClient.js.map +1 -1
- package/dist/esm/clients/SpokePoolClient/SpokePoolClient.js +4 -3
- package/dist/esm/clients/SpokePoolClient/SpokePoolClient.js.map +1 -1
- package/dist/esm/clients/mocks/MockHubPoolClient.d.ts +2 -2
- package/dist/esm/clients/mocks/MockHubPoolClient.js +1 -1
- package/dist/esm/clients/mocks/MockHubPoolClient.js.map +1 -1
- package/dist/esm/utils/BlockExplorerUtils.js +27 -19
- package/dist/esm/utils/BlockExplorerUtils.js.map +1 -1
- package/dist/esm/utils/FormattingUtils.d.ts +3 -3
- package/dist/esm/utils/FormattingUtils.js +4 -4
- package/dist/esm/utils/FormattingUtils.js.map +1 -1
- package/dist/types/clients/BundleDataClient/utils/DataworkerUtils.d.ts.map +1 -1
- package/dist/types/clients/BundleDataClient/utils/FillUtils.d.ts.map +1 -1
- package/dist/types/clients/BundleDataClient/utils/PoolRebalanceUtils.d.ts.map +1 -1
- package/dist/types/clients/HubPoolClient.d.ts +3 -9
- package/dist/types/clients/HubPoolClient.d.ts.map +1 -1
- package/dist/types/clients/SpokePoolClient/SpokePoolClient.d.ts.map +1 -1
- package/dist/types/clients/mocks/MockHubPoolClient.d.ts +2 -2
- package/dist/types/clients/mocks/MockHubPoolClient.d.ts.map +1 -1
- package/dist/types/utils/BlockExplorerUtils.d.ts.map +1 -1
- package/dist/types/utils/FormattingUtils.d.ts +3 -3
- package/dist/types/utils/FormattingUtils.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/clients/BundleDataClient/utils/DataworkerUtils.ts +14 -20
- package/src/clients/BundleDataClient/utils/FillUtils.ts +7 -1
- package/src/clients/BundleDataClient/utils/PoolRebalanceUtils.ts +2 -0
- package/src/clients/HubPoolClient.ts +50 -79
- package/src/clients/SpokePoolClient/SpokePoolClient.ts +15 -11
- package/src/clients/mocks/MockHubPoolClient.ts +3 -3
- package/src/utils/BlockExplorerUtils.ts +25 -18
- package/src/utils/FormattingUtils.ts +4 -4
|
@@ -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
|
-
|
|
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 =
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
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
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
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
|
-
|
|
240
|
-
|
|
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.
|
|
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
|
-
|
|
266
|
-
|
|
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
|
-
|
|
411
|
-
|
|
412
|
-
|
|
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
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
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]
|
|
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,7 +1,9 @@
|
|
|
1
1
|
import { ethers } from "ethers";
|
|
2
2
|
import { PUBLIC_NETWORKS } from "../constants";
|
|
3
|
-
import {
|
|
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(
|
|
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}:${
|
|
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 (
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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 =
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
[
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
|
65
|
+
* @example createShortenedString("0x772871a444c6e4e9903d8533a5a13101b74037158123e6709470f0afbf6e7d94") -> "0x7787...7d94"
|
|
66
66
|
*/
|
|
67
|
-
export function
|
|
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
|
|
137
|
+
* @see createShortenedString
|
|
138
138
|
*/
|
|
139
139
|
export function shortenHexStrings(addresses: string[]): string[] {
|
|
140
|
-
return addresses.map((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.
|