@aptos-labs/cross-chain-core 4.23.1

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 (66) hide show
  1. package/LICENSE +201 -0
  2. package/dist/CrossChainCore.d.ts +36 -0
  3. package/dist/CrossChainCore.d.ts.map +1 -0
  4. package/dist/config/index.d.ts +4 -0
  5. package/dist/config/index.d.ts.map +1 -0
  6. package/dist/config/mainnet/chains.d.ts +17 -0
  7. package/dist/config/mainnet/chains.d.ts.map +1 -0
  8. package/dist/config/mainnet/index.d.ts +3 -0
  9. package/dist/config/mainnet/index.d.ts.map +1 -0
  10. package/dist/config/mainnet/tokens.d.ts +4 -0
  11. package/dist/config/mainnet/tokens.d.ts.map +1 -0
  12. package/dist/config/testnet/chains.d.ts +19 -0
  13. package/dist/config/testnet/chains.d.ts.map +1 -0
  14. package/dist/config/testnet/index.d.ts +3 -0
  15. package/dist/config/testnet/index.d.ts.map +1 -0
  16. package/dist/config/testnet/tokens.d.ts +4 -0
  17. package/dist/config/testnet/tokens.d.ts.map +1 -0
  18. package/dist/config/types.d.ts +41 -0
  19. package/dist/config/types.d.ts.map +1 -0
  20. package/dist/index.d.ts +6 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +989 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/index.mjs +957 -0
  25. package/dist/index.mjs.map +1 -0
  26. package/dist/providers/wormhole/index.d.ts +5 -0
  27. package/dist/providers/wormhole/index.d.ts.map +1 -0
  28. package/dist/providers/wormhole/signers/AptosLocalSigner.d.ts +18 -0
  29. package/dist/providers/wormhole/signers/AptosLocalSigner.d.ts.map +1 -0
  30. package/dist/providers/wormhole/signers/EthereumSigner.d.ts +5 -0
  31. package/dist/providers/wormhole/signers/EthereumSigner.d.ts.map +1 -0
  32. package/dist/providers/wormhole/signers/Signer.d.ts +17 -0
  33. package/dist/providers/wormhole/signers/Signer.d.ts.map +1 -0
  34. package/dist/providers/wormhole/signers/SolanaSigner.d.ts +28 -0
  35. package/dist/providers/wormhole/signers/SolanaSigner.d.ts.map +1 -0
  36. package/dist/providers/wormhole/types.d.ts +39 -0
  37. package/dist/providers/wormhole/types.d.ts.map +1 -0
  38. package/dist/providers/wormhole/wormhole.d.ts +35 -0
  39. package/dist/providers/wormhole/wormhole.d.ts.map +1 -0
  40. package/dist/utils/getUsdcBalance.d.ts +5 -0
  41. package/dist/utils/getUsdcBalance.d.ts.map +1 -0
  42. package/dist/utils/logger.d.ts +6 -0
  43. package/dist/utils/logger.d.ts.map +1 -0
  44. package/dist/version.d.ts +2 -0
  45. package/dist/version.d.ts.map +1 -0
  46. package/package.json +83 -0
  47. package/src/CrossChainCore.ts +130 -0
  48. package/src/config/index.ts +3 -0
  49. package/src/config/mainnet/chains.ts +64 -0
  50. package/src/config/mainnet/index.ts +2 -0
  51. package/src/config/mainnet/tokens.ts +43 -0
  52. package/src/config/testnet/chains.ts +69 -0
  53. package/src/config/testnet/index.ts +2 -0
  54. package/src/config/testnet/tokens.ts +43 -0
  55. package/src/config/types.ts +45 -0
  56. package/src/index.ts +5 -0
  57. package/src/providers/wormhole/index.ts +4 -0
  58. package/src/providers/wormhole/signers/AptosLocalSigner.ts +136 -0
  59. package/src/providers/wormhole/signers/EthereumSigner.ts +49 -0
  60. package/src/providers/wormhole/signers/Signer.ts +102 -0
  61. package/src/providers/wormhole/signers/SolanaSigner.ts +418 -0
  62. package/src/providers/wormhole/types.ts +59 -0
  63. package/src/providers/wormhole/wormhole.ts +320 -0
  64. package/src/utils/getUsdcBalance.ts +82 -0
  65. package/src/utils/logger.ts +17 -0
  66. package/src/version.ts +1 -0
@@ -0,0 +1,64 @@
1
+ import { Context, ChainsConfig } from "../types";
2
+
3
+ export const mainnetChains: ChainsConfig = {
4
+ Ethereum: {
5
+ key: "Ethereum",
6
+ id: 2,
7
+ context: Context.ETH,
8
+ finalityThreshold: 64,
9
+ displayName: "Ethereum",
10
+ explorerUrl: "https://etherscan.io/",
11
+ explorerName: "Etherscan",
12
+ gasToken: "ETH",
13
+ chainId: 1,
14
+ icon: "Ethereum",
15
+ maxBlockSearch: 2000,
16
+ symbol: "ETH",
17
+ defaultRpc: "https://rpc.ankr.com/eth",
18
+ },
19
+ Solana: {
20
+ key: "Solana",
21
+ id: 1,
22
+ context: Context.SOLANA,
23
+ finalityThreshold: 32,
24
+ displayName: "Solana",
25
+ explorerUrl: "https://explorer.solana.com/",
26
+ explorerName: "Solana Explorer",
27
+ gasToken: "SOL",
28
+ chainId: 0,
29
+ icon: "Solana",
30
+ maxBlockSearch: 2000,
31
+ symbol: "SOL",
32
+ defaultRpc: "https://solana-mainnet.rpc.extrnode.com",
33
+ },
34
+ // Sui: {
35
+ // key: "Sui",
36
+ // id: 21,
37
+ // context: Context.SUI,
38
+ // finalityThreshold: 0,
39
+ // displayName: "Sui",
40
+ // sdkName: "Sui",
41
+ // explorerUrl: "https://suiscan.xyz/",
42
+ // explorerName: "Suiscan",
43
+ // gasToken: "SUI",
44
+ // chainId: 0,
45
+ // icon: "Sui",
46
+ // maxBlockSearch: 0,
47
+ // symbol: "SUI",
48
+ // },
49
+ };
50
+
51
+ export const AptosMainnetChain = {
52
+ key: "Aptos",
53
+ id: 22,
54
+ context: "Aptos",
55
+ finalityThreshold: 0,
56
+ displayName: "Aptos",
57
+ explorerUrl: "https://explorer.aptoslabs.com/",
58
+ explorerName: "Aptos Explorer",
59
+ gasToken: "APT",
60
+ chainId: 0,
61
+ icon: "Aptos",
62
+ maxBlockSearch: 0,
63
+ symbol: "APT",
64
+ };
@@ -0,0 +1,2 @@
1
+ export * from "./chains";
2
+ export * from "./tokens";
@@ -0,0 +1,43 @@
1
+ import { TokenConfig } from "../types";
2
+
3
+ export const mainnetTokens: Record<string, TokenConfig> = {
4
+ Ethereum: {
5
+ symbol: "USDC",
6
+ tokenId: {
7
+ chain: "Ethereum",
8
+ address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
9
+ },
10
+ icon: "USDC",
11
+ decimals: 6,
12
+ },
13
+ Solana: {
14
+ symbol: "USDC",
15
+ tokenId: {
16
+ chain: "Solana",
17
+ address: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
18
+ },
19
+ icon: "USDC",
20
+ decimals: 6,
21
+ },
22
+ // Sui: {
23
+ // symbol: "USDC",
24
+ // decimals: 6,
25
+ // tokenId: {
26
+ // chain: "Sui",
27
+ // address:
28
+ // "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC",
29
+ // },
30
+ // icon: "USDC",
31
+ // },
32
+ };
33
+
34
+ export const AptosMainnetUSDCToken: TokenConfig = {
35
+ symbol: "USDC",
36
+ tokenId: {
37
+ chain: "Aptos",
38
+ address:
39
+ "0xbae207659db88bea0cbead6da0ed00aac12edcdda169e591cd41c94180b46f3b",
40
+ },
41
+ icon: "USDC",
42
+ decimals: 6,
43
+ };
@@ -0,0 +1,69 @@
1
+ import { Context } from "../types";
2
+
3
+ import { ChainsConfig } from "../types";
4
+
5
+ export const testnetChains: ChainsConfig = {
6
+ Sepolia: {
7
+ key: "Sepolia",
8
+ id: 10002,
9
+ context: Context.ETH,
10
+ finalityThreshold: 0,
11
+ displayName: "Sepolia",
12
+ explorerUrl: "https://sepolia.etherscan.io/",
13
+ explorerName: "Etherscan",
14
+ gasToken: "ETHsepolia",
15
+ chainId: 11155111,
16
+ icon: "Ethereum",
17
+ maxBlockSearch: 2000,
18
+ symbol: "ETH",
19
+ defaultRpc: "https://eth-sepolia.public.blastapi.io",
20
+ wrappedGasToken: "0xeef12A83EE5b7161D3873317c8E0E7B76e0B5D9c",
21
+ },
22
+ Solana: {
23
+ key: "Solana",
24
+ id: 1,
25
+ context: Context.SOLANA,
26
+ finalityThreshold: 32,
27
+ displayName: "Solana",
28
+ explorerUrl: "https://explorer.solana.com/",
29
+ explorerName: "Solana Explorer",
30
+ gasToken: "SOL",
31
+ chainId: 0,
32
+ icon: "Solana",
33
+ maxBlockSearch: 2000,
34
+ symbol: "SOL",
35
+ defaultRpc: "https://api.devnet.solana.com",
36
+ wrappedGasToken: "So11111111111111111111111111111111111111112",
37
+ },
38
+ // Sui: {
39
+ // key: "Sui",
40
+ // id: 21,
41
+ // context: Context.SUI,
42
+ // finalityThreshold: 0,
43
+ // displayName: "Sui",
44
+ // explorerUrl: "https://suiscan.xyz/testnet/",
45
+ // explorerName: "Suiscan",
46
+ // gasToken: "SUI",
47
+ // chainId: 0,
48
+ // icon: "Sui",
49
+ // maxBlockSearch: 0,
50
+ // symbol: "SUI",
51
+ // sdkName: "Sui",
52
+ // },
53
+ };
54
+
55
+ export const AptosTestnetChain = {
56
+ key: "Aptos",
57
+ id: 22,
58
+ context: Context.APTOS,
59
+ finalityThreshold: 0,
60
+ displayName: "Aptos",
61
+ explorerUrl: "https://explorer.aptoslabs.com?network=testnet",
62
+ explorerName: "Aptos Explorer",
63
+ gasToken: "APT",
64
+ chainId: 0,
65
+ icon: "Aptos",
66
+ maxBlockSearch: 0,
67
+ symbol: "APT",
68
+ sdkName: "Aptos",
69
+ };
@@ -0,0 +1,2 @@
1
+ export * from "./chains";
2
+ export * from "./tokens";
@@ -0,0 +1,43 @@
1
+ import { TokenConfig } from "../types";
2
+
3
+ export const testnetTokens: Record<string, TokenConfig> = {
4
+ Sepolia: {
5
+ symbol: "USDC",
6
+ icon: "USDC",
7
+ decimals: 6,
8
+ tokenId: {
9
+ chain: "Sepolia",
10
+ address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
11
+ },
12
+ },
13
+ Solana: {
14
+ symbol: "USDC",
15
+ tokenId: {
16
+ chain: "Solana",
17
+ address: "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",
18
+ },
19
+ icon: "USDC",
20
+ decimals: 6,
21
+ },
22
+ // Sui: {
23
+ // symbol: "USDC",
24
+ // tokenId: {
25
+ // chain: "Sui",
26
+ // address:
27
+ // "0xa1ec7fc00a6f40db9693ad1415d0c193ad3906494428cf252621037bd7117e29::usdc::USDC",
28
+ // },
29
+ // icon: "USDC",
30
+ // decimals: 6,
31
+ // },
32
+ };
33
+
34
+ export const AptosTestnetUSDCToken: TokenConfig = {
35
+ symbol: "USDC",
36
+ decimals: 6,
37
+ tokenId: {
38
+ chain: "Aptos",
39
+ address:
40
+ "0x69091fbab5f7d635ee7ac5098cf0c1efbe31d68fec0f2cd565e8d168daf52832",
41
+ },
42
+ icon: "USDC",
43
+ };
@@ -0,0 +1,45 @@
1
+ import { ChainId } from "@wormhole-foundation/sdk";
2
+ import { Chain } from "../CrossChainCore";
3
+
4
+ export enum Context {
5
+ ETH = "Ethereum",
6
+ SOLANA = "Solana",
7
+ APTOS = "Aptos",
8
+ }
9
+
10
+ export type BaseChainConfig = {
11
+ key: Chain;
12
+ id: ChainId;
13
+ context: Context;
14
+ finalityThreshold: number;
15
+ disabledAsSource?: boolean;
16
+ disabledAsDestination?: boolean;
17
+ };
18
+
19
+ export interface ChainConfig extends BaseChainConfig {
20
+ defaultRpc: string;
21
+ displayName: string;
22
+ explorerUrl: string;
23
+ explorerName: string;
24
+ gasToken: string;
25
+ wrappedGasToken?: string;
26
+ chainId: number | string;
27
+ icon: Chain;
28
+ maxBlockSearch: number;
29
+ symbol?: string;
30
+ }
31
+
32
+ export type ChainsConfig = {
33
+ [chain in Chain]?: ChainConfig;
34
+ };
35
+
36
+ export type TokenConfig = {
37
+ symbol: string;
38
+ name?: string;
39
+ decimals: number;
40
+ icon: string;
41
+ tokenId: {
42
+ chain: Chain;
43
+ address: string;
44
+ };
45
+ };
package/src/index.ts ADDED
@@ -0,0 +1,5 @@
1
+ export * from "./CrossChainCore";
2
+ export * from "./config";
3
+ export * from "./providers/wormhole/index";
4
+ export * from "./providers/wormhole/types";
5
+ export { Network } from "@aptos-labs/ts-sdk";
@@ -0,0 +1,4 @@
1
+ export * from "./wormhole";
2
+ export * from "./types";
3
+ export * from "./signers/AptosLocalSigner";
4
+ export * from "../../config";
@@ -0,0 +1,136 @@
1
+ import {
2
+ AccountAuthenticator,
3
+ AnyRawTransaction,
4
+ Aptos,
5
+ AptosConfig,
6
+ Network as AptosNetwork,
7
+ Account,
8
+ } from "@aptos-labs/ts-sdk";
9
+
10
+ import {
11
+ Chain,
12
+ Network,
13
+ SignAndSendSigner,
14
+ TxHash,
15
+ UnsignedTransaction,
16
+ } from "@wormhole-foundation/sdk";
17
+ import {
18
+ AptosUnsignedTransaction,
19
+ AptosChains,
20
+ } from "@wormhole-foundation/sdk-aptos";
21
+ import { GasStationApiKey } from "../types";
22
+
23
+ export class AptosLocalSigner<N extends Network, C extends Chain>
24
+ implements SignAndSendSigner<N, C>
25
+ {
26
+ _chain: C;
27
+ _options: any;
28
+ _wallet: Account;
29
+ _sponsorAccount: Account | GasStationApiKey | undefined;
30
+ _claimedTransactionHashes: string;
31
+
32
+ constructor(
33
+ chain: C,
34
+ options: any,
35
+ wallet: Account,
36
+ feePayerAccount: Account | GasStationApiKey | undefined
37
+ ) {
38
+ this._chain = chain;
39
+ this._options = options;
40
+ this._wallet = wallet;
41
+ this._sponsorAccount = feePayerAccount;
42
+ this._claimedTransactionHashes = "";
43
+ }
44
+
45
+ chain(): C {
46
+ return this._chain;
47
+ }
48
+ address(): string {
49
+ return this._wallet.accountAddress.toString();
50
+ }
51
+
52
+ claimedTransactionHashes(): string {
53
+ return this._claimedTransactionHashes;
54
+ }
55
+ /* other methods... */
56
+
57
+ async signAndSend(txs: UnsignedTransaction<N, C>[]): Promise<TxHash[]> {
58
+ const txHashes: TxHash[] = [];
59
+
60
+ for (const tx of txs) {
61
+ const txId = await signAndSendTransaction(
62
+ tx as AptosUnsignedTransaction<Network, AptosChains>,
63
+ this._wallet,
64
+ this._sponsorAccount
65
+ );
66
+ txHashes.push(txId);
67
+ this._claimedTransactionHashes = txId;
68
+ }
69
+ return txHashes;
70
+ }
71
+ }
72
+
73
+ export async function signAndSendTransaction(
74
+ request: UnsignedTransaction<Network, AptosChains>,
75
+ wallet: Account,
76
+ sponsorAccount: Account | GasStationApiKey | undefined
77
+ ) {
78
+ if (!wallet) {
79
+ throw new Error("Wallet is undefined");
80
+ }
81
+
82
+ const payload = request.transaction;
83
+ // The wallets do not handle Uint8Array serialization
84
+ payload.functionArguments = payload.functionArguments.map((a: any) => {
85
+ if (a instanceof Uint8Array) {
86
+ return Array.from(a);
87
+ } else if (typeof a === "bigint") {
88
+ return a.toString();
89
+ } else {
90
+ return a;
91
+ }
92
+ });
93
+
94
+ const aptosConfig = new AptosConfig({
95
+ network: AptosNetwork.TESTNET,
96
+ });
97
+ const aptos = new Aptos(aptosConfig);
98
+
99
+ const txnToSign = await aptos.transaction.build.simple({
100
+ data: payload,
101
+ sender: wallet.accountAddress.toString(),
102
+ withFeePayer: sponsorAccount ? true : false,
103
+ });
104
+ const senderAuthenticator = await aptos.transaction.sign({
105
+ signer: wallet,
106
+ transaction: txnToSign,
107
+ });
108
+
109
+ const txnToSubmit: {
110
+ transaction: AnyRawTransaction;
111
+ senderAuthenticator: AccountAuthenticator;
112
+ feePayerAuthenticator?: AccountAuthenticator;
113
+ } = {
114
+ transaction: txnToSign,
115
+ senderAuthenticator,
116
+ };
117
+
118
+ if (sponsorAccount) {
119
+ if (typeof sponsorAccount === "string") {
120
+ // TODO: handle gas station integration here
121
+ } else {
122
+ const feePayerSignerAuthenticator = aptos.transaction.signAsFeePayer({
123
+ signer: sponsorAccount as Account,
124
+ transaction: txnToSign,
125
+ });
126
+ txnToSubmit.feePayerAuthenticator = feePayerSignerAuthenticator;
127
+ }
128
+ }
129
+ const response = await aptos.transaction.submit.simple(txnToSubmit);
130
+
131
+ const tx = await aptos.waitForTransaction({
132
+ transactionHash: response.hash,
133
+ });
134
+
135
+ return tx.hash;
136
+ }
@@ -0,0 +1,49 @@
1
+ import {
2
+ EvmUnsignedTransaction,
3
+ EvmChains,
4
+ } from "@wormhole-foundation/sdk-evm";
5
+ import { Network } from "@wormhole-foundation/sdk";
6
+ import { ethers, getBigInt } from "ethers";
7
+ import { AdapterWallet } from "@aptos-labs/wallet-adapter-core";
8
+ import { EIP1193DerivedWallet } from "@aptos-labs/derived-wallet-ethereum";
9
+ export async function signAndSendTransaction(
10
+ request: EvmUnsignedTransaction<Network, EvmChains>,
11
+ wallet: AdapterWallet,
12
+ chainName: string,
13
+ options: any
14
+ ): Promise<string> {
15
+ if (!wallet) {
16
+ throw new Error("wallet.sendTransaction is undefined").message;
17
+ }
18
+ // Ensure the signer is connected to the correct chain
19
+ const chainId = await (
20
+ wallet as EIP1193DerivedWallet
21
+ ).eip1193Provider.request({
22
+ method: "eth_chainId",
23
+ });
24
+ const actualChainId = parseInt(chainId, 16);
25
+
26
+ if (!actualChainId)
27
+ throw new Error("No signer found for chain" + chainName).message;
28
+ const expectedChainId = request.transaction.chainId
29
+ ? getBigInt(request.transaction.chainId)
30
+ : undefined;
31
+ if (
32
+ !actualChainId ||
33
+ !expectedChainId ||
34
+ BigInt(actualChainId) !== expectedChainId
35
+ ) {
36
+ throw new Error(
37
+ `Signer is not connected to the right chain. Expected ${expectedChainId}, got ${actualChainId}`
38
+ ).message;
39
+ }
40
+
41
+ const provider = new ethers.BrowserProvider(
42
+ (wallet as EIP1193DerivedWallet).eip1193Provider
43
+ );
44
+ const signer = await provider.getSigner();
45
+ const response = await signer.sendTransaction(request.transaction);
46
+ const receipt = await response.wait();
47
+
48
+ return receipt?.hash || "";
49
+ }
@@ -0,0 +1,102 @@
1
+ import {
2
+ UnsignedTransaction,
3
+ Network,
4
+ Chain,
5
+ TxHash,
6
+ SignAndSendSigner,
7
+ } from "@wormhole-foundation/sdk";
8
+ import { SolanaUnsignedTransaction } from "@wormhole-foundation/sdk-solana";
9
+ import { AdapterWallet } from "@aptos-labs/wallet-adapter-core";
10
+ import {
11
+ EvmUnsignedTransaction,
12
+ EvmChains,
13
+ } from "@wormhole-foundation/sdk-evm";
14
+
15
+ import * as solanaSigner from "./SolanaSigner";
16
+ import * as ethereumSigner from "./EthereumSigner";
17
+ // import {
18
+ // SuiChains,
19
+ // SuiUnsignedTransaction,
20
+ // } from "@wormhole-foundation/sdk-sui";
21
+ // import * as suiSigner from "./SuiSigner";
22
+
23
+ import { ChainConfig } from "../../../config";
24
+ import { CrossChainCore } from "../../../CrossChainCore";
25
+ export class Signer<N extends Network, C extends Chain>
26
+ implements SignAndSendSigner<N, C>
27
+ {
28
+ _chain: ChainConfig;
29
+ _address: string;
30
+ _options: any;
31
+ _wallet: AdapterWallet;
32
+ _crossChainCore?: CrossChainCore;
33
+
34
+ constructor(
35
+ chain: ChainConfig,
36
+ address: string,
37
+ options: any,
38
+ wallet: AdapterWallet,
39
+ crossChainCore?: CrossChainCore
40
+ ) {
41
+ this._chain = chain;
42
+ this._address = address;
43
+ this._options = options;
44
+ this._wallet = wallet;
45
+ this._crossChainCore = crossChainCore;
46
+ }
47
+
48
+ chain(): C {
49
+ return this._chain.displayName as C;
50
+ }
51
+ address(): string {
52
+ return this._address;
53
+ }
54
+
55
+ async signAndSend(txs: UnsignedTransaction<N, C>[]): Promise<TxHash[]> {
56
+ const txHashes: TxHash[] = [];
57
+
58
+ for (const tx of txs) {
59
+ const txId = await signAndSendTransaction(
60
+ this._chain,
61
+ tx,
62
+ this._wallet,
63
+ this._options,
64
+ this._crossChainCore
65
+ );
66
+ txHashes.push(txId);
67
+ }
68
+ return txHashes;
69
+ }
70
+ }
71
+
72
+ export const signAndSendTransaction = async (
73
+ chain: ChainConfig,
74
+ request: UnsignedTransaction<Network, Chain>,
75
+ wallet: AdapterWallet,
76
+ options: any = {},
77
+ crossChainCore?: CrossChainCore
78
+ ): Promise<string> => {
79
+ if (!wallet) {
80
+ throw new Error("wallet is undefined");
81
+ }
82
+
83
+ if (chain.context === "Solana") {
84
+ const signature = await solanaSigner.signAndSendTransaction(
85
+ request as SolanaUnsignedTransaction<Network>,
86
+ wallet,
87
+ options,
88
+ crossChainCore
89
+ );
90
+ return signature;
91
+ } else if (chain.context === "Ethereum") {
92
+ const tx = await ethereumSigner.signAndSendTransaction(
93
+ request as EvmUnsignedTransaction<Network, EvmChains>,
94
+ wallet,
95
+ chain.displayName,
96
+ options
97
+ );
98
+ return tx;
99
+ } else {
100
+ throw new Error(`Unsupported chain: ${chain}`);
101
+ }
102
+ };