@across-protocol/sdk 4.2.16-alpha.3 → 4.2.16-alpha.5
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.d.ts +2 -6
- 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 +10 -9
- package/dist/cjs/arch/svm/SpokeUtils.js.map +1 -1
- package/dist/cjs/arch/svm/eventsClient.js +4 -2
- package/dist/cjs/arch/svm/eventsClient.js.map +1 -1
- package/dist/cjs/arch/svm/utils.d.ts +2 -2
- package/dist/cjs/arch/svm/utils.js +1 -1
- package/dist/cjs/arch/svm/utils.js.map +1 -1
- package/dist/cjs/clients/BundleDataClient/utils/SuperstructUtils.d.ts +63 -63
- package/dist/cjs/clients/BundleDataClient/utils/SuperstructUtils.js +4 -2
- package/dist/cjs/clients/BundleDataClient/utils/SuperstructUtils.js.map +1 -1
- package/dist/cjs/clients/HubPoolClient.js +5 -4
- package/dist/cjs/clients/HubPoolClient.js.map +1 -1
- package/dist/cjs/clients/SpokePoolClient/SpokePoolClient.js +3 -2
- package/dist/cjs/clients/SpokePoolClient/SpokePoolClient.js.map +1 -1
- package/dist/cjs/clients/mocks/MockHubPoolClient.d.ts +3 -3
- package/dist/cjs/clients/mocks/MockHubPoolClient.js.map +1 -1
- package/dist/cjs/clients/mocks/MockSvmCpiEventsClient.d.ts +1 -1
- package/dist/cjs/clients/mocks/MockSvmCpiEventsClient.js +6 -4
- package/dist/cjs/clients/mocks/MockSvmCpiEventsClient.js.map +1 -1
- package/dist/cjs/relayFeeCalculator/chain-queries/baseQuery.d.ts +6 -2
- package/dist/cjs/relayFeeCalculator/chain-queries/baseQuery.js +13 -4
- package/dist/cjs/relayFeeCalculator/chain-queries/baseQuery.js.map +1 -1
- package/dist/cjs/relayFeeCalculator/chain-queries/svmQuery.d.ts +5 -1
- package/dist/cjs/relayFeeCalculator/chain-queries/svmQuery.js +18 -5
- package/dist/cjs/relayFeeCalculator/chain-queries/svmQuery.js.map +1 -1
- package/dist/cjs/utils/AddressUtils.d.ts +12 -6
- package/dist/cjs/utils/AddressUtils.js +39 -36
- package/dist/cjs/utils/AddressUtils.js.map +1 -1
- package/dist/cjs/utils/TokenUtils.d.ts +2 -2
- package/dist/cjs/utils/TokenUtils.js +5 -3
- package/dist/cjs/utils/TokenUtils.js.map +1 -1
- package/dist/esm/arch/evm/SpokeUtils.d.ts +2 -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 +10 -9
- package/dist/esm/arch/svm/SpokeUtils.js.map +1 -1
- package/dist/esm/arch/svm/eventsClient.js +5 -3
- package/dist/esm/arch/svm/eventsClient.js.map +1 -1
- package/dist/esm/arch/svm/utils.d.ts +2 -2
- package/dist/esm/arch/svm/utils.js +2 -2
- package/dist/esm/arch/svm/utils.js.map +1 -1
- package/dist/esm/clients/BundleDataClient/utils/SuperstructUtils.d.ts +63 -63
- package/dist/esm/clients/BundleDataClient/utils/SuperstructUtils.js +11 -4
- package/dist/esm/clients/BundleDataClient/utils/SuperstructUtils.js.map +1 -1
- package/dist/esm/clients/HubPoolClient.js +5 -4
- package/dist/esm/clients/HubPoolClient.js.map +1 -1
- package/dist/esm/clients/SpokePoolClient/SpokePoolClient.js +3 -2
- package/dist/esm/clients/SpokePoolClient/SpokePoolClient.js.map +1 -1
- package/dist/esm/clients/mocks/MockHubPoolClient.d.ts +3 -3
- package/dist/esm/clients/mocks/MockHubPoolClient.js.map +1 -1
- package/dist/esm/clients/mocks/MockSvmCpiEventsClient.d.ts +1 -1
- package/dist/esm/clients/mocks/MockSvmCpiEventsClient.js +7 -5
- package/dist/esm/clients/mocks/MockSvmCpiEventsClient.js.map +1 -1
- package/dist/esm/relayFeeCalculator/chain-queries/baseQuery.d.ts +6 -2
- package/dist/esm/relayFeeCalculator/chain-queries/baseQuery.js +13 -4
- package/dist/esm/relayFeeCalculator/chain-queries/baseQuery.js.map +1 -1
- package/dist/esm/relayFeeCalculator/chain-queries/svmQuery.d.ts +7 -2
- package/dist/esm/relayFeeCalculator/chain-queries/svmQuery.js +22 -7
- package/dist/esm/relayFeeCalculator/chain-queries/svmQuery.js.map +1 -1
- package/dist/esm/utils/AddressUtils.d.ts +12 -6
- package/dist/esm/utils/AddressUtils.js +42 -36
- package/dist/esm/utils/AddressUtils.js.map +1 -1
- package/dist/esm/utils/TokenUtils.d.ts +18 -2
- package/dist/esm/utils/TokenUtils.js +6 -4
- package/dist/esm/utils/TokenUtils.js.map +1 -1
- package/dist/types/arch/evm/SpokeUtils.d.ts +2 -6
- 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/arch/svm/eventsClient.d.ts.map +1 -1
- package/dist/types/arch/svm/utils.d.ts +2 -2
- package/dist/types/arch/svm/utils.d.ts.map +1 -1
- package/dist/types/clients/BundleDataClient/utils/SuperstructUtils.d.ts +63 -63
- package/dist/types/clients/BundleDataClient/utils/SuperstructUtils.d.ts.map +1 -1
- 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 +3 -3
- package/dist/types/clients/mocks/MockHubPoolClient.d.ts.map +1 -1
- package/dist/types/clients/mocks/MockSvmCpiEventsClient.d.ts +1 -1
- package/dist/types/clients/mocks/MockSvmCpiEventsClient.d.ts.map +1 -1
- package/dist/types/relayFeeCalculator/chain-queries/baseQuery.d.ts +6 -2
- package/dist/types/relayFeeCalculator/chain-queries/baseQuery.d.ts.map +1 -1
- package/dist/types/relayFeeCalculator/chain-queries/svmQuery.d.ts +7 -2
- package/dist/types/relayFeeCalculator/chain-queries/svmQuery.d.ts.map +1 -1
- package/dist/types/utils/AddressUtils.d.ts +12 -6
- package/dist/types/utils/AddressUtils.d.ts.map +1 -1
- package/dist/types/utils/TokenUtils.d.ts +18 -2
- package/dist/types/utils/TokenUtils.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/arch/evm/SpokeUtils.ts +1 -6
- package/src/arch/svm/SpokeUtils.ts +10 -6
- package/src/arch/svm/eventsClient.ts +40 -8
- package/src/arch/svm/utils.ts +3 -3
- package/src/clients/BundleDataClient/utils/SuperstructUtils.ts +12 -4
- package/src/clients/HubPoolClient.ts +7 -6
- package/src/clients/SpokePoolClient/SpokePoolClient.ts +5 -2
- package/src/clients/mocks/MockHubPoolClient.ts +3 -3
- package/src/clients/mocks/MockSvmCpiEventsClient.ts +8 -5
- package/src/relayFeeCalculator/chain-queries/baseQuery.ts +21 -3
- package/src/relayFeeCalculator/chain-queries/svmQuery.ts +27 -5
- package/src/utils/AddressUtils.ts +41 -41
- package/src/utils/TokenUtils.ts +8 -6
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@across-protocol/sdk",
|
|
3
3
|
"author": "UMA Team",
|
|
4
|
-
"version": "4.2.16-alpha.
|
|
4
|
+
"version": "4.2.16-alpha.5",
|
|
5
5
|
"license": "AGPL-3.0",
|
|
6
6
|
"homepage": "https://docs.across.to/reference/sdk",
|
|
7
7
|
"files": [
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"src"
|
|
11
11
|
],
|
|
12
12
|
"engines": {
|
|
13
|
-
"node": ">=20.
|
|
13
|
+
"node": ">=20.19.2"
|
|
14
14
|
},
|
|
15
15
|
"scripts": {
|
|
16
16
|
"build-bigint-buffer": "node scripts/build-bigint-buffer.js",
|
|
@@ -3,7 +3,6 @@ import { BytesLike, Contract, PopulatedTransaction, providers } from "ethers";
|
|
|
3
3
|
import { CHAIN_IDs } from "../../constants";
|
|
4
4
|
import { Deposit, FillStatus, FillWithBlock, RelayData, RelayExecutionEventInfo } from "../../interfaces";
|
|
5
5
|
import {
|
|
6
|
-
EvmAddress,
|
|
7
6
|
bnUint32Max,
|
|
8
7
|
BigNumber,
|
|
9
8
|
toBN,
|
|
@@ -31,11 +30,7 @@ type BlockTag = providers.BlockTag;
|
|
|
31
30
|
*/
|
|
32
31
|
export function populateV3Relay(
|
|
33
32
|
spokePool: Contract,
|
|
34
|
-
deposit: Omit<Deposit, "messageHash" | "fromLiteChain" | "toLiteChain"
|
|
35
|
-
recipient: EvmAddress;
|
|
36
|
-
outputToken: EvmAddress;
|
|
37
|
-
exclusiveRelayer: EvmAddress;
|
|
38
|
-
},
|
|
33
|
+
deposit: Omit<Deposit, "messageHash" | "fromLiteChain" | "toLiteChain">,
|
|
39
34
|
repaymentAddress: Address,
|
|
40
35
|
repaymentChainId = deposit.destinationChainId
|
|
41
36
|
): Promise<PopulatedTransaction> {
|
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
BigNumber,
|
|
38
38
|
EvmAddress,
|
|
39
39
|
SvmAddress,
|
|
40
|
+
Address as SdkAddress,
|
|
40
41
|
chainIsSvm,
|
|
41
42
|
chunk,
|
|
42
43
|
isUnsafeDepositId,
|
|
@@ -384,7 +385,10 @@ export async function findFillEvent(
|
|
|
384
385
|
*/
|
|
385
386
|
export async function fillRelayInstruction(
|
|
386
387
|
spokePool: SvmAddress,
|
|
387
|
-
deposit: Omit<
|
|
388
|
+
deposit: Omit<
|
|
389
|
+
Deposit,
|
|
390
|
+
"recipient" | "outputToken" | "exclusiveRelayer" | "messageHash" | "fromLiteChain" | "toLiteChain"
|
|
391
|
+
> & {
|
|
388
392
|
recipient: SvmAddress;
|
|
389
393
|
outputToken: SvmAddress;
|
|
390
394
|
exclusiveRelayer: SvmAddress;
|
|
@@ -405,6 +409,7 @@ export async function fillRelayInstruction(
|
|
|
405
409
|
const relayDataHash = new Uint8Array(Buffer.from(_relayDataHash.slice(2), "hex"));
|
|
406
410
|
|
|
407
411
|
const relayer = SvmAddress.from(signer.address);
|
|
412
|
+
|
|
408
413
|
// Create ATA for the relayer and recipient token accounts
|
|
409
414
|
const relayerTokenAccount = await getAssociatedTokenAddress(relayer, deposit.outputToken);
|
|
410
415
|
|
|
@@ -425,13 +430,12 @@ export async function fillRelayInstruction(
|
|
|
425
430
|
program
|
|
426
431
|
);
|
|
427
432
|
|
|
428
|
-
|
|
429
|
-
// from an EVM Spoke pool. Once we migrate to `Address` types, this can be modified/removed.
|
|
430
|
-
const [depositor, inputToken] = [deposit.depositor, deposit.inputToken].map(toAddress);
|
|
431
|
-
const [recipient, outputToken, exclusiveRelayer] = [
|
|
433
|
+
const [recipient, outputToken, exclusiveRelayer, depositor, inputToken] = [
|
|
432
434
|
deposit.recipient,
|
|
433
435
|
deposit.outputToken,
|
|
434
436
|
deposit.exclusiveRelayer,
|
|
437
|
+
deposit.depositor,
|
|
438
|
+
deposit.inputToken,
|
|
435
439
|
].map(toAddress);
|
|
436
440
|
|
|
437
441
|
return SvmSpokeClient.getFillRelayInstruction({
|
|
@@ -639,7 +643,7 @@ export function getRelayDataHash(relayData: RelayData, destinationChainId: numbe
|
|
|
639
643
|
const uint32Encoder = getU32Encoder();
|
|
640
644
|
|
|
641
645
|
assert(relayData.message.startsWith("0x"), "Message must be a hex string");
|
|
642
|
-
const encodeAddress = (data:
|
|
646
|
+
const encodeAddress = (data: SdkAddress) => Uint8Array.from(addressEncoder.encode(toAddress(data)));
|
|
643
647
|
|
|
644
648
|
const contentToHash = Buffer.concat([
|
|
645
649
|
encodeAddress(relayData.depositor),
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
GetTransactionApi,
|
|
11
11
|
Signature,
|
|
12
12
|
} from "@solana/kit";
|
|
13
|
-
import { bs58, chainIsSvm, getMessageHash } from "../../utils";
|
|
13
|
+
import { bs58, chainIsSvm, getMessageHash, toAddressType } from "../../utils";
|
|
14
14
|
import { EventName, EventWithData, SVMProvider } from "./types";
|
|
15
15
|
import { decodeEvent, isDevnet } from "./utils";
|
|
16
16
|
import { Deposit, DepositWithTime, Fill, FillWithTime } from "../../interfaces";
|
|
@@ -252,7 +252,6 @@ export class SvmCpiEventsClient {
|
|
|
252
252
|
|
|
253
253
|
// Filter for FundsDeposited events only
|
|
254
254
|
const depositEvents = events?.filter((event) => event?.name === "FundsDeposited");
|
|
255
|
-
|
|
256
255
|
if (!txDetails || !depositEvents?.length) {
|
|
257
256
|
return;
|
|
258
257
|
}
|
|
@@ -261,13 +260,29 @@ export class SvmCpiEventsClient {
|
|
|
261
260
|
const unwrappedEventArgs = unwrapEventData(event as Record<string, unknown>, ["depositId"]) as Record<
|
|
262
261
|
"data",
|
|
263
262
|
Deposit
|
|
264
|
-
|
|
265
|
-
|
|
263
|
+
> &
|
|
264
|
+
Record<
|
|
265
|
+
"data",
|
|
266
|
+
{
|
|
267
|
+
depositor: string;
|
|
268
|
+
recipient: string;
|
|
269
|
+
exclusiveRelayer: string;
|
|
270
|
+
inputToken: string;
|
|
271
|
+
outputToken: string;
|
|
272
|
+
}
|
|
273
|
+
>;
|
|
274
|
+
|
|
275
|
+
const { data } = unwrappedEventArgs;
|
|
266
276
|
return {
|
|
267
|
-
...
|
|
277
|
+
...data,
|
|
278
|
+
depositor: toAddressType(data.depositor, data.originChainId),
|
|
279
|
+
recipient: toAddressType(data.recipient, data.destinationChainId),
|
|
280
|
+
exclusiveRelayer: toAddressType(data.exclusiveRelayer, data.destinationChainId),
|
|
281
|
+
inputToken: toAddressType(data.inputToken, data.originChainId),
|
|
282
|
+
outputToken: toAddressType(data.outputToken, data.destinationChainId),
|
|
268
283
|
depositTimestamp: Number(txDetails.blockTime),
|
|
269
284
|
originChainId,
|
|
270
|
-
messageHash: getMessageHash(
|
|
285
|
+
messageHash: getMessageHash(data.message),
|
|
271
286
|
blockNumber: Number(txDetails.slot),
|
|
272
287
|
txnIndex: 0,
|
|
273
288
|
txnRef: txSignature,
|
|
@@ -309,9 +324,26 @@ export class SvmCpiEventsClient {
|
|
|
309
324
|
}
|
|
310
325
|
|
|
311
326
|
return fillEvents.map((event) => {
|
|
312
|
-
const unwrappedEventData = unwrapEventData(event as Record<string, unknown>) as Record<"data", Fill
|
|
327
|
+
const unwrappedEventData = unwrapEventData(event as Record<string, unknown>) as Record<"data", Fill> &
|
|
328
|
+
Record<
|
|
329
|
+
"data",
|
|
330
|
+
{
|
|
331
|
+
depositor: string;
|
|
332
|
+
recipient: string;
|
|
333
|
+
exclusiveRelayer: string;
|
|
334
|
+
inputToken: string;
|
|
335
|
+
outputToken: string;
|
|
336
|
+
}
|
|
337
|
+
>;
|
|
338
|
+
|
|
339
|
+
const { data } = unwrappedEventData;
|
|
313
340
|
return {
|
|
314
|
-
...
|
|
341
|
+
...data,
|
|
342
|
+
depositor: toAddressType(data.depositor, data.originChainId),
|
|
343
|
+
recipient: toAddressType(data.recipient, data.destinationChainId),
|
|
344
|
+
exclusiveRelayer: toAddressType(data.exclusiveRelayer, data.destinationChainId),
|
|
345
|
+
inputToken: toAddressType(data.inputToken, data.originChainId),
|
|
346
|
+
outputToken: toAddressType(data.outputToken, data.destinationChainId),
|
|
315
347
|
fillTimestamp: Number(txDetails.blockTime),
|
|
316
348
|
blockNumber: Number(txDetails.slot),
|
|
317
349
|
txnRef: txSignature,
|
package/src/arch/svm/utils.ts
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
} from "@solana/kit";
|
|
18
18
|
import { SvmSpokeClient } from "@across-protocol/contracts";
|
|
19
19
|
import { FillType, RelayData } from "../../interfaces";
|
|
20
|
-
import { BigNumber,
|
|
20
|
+
import { BigNumber, getRelayDataHash, isUint8Array, Address as SdkAddress } from "../../utils";
|
|
21
21
|
import { EventName, SVMEventNames, SVMProvider } from "./types";
|
|
22
22
|
|
|
23
23
|
/**
|
|
@@ -45,7 +45,7 @@ export async function isDevnet(rpc: SVMProvider): Promise<boolean> {
|
|
|
45
45
|
/**
|
|
46
46
|
* Small utility to convert an Address to a Solana Kit branded type.
|
|
47
47
|
*/
|
|
48
|
-
export function toAddress(address:
|
|
48
|
+
export function toAddress(address: SdkAddress): Address<string> {
|
|
49
49
|
return address.toBase58() as Address<string>;
|
|
50
50
|
}
|
|
51
51
|
|
|
@@ -144,7 +144,7 @@ export function unwrapEventData(
|
|
|
144
144
|
}
|
|
145
145
|
// Handle strings (potential addresses)
|
|
146
146
|
if (typeof data === "string" && isAddress(data)) {
|
|
147
|
-
return
|
|
147
|
+
return ethers.utils.hexlify(bs58.decode(data));
|
|
148
148
|
}
|
|
149
149
|
// Handle objects
|
|
150
150
|
if (typeof data === "object") {
|
|
@@ -14,8 +14,8 @@ import {
|
|
|
14
14
|
union,
|
|
15
15
|
type,
|
|
16
16
|
} from "superstruct";
|
|
17
|
-
import { UNDEFINED_MESSAGE_HASH } from "../../../constants";
|
|
18
|
-
import { BigNumber,
|
|
17
|
+
import { CHAIN_IDs, UNDEFINED_MESSAGE_HASH } from "../../../constants";
|
|
18
|
+
import { BigNumber, EvmAddress, RawAddress, SvmAddress, toAddressType } from "../../../utils";
|
|
19
19
|
|
|
20
20
|
const PositiveIntegerStringSS = pattern(string(), /\d+/);
|
|
21
21
|
const Web3AddressSS = pattern(string(), /^0x[a-fA-F0-9]{40}$/);
|
|
@@ -31,8 +31,16 @@ const BigNumberType = coerce(instance(BigNumber), union([string(), number()]), (
|
|
|
31
31
|
}
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
// Accept any concrete implementation of `Address` (Evm, Svm, or Raw) but avoid using the
|
|
35
|
+
// abstract `Address` class directly to keep TypeScript happy.
|
|
36
|
+
const AddressInstanceSS = union([instance(EvmAddress), instance(SvmAddress), instance(RawAddress)]);
|
|
37
|
+
|
|
38
|
+
const AddressType = coerce(AddressInstanceSS, string(), (value) => {
|
|
39
|
+
// Addresses are posted to arweave in their native format (base16 for EVM, base58 for SVM). The chainId for
|
|
40
|
+
// for the event data is not directly available, so infer it based on the shape of the address. RawAddress
|
|
41
|
+
// will be instantiated if the address format does not match the expected family.
|
|
42
|
+
const chainId = value.startsWith("0x") ? CHAIN_IDs.MAINNET : CHAIN_IDs.SOLANA;
|
|
43
|
+
return toAddressType(value, chainId);
|
|
36
44
|
});
|
|
37
45
|
|
|
38
46
|
const FillTypeSS = number();
|
|
@@ -1010,7 +1010,7 @@ export class HubPoolClient extends BaseAbstractClient {
|
|
|
1010
1010
|
const [tokenInfo, lpTokenInfo] = await Promise.all([
|
|
1011
1011
|
Promise.all(
|
|
1012
1012
|
uniqueL1Tokens.map(async (l1Token: string) => {
|
|
1013
|
-
const tokenInfo
|
|
1013
|
+
const tokenInfo = await fetchTokenInfo(l1Token, this.hubPool.provider);
|
|
1014
1014
|
return {
|
|
1015
1015
|
...tokenInfo,
|
|
1016
1016
|
address: EvmAddress.from(l1Token),
|
|
@@ -1049,7 +1049,7 @@ export class HubPoolClient extends BaseAbstractClient {
|
|
|
1049
1049
|
const args = spreadEventWithBlockNumber(_event) as ProposedRootBundle & { proposer: string };
|
|
1050
1050
|
return {
|
|
1051
1051
|
...args,
|
|
1052
|
-
proposer:
|
|
1052
|
+
proposer: EvmAddress.from(args.proposer),
|
|
1053
1053
|
};
|
|
1054
1054
|
})
|
|
1055
1055
|
);
|
|
@@ -1086,11 +1086,12 @@ export class HubPoolClient extends BaseAbstractClient {
|
|
|
1086
1086
|
);
|
|
1087
1087
|
}
|
|
1088
1088
|
executedRootBundle.runningBalances = runningBalances.slice(0, nTokens);
|
|
1089
|
-
|
|
1089
|
+
this.executedRootBundles.push({
|
|
1090
1090
|
...executedRootBundle,
|
|
1091
|
-
l1Tokens:
|
|
1092
|
-
|
|
1093
|
-
|
|
1091
|
+
l1Tokens: l1Tokens.map((token: string) => {
|
|
1092
|
+
return EvmAddress.from(token, "base16");
|
|
1093
|
+
}),
|
|
1094
|
+
});
|
|
1094
1095
|
}
|
|
1095
1096
|
}
|
|
1096
1097
|
|
|
@@ -588,13 +588,16 @@ export abstract class SpokePoolClient extends BaseAbstractClient {
|
|
|
588
588
|
.map((_event) => {
|
|
589
589
|
const event = _event as SpeedUpWithBlock & { depositor: string; updatedRecipient: string };
|
|
590
590
|
|
|
591
|
-
|
|
591
|
+
const invalid = [event.depositor, event.updatedRecipient].some(
|
|
592
|
+
(addr) => !EvmAddress.validate(ethersUtils.arrayify(addr))
|
|
593
|
+
);
|
|
594
|
+
if (invalid) {
|
|
592
595
|
return;
|
|
593
596
|
}
|
|
594
597
|
|
|
595
598
|
return {
|
|
596
599
|
...event,
|
|
597
|
-
depositor:
|
|
600
|
+
depositor: EvmAddress.from(event.depositor),
|
|
598
601
|
updatedRecipient: EvmAddress.from(event.updatedRecipient),
|
|
599
602
|
} as SpeedUpWithBlock;
|
|
600
603
|
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import winston from "winston";
|
|
2
2
|
import { Contract } from "ethers";
|
|
3
3
|
import { BigNumber, randomAddress, assign, bnZero, toAddressType, EvmAddress, Address, isDefined } from "../../utils";
|
|
4
|
-
import {
|
|
4
|
+
import { Log, PendingRootBundle, RealizedLpFee, L1TokenInfo } from "../../interfaces";
|
|
5
5
|
import { AcrossConfigStoreClient as ConfigStoreClient } from "../AcrossConfigStoreClient";
|
|
6
6
|
import { HubPoolClient, HubPoolUpdate, LpFeeRequest } from "../HubPoolClient";
|
|
7
7
|
import { EventManager, EventOverrides, getEventManager } from "./MockEvents";
|
|
@@ -83,7 +83,7 @@ export class MockHubPoolClient extends HubPoolClient {
|
|
|
83
83
|
this.latestHeightSearched = blockNumber;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
addL1Token(l1Token:
|
|
86
|
+
addL1Token(l1Token: L1TokenInfo) {
|
|
87
87
|
this.l1TokensMock.push(l1Token);
|
|
88
88
|
}
|
|
89
89
|
|
|
@@ -132,7 +132,7 @@ export class MockHubPoolClient extends HubPoolClient {
|
|
|
132
132
|
return l2Token ?? super.getL2TokenForL1TokenAtBlock(l1Token, chainId, blockNumber);
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
getTokenInfoForL1Token(l1Token: EvmAddress):
|
|
135
|
+
getTokenInfoForL1Token(l1Token: EvmAddress): L1TokenInfo | undefined {
|
|
136
136
|
return this.l1TokensMock.find((token) => token.address.eq(l1Token));
|
|
137
137
|
}
|
|
138
138
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import assert from "assert";
|
|
2
|
+
import { utils as ethersUtils } from "ethers";
|
|
2
3
|
import { createHash } from "crypto";
|
|
3
4
|
import { hexlify, arrayify, hexZeroPad } from "ethers/lib/utils";
|
|
4
5
|
import { random } from "lodash";
|
|
@@ -17,9 +18,11 @@ import {
|
|
|
17
18
|
SVMProvider,
|
|
18
19
|
getRandomSvmAddress,
|
|
19
20
|
} from "../../arch/svm";
|
|
20
|
-
import { bnZero, bnOne, bs58, getCurrentTime, randomAddress, EvmAddress } from "../../utils";
|
|
21
|
+
import { bnZero, bnOne, bs58, getCurrentTime, randomAddress, EvmAddress, SvmAddress } from "../../utils";
|
|
21
22
|
import { FillType } from "../../interfaces";
|
|
22
23
|
|
|
24
|
+
const randomBytes = (n: number) => ethersUtils.hexlify(ethersUtils.randomBytes(n));
|
|
25
|
+
|
|
23
26
|
export class MockSvmCpiEventsClient extends SvmCpiEventsClient {
|
|
24
27
|
private events: Record<EventName, EventWithData[]> = {} as Record<EventName, EventWithData[]>;
|
|
25
28
|
private slotHeight: bigint = BigInt(0);
|
|
@@ -75,9 +78,9 @@ export class MockSvmCpiEventsClient extends SvmCpiEventsClient {
|
|
|
75
78
|
|
|
76
79
|
destinationChainId ??= BigInt(random(1, 42161, false));
|
|
77
80
|
const depositor = deposit.depositor ?? getRandomSvmAddress();
|
|
78
|
-
const recipient = deposit.recipient ??
|
|
81
|
+
const recipient = deposit.recipient ?? SvmAddress.from(randomBytes(32), "base16").toBase58();
|
|
79
82
|
const inputToken = deposit.inputToken ?? getRandomSvmAddress();
|
|
80
|
-
const outputToken = deposit.outputToken ??
|
|
83
|
+
const outputToken = deposit.outputToken ?? SvmAddress.from(randomBytes(32), "base16").toBase58();
|
|
81
84
|
inputAmount ??= BigInt(random(1, 1000, false));
|
|
82
85
|
outputAmount ??= (inputAmount * BigInt(95)) / BigInt(100);
|
|
83
86
|
const message = deposit.message ?? new Uint8Array(32);
|
|
@@ -158,9 +161,9 @@ export class MockSvmCpiEventsClient extends SvmCpiEventsClient {
|
|
|
158
161
|
let { depositId, originChainId } = slowFillRequest;
|
|
159
162
|
depositId ??= Uint8Array.from([random(1, 100_000, false)]);
|
|
160
163
|
originChainId ??= BigInt(random(1, 42161, false));
|
|
161
|
-
const depositor = slowFillRequest.depositor ??
|
|
164
|
+
const depositor = slowFillRequest.depositor ?? SvmAddress.from(randomBytes(32)).toBase58();
|
|
162
165
|
const recipient = slowFillRequest.recipient ?? getRandomSvmAddress();
|
|
163
|
-
const inputToken = slowFillRequest.inputToken ??
|
|
166
|
+
const inputToken = slowFillRequest.inputToken ?? SvmAddress.from(randomBytes(32)).toBase58();
|
|
164
167
|
const outputToken = slowFillRequest.outputToken ?? getRandomSvmAddress();
|
|
165
168
|
|
|
166
169
|
const args = {
|
|
@@ -9,6 +9,7 @@ import { SpokePool, SpokePool__factory } from "../../typechain";
|
|
|
9
9
|
import { populateV3Relay } from "../../arch/evm";
|
|
10
10
|
import {
|
|
11
11
|
BigNumberish,
|
|
12
|
+
EvmAddress,
|
|
12
13
|
TransactionCostEstimate,
|
|
13
14
|
BigNumber,
|
|
14
15
|
toBNWei,
|
|
@@ -93,7 +94,12 @@ export class QueryBase implements QueryInterface {
|
|
|
93
94
|
transport,
|
|
94
95
|
} = options;
|
|
95
96
|
|
|
96
|
-
const
|
|
97
|
+
const { recipient, outputToken, exclusiveRelayer } = deposit;
|
|
98
|
+
assert(recipient.isEVM(), `getGasCosts: recipient not an EVM address (${recipient})`);
|
|
99
|
+
assert(outputToken.isEVM(), `getGasCosts: outputToken not an EVM address (${outputToken})`);
|
|
100
|
+
assert(exclusiveRelayer.isEVM(), `getGasCosts: exclusiveRelayer not an EVM address (${exclusiveRelayer})`);
|
|
101
|
+
|
|
102
|
+
const tx = await this.getUnsignedTxFromDeposit({ ...deposit, recipient, outputToken, exclusiveRelayer }, relayer);
|
|
97
103
|
const {
|
|
98
104
|
nativeGasCost,
|
|
99
105
|
tokenGasCost,
|
|
@@ -123,7 +129,11 @@ export class QueryBase implements QueryInterface {
|
|
|
123
129
|
* @returns PopulatedTransaction
|
|
124
130
|
*/
|
|
125
131
|
getUnsignedTxFromDeposit(
|
|
126
|
-
deposit: Omit<Deposit, "messageHash"
|
|
132
|
+
deposit: Omit<Deposit, "messageHash"> & {
|
|
133
|
+
recipient: EvmAddress;
|
|
134
|
+
outputToken: EvmAddress;
|
|
135
|
+
exclusiveRelayer: EvmAddress;
|
|
136
|
+
},
|
|
127
137
|
relayer = toAddressType(getDefaultSimulatedRelayerAddress(deposit.destinationChainId), deposit.destinationChainId)
|
|
128
138
|
): Promise<PopulatedTransaction> {
|
|
129
139
|
return populateV3Relay(this.spokePool, deposit, relayer);
|
|
@@ -139,7 +149,15 @@ export class QueryBase implements QueryInterface {
|
|
|
139
149
|
deposit: Omit<Deposit, "messageHash">,
|
|
140
150
|
relayer = toAddressType(getDefaultSimulatedRelayerAddress(deposit.destinationChainId), deposit.destinationChainId)
|
|
141
151
|
): Promise<BigNumber> {
|
|
142
|
-
const
|
|
152
|
+
const { recipient, outputToken, exclusiveRelayer } = deposit;
|
|
153
|
+
assert(recipient.isEVM(), `getNativeGasCost: recipient not an EVM address (${recipient})`);
|
|
154
|
+
assert(outputToken.isEVM(), `getNativeGasCost: outputToken not an EVM address (${outputToken})`);
|
|
155
|
+
assert(exclusiveRelayer.isEVM(), `getNativeGasCost: exclusiveRelayer not an EVM address (${exclusiveRelayer})`);
|
|
156
|
+
|
|
157
|
+
const unsignedTx = await this.getUnsignedTxFromDeposit(
|
|
158
|
+
{ ...deposit, recipient, outputToken, exclusiveRelayer },
|
|
159
|
+
relayer
|
|
160
|
+
);
|
|
143
161
|
const voidSigner = new VoidSigner(relayer.toEvmAddress(), this.provider);
|
|
144
162
|
return voidSigner.estimateGas(unsignedTx);
|
|
145
163
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import assert from "assert";
|
|
1
2
|
import { SvmSpokeClient } from "@across-protocol/contracts";
|
|
2
3
|
import { intToU8Array32 } from "@across-protocol/contracts/dist/src/svm/web3-v1/conversionUtils";
|
|
3
4
|
import { SYSTEM_PROGRAM_ADDRESS } from "@solana-program/system";
|
|
@@ -83,7 +84,12 @@ export class SvmQuery implements QueryInterface {
|
|
|
83
84
|
priorityFeeMultiplier: BigNumber;
|
|
84
85
|
}> = {}
|
|
85
86
|
): Promise<TransactionCostEstimate> {
|
|
86
|
-
const
|
|
87
|
+
const { recipient, outputToken, exclusiveRelayer } = deposit;
|
|
88
|
+
assert(recipient.isSVM(), `getGasCosts: recipient not an SVM address (${recipient})`);
|
|
89
|
+
assert(outputToken.isSVM(), `getGasCosts: outputToken not an SVM address (${outputToken})`);
|
|
90
|
+
assert(exclusiveRelayer.isSVM(), `getGasCosts: exclusiveRelayer not an SVM address (${exclusiveRelayer})`);
|
|
91
|
+
|
|
92
|
+
const fillRelayTx = await this.getFillRelayTx({ ...deposit, recipient, outputToken, exclusiveRelayer }, relayer);
|
|
87
93
|
|
|
88
94
|
const [computeUnitsConsumed, gasPriceEstimate] = await Promise.all([
|
|
89
95
|
toBN(await this.computeUnitEstimator(fillRelayTx)),
|
|
@@ -114,10 +120,15 @@ export class SvmQuery implements QueryInterface {
|
|
|
114
120
|
* @returns Estimated gas cost in compute units
|
|
115
121
|
*/
|
|
116
122
|
async getNativeGasCost(
|
|
117
|
-
deposit: Omit<Deposit, "messageHash">,
|
|
123
|
+
deposit: Omit<Deposit, "messageHash">, // @todo Update interface to permit EvmAddress | SvmAddress
|
|
118
124
|
_relayer = toAddressType(getDefaultSimulatedRelayerAddress(deposit.destinationChainId), deposit.destinationChainId)
|
|
119
125
|
): Promise<BigNumber> {
|
|
120
|
-
const
|
|
126
|
+
const { recipient, outputToken, exclusiveRelayer } = deposit;
|
|
127
|
+
assert(recipient.isSVM(), `getNativeGasCost: recipient not an SVM address (${recipient})`);
|
|
128
|
+
assert(outputToken.isSVM(), `getNativeGasCost: outputToken not an SVM address (${outputToken})`);
|
|
129
|
+
assert(exclusiveRelayer.isSVM(), `getNativeGasCost: exclusiveRelayer not an SVM address (${exclusiveRelayer})`);
|
|
130
|
+
|
|
131
|
+
const fillRelayTx = await this.getFillRelayTx({ ...deposit, recipient, outputToken, exclusiveRelayer }, _relayer);
|
|
121
132
|
return toBN(await this.computeUnitEstimator(fillRelayTx));
|
|
122
133
|
}
|
|
123
134
|
|
|
@@ -128,7 +139,11 @@ export class SvmQuery implements QueryInterface {
|
|
|
128
139
|
* @returns FillRelay transaction
|
|
129
140
|
*/
|
|
130
141
|
async getFillRelayTx(
|
|
131
|
-
deposit: Omit<Deposit, "messageHash"
|
|
142
|
+
deposit: Omit<Deposit, "recipent" | "outputToken" | "exclusiveRelayer" | "messageHash"> & {
|
|
143
|
+
recipient: SvmAddress;
|
|
144
|
+
outputToken: SvmAddress;
|
|
145
|
+
exclusiveRelayer: SvmAddress;
|
|
146
|
+
},
|
|
132
147
|
relayer = toAddressType(getDefaultSimulatedRelayerAddress(deposit.destinationChainId), deposit.destinationChainId),
|
|
133
148
|
repaymentChainId = deposit.destinationChainId,
|
|
134
149
|
repaymentAddress = toAddressType(
|
|
@@ -138,6 +153,13 @@ export class SvmQuery implements QueryInterface {
|
|
|
138
153
|
) {
|
|
139
154
|
const { depositor, recipient, inputToken, outputToken, exclusiveRelayer, destinationChainId } = deposit;
|
|
140
155
|
|
|
156
|
+
// tsc appeasement...should be unnecessary, but isn't. @todo Identify why.
|
|
157
|
+
assert(recipient.isSVM(), `getFillRelayTx: recipient not an SVM address (${recipient})`);
|
|
158
|
+
assert(
|
|
159
|
+
repaymentAddress.isValidOn(repaymentChainId),
|
|
160
|
+
`getFillRelayTx: repayment address ${repaymentAddress} not valid on chain ${repaymentChainId})`
|
|
161
|
+
);
|
|
162
|
+
|
|
141
163
|
const program = toAddress(this.spokePool);
|
|
142
164
|
const _relayDataHash = getRelayDataHash(deposit, destinationChainId);
|
|
143
165
|
const relayDataHash = new Uint8Array(Buffer.from(_relayDataHash.slice(2), "hex"));
|
|
@@ -151,7 +173,7 @@ export class SvmQuery implements QueryInterface {
|
|
|
151
173
|
const mintInfo = await fetchMint(this.provider, mint);
|
|
152
174
|
|
|
153
175
|
const [recipientAta, relayerAta, fillStatus, eventAuthority] = await Promise.all([
|
|
154
|
-
getAssociatedTokenAddress(
|
|
176
|
+
getAssociatedTokenAddress(recipient, outputToken, mintInfo.programAddress),
|
|
155
177
|
getAssociatedTokenAddress(SvmAddress.from(relayer.toBase58()), outputToken, mintInfo.programAddress),
|
|
156
178
|
getFillStatusPda(program, deposit, destinationChainId),
|
|
157
179
|
getEventAuthority(program),
|
|
@@ -81,15 +81,15 @@ export function isValidEvmAddress(address: string): boolean {
|
|
|
81
81
|
export function toAddressType(address: string, chainId: number): Address {
|
|
82
82
|
const rawAddress = address.startsWith("0x") ? utils.arrayify(address) : bs58.decode(address);
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
if (
|
|
86
|
-
|
|
87
|
-
return new
|
|
84
|
+
if (chainIsEvm(chainId) && EvmAddress.validate(rawAddress)) return new EvmAddress(rawAddress);
|
|
85
|
+
else if (chainIsSvm(chainId) && SvmAddress.validate(rawAddress)) return new SvmAddress(rawAddress);
|
|
86
|
+
|
|
87
|
+
return new RawAddress(rawAddress);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
// The Address class can contain any address type. It is up to the subclasses to determine how to format the address's internal representation,
|
|
91
91
|
// which for this class, is a bytes32 hex string.
|
|
92
|
-
export class Address {
|
|
92
|
+
export abstract class Address {
|
|
93
93
|
readonly rawAddress: Uint8Array;
|
|
94
94
|
|
|
95
95
|
// Keep all address types in cache so that we may lazily evaluate them when necessary.
|
|
@@ -109,10 +109,6 @@ export class Address {
|
|
|
109
109
|
this.rawAddress = utils.zeroPad(_rawAddress, 32);
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
static __unsafeConstruct(_rawAddress: Uint8Array): Address {
|
|
113
|
-
return new this(_rawAddress);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
112
|
// Converts the address into a bytes32 string. Note that the output bytes will be lowercase so that it matches ethers event data. This function will never
|
|
117
113
|
// throw since address length validation was done at construction time.
|
|
118
114
|
toBytes32(): string {
|
|
@@ -167,11 +163,6 @@ export class Address {
|
|
|
167
163
|
return false;
|
|
168
164
|
}
|
|
169
165
|
|
|
170
|
-
// Checks if the object is an address by looking at whether it has an Address constructor.
|
|
171
|
-
static isAddress(obj: unknown): boolean {
|
|
172
|
-
return obj instanceof this;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
166
|
// Converts the input address to a 32-byte hex data string.
|
|
176
167
|
toString(): string {
|
|
177
168
|
return this.toNative();
|
|
@@ -193,6 +184,7 @@ export class Address {
|
|
|
193
184
|
}
|
|
194
185
|
|
|
195
186
|
// Compares Addresses by first converting them to BigNumbers.
|
|
187
|
+
// note: Intended for use when sorting like addresses.
|
|
196
188
|
compare(otherAddress: Address): 1 | -1 | 0 {
|
|
197
189
|
// Convert address strings to BigNumbers and then sort numerical value of the BigNumber, which sorts the addresses
|
|
198
190
|
// effectively by their hex value.
|
|
@@ -207,17 +199,19 @@ export class Address {
|
|
|
207
199
|
}
|
|
208
200
|
}
|
|
209
201
|
|
|
210
|
-
|
|
211
|
-
return
|
|
202
|
+
isEVM(): this is EvmAddress {
|
|
203
|
+
return false;
|
|
212
204
|
}
|
|
213
205
|
|
|
214
|
-
|
|
215
|
-
return
|
|
206
|
+
isSVM(): this is SvmAddress {
|
|
207
|
+
return false;
|
|
216
208
|
}
|
|
217
209
|
}
|
|
218
210
|
|
|
219
211
|
// Subclass of address which strictly deals with 20-byte addresses. These addresses are guaranteed to be valid EVM addresses, so `toAddress` will always succeed.
|
|
220
212
|
export class EvmAddress extends Address {
|
|
213
|
+
private readonly _type = "evm";
|
|
214
|
+
|
|
221
215
|
// On construction, validate that the address can indeed be coerced into an EVM address. Throw immediately if it cannot.
|
|
222
216
|
constructor(rawAddress: Uint8Array) {
|
|
223
217
|
if (!EvmAddress.validate(rawAddress)) {
|
|
@@ -225,6 +219,7 @@ export class EvmAddress extends Address {
|
|
|
225
219
|
}
|
|
226
220
|
|
|
227
221
|
super(rawAddress);
|
|
222
|
+
this._type; // tsc noUnusedLocals appeasement.
|
|
228
223
|
}
|
|
229
224
|
|
|
230
225
|
static validate(rawAddress: Uint8Array): boolean {
|
|
@@ -233,31 +228,25 @@ export class EvmAddress extends Address {
|
|
|
233
228
|
);
|
|
234
229
|
}
|
|
235
230
|
|
|
231
|
+
override isEVM(): this is EvmAddress {
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
234
|
+
|
|
236
235
|
// Override `toAddress` to return the 20-byte representation address.
|
|
237
236
|
override toNative(): string {
|
|
238
237
|
return this.toEvmAddress();
|
|
239
238
|
}
|
|
240
239
|
|
|
241
240
|
// Constructs a new EvmAddress type.
|
|
242
|
-
static from(address: string, encoding: "
|
|
243
|
-
|
|
244
|
-
return new this(utils.arrayify(address));
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
const decodedAddress = bs58.decode(address);
|
|
248
|
-
const padding = decodedAddress.subarray(0, 12);
|
|
249
|
-
const evmAddress = decodedAddress.subarray(12);
|
|
250
|
-
|
|
251
|
-
if (padding.length !== 12 || utils.stripZeros(padding).length !== 0 || evmAddress.length !== 20) {
|
|
252
|
-
throw new Error(`Not a valid base58-encoded EVM address: ${address}`);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
return new this(evmAddress);
|
|
241
|
+
static from(address: string, encoding: "base58" | "base16" = "base16"): EvmAddress {
|
|
242
|
+
return encoding === "base16" ? new this(utils.arrayify(address)) : new this(bs58.decode(address));
|
|
256
243
|
}
|
|
257
244
|
}
|
|
258
245
|
|
|
259
246
|
// Subclass of address which strictly deals SVM addresses. These addresses are guaranteed to be valid SVM addresses, so `toBase58` will always produce a valid Solana address.
|
|
260
247
|
export class SvmAddress extends Address {
|
|
248
|
+
private readonly _type = "svm";
|
|
249
|
+
|
|
261
250
|
// On construction, validate that the address is a point on Curve25519. Throw immediately if it is not.
|
|
262
251
|
constructor(rawAddress: Uint8Array) {
|
|
263
252
|
if (!SvmAddress.validate(rawAddress)) {
|
|
@@ -265,10 +254,21 @@ export class SvmAddress extends Address {
|
|
|
265
254
|
}
|
|
266
255
|
|
|
267
256
|
super(rawAddress);
|
|
257
|
+
this._type; // tsc noUnusedLocals appeasement.
|
|
268
258
|
}
|
|
269
259
|
|
|
270
260
|
static validate(rawAddress: Uint8Array): boolean {
|
|
271
|
-
|
|
261
|
+
// Deliberately invalidate SVM addresses w/ the upper 12 bytes zeroed. These addresses are technically valid
|
|
262
|
+
// but highly improbable and are much more likely to be a mistaken interpretation of an EVM address. Err on
|
|
263
|
+
// the side of caution for the time being. Exception: Permit the zero address (i.e. for exclusiverRelayer).
|
|
264
|
+
return (
|
|
265
|
+
rawAddress.length === 32 &&
|
|
266
|
+
(!rawAddress.slice(0, 12).every((field) => field === 0) || rawAddress.every((field) => field === 0))
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
override isSVM(): this is SvmAddress {
|
|
271
|
+
return true;
|
|
272
272
|
}
|
|
273
273
|
|
|
274
274
|
// Override the toAddress function for SVM addresses only since while they will never have a defined 20-byte representation. The base58 encoded addresses are also the encodings
|
|
@@ -279,15 +279,15 @@ export class SvmAddress extends Address {
|
|
|
279
279
|
|
|
280
280
|
// Constructs a new SvmAddress type.
|
|
281
281
|
static from(address: string, encoding: "base58" | "base16" = "base58"): SvmAddress {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
282
|
+
return encoding === "base58" ? new this(bs58.decode(address)) : new this(utils.arrayify(address));
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
285
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
throw new Error(`Not a valid base16-encoded SVM address: ${address}`);
|
|
289
|
-
}
|
|
286
|
+
export class RawAddress extends Address {
|
|
287
|
+
private readonly _type = "raw";
|
|
290
288
|
|
|
291
|
-
|
|
289
|
+
constructor(rawAddress: Uint8Array) {
|
|
290
|
+
super(rawAddress);
|
|
291
|
+
this._type; // tsc noUnusedLocals appeasement.
|
|
292
292
|
}
|
|
293
293
|
}
|