@imtbl/wallet 2.12.5-alpha.8 → 2.12.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.
Files changed (37) hide show
  1. package/dist/browser/index.js +202 -29
  2. package/dist/node/index.cjs +241 -56
  3. package/dist/node/index.js +202 -29
  4. package/dist/types/confirmation/confirmation.d.ts +1 -1
  5. package/dist/types/connectWallet.d.ts +2 -3
  6. package/dist/types/constants.d.ts +7 -0
  7. package/dist/types/index.d.ts +4 -2
  8. package/dist/types/network/chainRegistry.d.ts +13 -0
  9. package/dist/types/{presets.d.ts → network/presets.d.ts} +37 -1
  10. package/dist/types/sequence/sequenceProvider.d.ts +21 -0
  11. package/dist/types/sequence/signer/identityInstrumentSigner.d.ts +15 -0
  12. package/dist/types/sequence/signer/index.d.ts +20 -0
  13. package/dist/types/sequence/signer/privateKeySigner.d.ts +15 -0
  14. package/dist/types/sequence/signer/types.d.ts +14 -0
  15. package/dist/types/sequence/user/index.d.ts +2 -0
  16. package/dist/types/sequence/user/registerUser.d.ts +18 -0
  17. package/dist/types/types.d.ts +22 -1
  18. package/dist/types/zkEvm/types.d.ts +3 -10
  19. package/package.json +9 -4
  20. package/src/confirmation/confirmation.ts +14 -4
  21. package/src/connectWallet.test.ts +62 -3
  22. package/src/connectWallet.ts +82 -45
  23. package/src/constants.ts +10 -0
  24. package/src/guardian/index.ts +2 -0
  25. package/src/index.ts +14 -2
  26. package/src/network/chainRegistry.test.ts +64 -0
  27. package/src/network/chainRegistry.ts +74 -0
  28. package/src/{presets.ts → network/presets.ts} +64 -2
  29. package/src/sequence/sequenceProvider.ts +276 -0
  30. package/src/sequence/signer/identityInstrumentSigner.ts +193 -0
  31. package/src/sequence/signer/index.ts +45 -0
  32. package/src/sequence/signer/privateKeySigner.ts +111 -0
  33. package/src/sequence/signer/types.ts +24 -0
  34. package/src/sequence/user/index.ts +2 -0
  35. package/src/sequence/user/registerUser.ts +100 -0
  36. package/src/types.ts +26 -2
  37. package/src/zkEvm/types.ts +4 -10
package/src/constants.ts CHANGED
@@ -8,6 +8,16 @@ export const IMMUTABLE_ZKEVM_MAINNET_CHAIN_ID = 13371;
8
8
  /** Immutable zkEVM Testnet chain ID */
9
9
  export const IMMUTABLE_ZKEVM_TESTNET_CHAIN_ID = 13473;
10
10
 
11
+ /**
12
+ * Chain ID constants for Arbitrum networks
13
+ */
14
+
15
+ /** Arbitrum One Mainnet chain ID */
16
+ export const ARBITRUM_ONE_CHAIN_ID = 42161;
17
+
18
+ /** Arbitrum Sepolia Testnet chain ID */
19
+ export const ARBITRUM_SEPOLIA_CHAIN_ID = 421614;
20
+
11
21
  /**
12
22
  * Magic configuration for Immutable networks
13
23
  * @internal
@@ -232,6 +232,7 @@ export default class GuardianClient {
232
232
  messageId,
233
233
  user.zkEvm.ethAddress,
234
234
  'eip712',
235
+ chainID,
235
236
  );
236
237
 
237
238
  if (!confirmationResult.confirmed) {
@@ -286,6 +287,7 @@ export default class GuardianClient {
286
287
  messageId,
287
288
  user.zkEvm.ethAddress,
288
289
  'erc191',
290
+ String(chainID),
289
291
  );
290
292
 
291
293
  if (!confirmationResult.confirmed) {
package/src/index.ts CHANGED
@@ -5,20 +5,32 @@ export { connectWallet } from './connectWallet';
5
5
  export {
6
6
  IMMUTABLE_ZKEVM_MAINNET_CHAIN_ID,
7
7
  IMMUTABLE_ZKEVM_TESTNET_CHAIN_ID,
8
+ ARBITRUM_ONE_CHAIN_ID,
9
+ ARBITRUM_SEPOLIA_CHAIN_ID,
8
10
  } from './constants';
9
11
 
10
12
  // Export presets (public API)
11
13
  export {
14
+ // zkEVM chains
12
15
  IMMUTABLE_ZKEVM_MAINNET,
13
16
  IMMUTABLE_ZKEVM_TESTNET,
14
17
  IMMUTABLE_ZKEVM_MULTICHAIN,
15
18
  IMMUTABLE_ZKEVM_MAINNET_CHAIN,
16
19
  IMMUTABLE_ZKEVM_TESTNET_CHAIN,
17
20
  DEFAULT_CHAINS,
18
- } from './presets';
21
+ // Arbitrum chains
22
+ ARBITRUM_ONE,
23
+ ARBITRUM_SEPOLIA,
24
+ ARBITRUM_ONE_CHAIN,
25
+ ARBITRUM_SEPOLIA_CHAIN,
26
+ } from './network/presets';
19
27
 
20
- // Export main wallet provider
28
+ // Export chain registry for looking up chain configs
29
+ export { getChainConfig, getEvmChainFromChainId } from './network/chainRegistry';
30
+
31
+ // Export main wallet providers
21
32
  export { ZkEvmProvider } from './zkEvm/zkEvmProvider';
33
+ export { SequenceProvider } from './sequence/sequenceProvider';
22
34
 
23
35
  // Export internal configuration (for Passport/advanced usage)
24
36
  export { WalletConfiguration } from './config';
@@ -0,0 +1,64 @@
1
+ import { Environment } from '@imtbl/config';
2
+ import { getChainConfig, getEvmChainFromChainId } from './chainRegistry';
3
+ import { EvmChain } from '../types';
4
+ import { ARBITRUM_ONE_CHAIN, ARBITRUM_SEPOLIA_CHAIN } from './presets';
5
+
6
+ describe('chainRegistry', () => {
7
+ describe('getChainConfig', () => {
8
+ it('returns Arbitrum One mainnet config for PRODUCTION', () => {
9
+ const config = getChainConfig(EvmChain.ARBITRUM_ONE, Environment.PRODUCTION);
10
+
11
+ expect(config).toEqual(ARBITRUM_ONE_CHAIN);
12
+ expect(config.chainId).toBe(42161);
13
+ expect(config.name).toBe('Arbitrum One');
14
+ });
15
+
16
+ it('returns Arbitrum Sepolia config for SANDBOX', () => {
17
+ const config = getChainConfig(EvmChain.ARBITRUM_ONE, Environment.SANDBOX);
18
+
19
+ expect(config).toEqual(ARBITRUM_SEPOLIA_CHAIN);
20
+ expect(config.chainId).toBe(421614);
21
+ expect(config.name).toBe('Arbitrum Sepolia');
22
+ });
23
+
24
+ it('throws error for unsupported chain', () => {
25
+ expect(() => {
26
+ getChainConfig('unsupported_chain' as any, Environment.PRODUCTION);
27
+ }).toThrow('Chain unsupported_chain is not supported');
28
+ });
29
+ });
30
+
31
+ describe('getEvmChainFromChainId', () => {
32
+ it('returns ZKEVM for mainnet chainId', () => {
33
+ expect(getEvmChainFromChainId(13371)).toBe(EvmChain.ZKEVM);
34
+ });
35
+
36
+ it('returns ZKEVM for testnet chainId', () => {
37
+ expect(getEvmChainFromChainId(13473)).toBe(EvmChain.ZKEVM);
38
+ });
39
+
40
+ it('returns ZKEVM for devnet chainId', () => {
41
+ expect(getEvmChainFromChainId(15003)).toBe(EvmChain.ZKEVM);
42
+ });
43
+
44
+ it('returns ARBITRUM_ONE for Arbitrum mainnet chainId', () => {
45
+ expect(getEvmChainFromChainId(42161)).toBe(EvmChain.ARBITRUM_ONE);
46
+ });
47
+
48
+ it('returns ARBITRUM_ONE for Arbitrum Sepolia chainId', () => {
49
+ expect(getEvmChainFromChainId(421614)).toBe(EvmChain.ARBITRUM_ONE);
50
+ });
51
+
52
+ it('handles string chainId', () => {
53
+ expect(getEvmChainFromChainId('42161')).toBe(EvmChain.ARBITRUM_ONE);
54
+ });
55
+
56
+ it('handles eip155 format chainId', () => {
57
+ expect(getEvmChainFromChainId('eip155:42161')).toBe(EvmChain.ARBITRUM_ONE);
58
+ });
59
+
60
+ it('defaults to ZKEVM for unknown chainId', () => {
61
+ expect(getEvmChainFromChainId(99999)).toBe(EvmChain.ZKEVM);
62
+ });
63
+ });
64
+ });
@@ -0,0 +1,74 @@
1
+ import { Environment } from '@imtbl/config';
2
+ import { ChainConfig, EvmChain } from '../types';
3
+ import {
4
+ IMMUTABLE_ZKEVM_MAINNET_CHAIN,
5
+ IMMUTABLE_ZKEVM_TESTNET_CHAIN,
6
+ ARBITRUM_ONE_CHAIN,
7
+ ARBITRUM_SEPOLIA_CHAIN,
8
+ } from './presets';
9
+ import { ChainId } from './chains';
10
+
11
+ /**
12
+ * Registry mapping (EvmChain, Environment) to ChainConfig
13
+ */
14
+ const CHAIN_REGISTRY: Record<EvmChain, Record<Environment, ChainConfig>> = {
15
+ [EvmChain.ZKEVM]: {
16
+ [Environment.PRODUCTION]: IMMUTABLE_ZKEVM_MAINNET_CHAIN,
17
+ [Environment.SANDBOX]: IMMUTABLE_ZKEVM_TESTNET_CHAIN,
18
+ },
19
+ [EvmChain.ARBITRUM_ONE]: {
20
+ [Environment.PRODUCTION]: ARBITRUM_ONE_CHAIN,
21
+ [Environment.SANDBOX]: ARBITRUM_SEPOLIA_CHAIN,
22
+ },
23
+ };
24
+
25
+ /**
26
+ * Build chainId → EvmChain mapping from CHAIN_REGISTRY (derived, not manual)
27
+ */
28
+ function buildChainIdToEvmChainMap(): Record<number, EvmChain> {
29
+ const map: Record<number, EvmChain> = {};
30
+ for (const [evmChain, envConfigs] of Object.entries(CHAIN_REGISTRY)) {
31
+ for (const config of Object.values(envConfigs)) {
32
+ map[config.chainId] = evmChain as EvmChain;
33
+ }
34
+ }
35
+ // Devnet doesn't have a preset
36
+ map[ChainId.IMTBL_ZKEVM_DEVNET] = EvmChain.ZKEVM;
37
+ return map;
38
+ }
39
+
40
+ const CHAIN_ID_TO_EVM_CHAIN = buildChainIdToEvmChainMap();
41
+
42
+ /**
43
+ * Get chain config for non-zkEVM chains
44
+ * @throws Error if chain is not in registry
45
+ */
46
+ export function getChainConfig(
47
+ chain: Exclude<EvmChain, EvmChain.ZKEVM>,
48
+ environment: Environment,
49
+ ): ChainConfig {
50
+ const envConfigs = CHAIN_REGISTRY[chain];
51
+ if (!envConfigs) {
52
+ throw new Error(`Chain ${chain} is not supported`);
53
+ }
54
+
55
+ const config = envConfigs[environment];
56
+ if (!config) {
57
+ throw new Error(`Chain ${chain} is not configured for environment ${environment}`);
58
+ }
59
+
60
+ return config;
61
+ }
62
+
63
+ /**
64
+ * Get EvmChain from chainId
65
+ * @param chainId - Chain ID (can be number or string like "eip155:42161")
66
+ * @returns EvmChain enum value, defaults to ZKEVM if not found
67
+ */
68
+ export function getEvmChainFromChainId(chainId: string | number): EvmChain {
69
+ const numericChainId = typeof chainId === 'string'
70
+ ? parseInt(chainId.includes(':') ? chainId.split(':')[1] : chainId, 10)
71
+ : chainId;
72
+
73
+ return CHAIN_ID_TO_EVM_CHAIN[numericChainId] ?? EvmChain.ZKEVM;
74
+ }
@@ -1,9 +1,11 @@
1
- import { ChainConfig } from './types';
1
+ import { ChainConfig } from '../types';
2
2
  import {
3
3
  IMMUTABLE_ZKEVM_MAINNET_CHAIN_ID,
4
4
  IMMUTABLE_ZKEVM_TESTNET_CHAIN_ID,
5
+ ARBITRUM_ONE_CHAIN_ID,
6
+ ARBITRUM_SEPOLIA_CHAIN_ID,
5
7
  MAGIC_CONFIG,
6
- } from './constants';
8
+ } from '../constants';
7
9
 
8
10
  /**
9
11
  * Immutable zkEVM Mainnet chain configuration
@@ -35,6 +37,36 @@ export const IMMUTABLE_ZKEVM_TESTNET_CHAIN: ChainConfig = {
35
37
  magicTeeBasePath: 'https://tee.express.magiclabs.com',
36
38
  };
37
39
 
40
+ /**
41
+ * Arbitrum One Mainnet chain configuration
42
+ */
43
+ export const ARBITRUM_ONE_CHAIN: ChainConfig = {
44
+ chainId: ARBITRUM_ONE_CHAIN_ID,
45
+ name: 'Arbitrum One',
46
+ rpcUrl: 'https://arb1.arbitrum.io/rpc',
47
+ relayerUrl: 'https://next-arbitrum-one-relayer.sequence.app',
48
+ nodeUrl: 'https://next-nodes.sequence.app/arbitrum-one',
49
+ apiUrl: 'https://api.immutable.com',
50
+ passportDomain: 'https://passport.immutable.com',
51
+ feeTokenSymbol: 'ETH',
52
+ sequenceIdentityInstrumentEndpoint: 'https://next-identity.sequence.app',
53
+ };
54
+
55
+ /**
56
+ * Arbitrum Sepolia Testnet chain configuration
57
+ */
58
+ export const ARBITRUM_SEPOLIA_CHAIN: ChainConfig = {
59
+ chainId: ARBITRUM_SEPOLIA_CHAIN_ID,
60
+ name: 'Arbitrum Sepolia',
61
+ rpcUrl: 'https://sepolia-rollup.arbitrum.io/rpc',
62
+ relayerUrl: 'https://next-arbitrum-sepolia-relayer.sequence.app',
63
+ nodeUrl: 'https://next-nodes.sequence.app/arbitrum-sepolia',
64
+ apiUrl: 'https://api.sandbox.immutable.com',
65
+ passportDomain: 'https://passport.sandbox.immutable.com',
66
+ feeTokenSymbol: 'ETH',
67
+ sequenceIdentityInstrumentEndpoint: 'https://next-identity.sequence-dev.app',
68
+ };
69
+
38
70
  /**
39
71
  * Default chains (testnet + mainnet)
40
72
  * Testnet is first (default initial chain)
@@ -90,3 +122,33 @@ export const IMMUTABLE_ZKEVM_TESTNET = {
90
122
  export const IMMUTABLE_ZKEVM_MULTICHAIN = {
91
123
  chains: DEFAULT_CHAINS,
92
124
  };
125
+
126
+ /**
127
+ * Arbitrum mainnet only preset
128
+ *
129
+ * @example
130
+ * ```typescript
131
+ * const provider = await connectWallet({
132
+ * ...ARBITRUM_ONE_MAINNET,
133
+ * auth,
134
+ * });
135
+ * ```
136
+ */
137
+ export const ARBITRUM_ONE = {
138
+ chains: [ARBITRUM_ONE_CHAIN],
139
+ };
140
+
141
+ /**
142
+ * Arbitrum testnet only preset
143
+ *
144
+ * @example
145
+ * ```typescript
146
+ * const provider = await connectWallet({
147
+ * ...ARBITRUM_SEPOLIA,
148
+ * auth,
149
+ * });
150
+ * ```
151
+ */
152
+ export const ARBITRUM_SEPOLIA = {
153
+ chains: [ARBITRUM_SEPOLIA_CHAIN],
154
+ };
@@ -0,0 +1,276 @@
1
+ import {
2
+ createPublicClient,
3
+ http,
4
+ toHex,
5
+ type PublicClient,
6
+ } from 'viem';
7
+ import { MultiRollupApiClients } from '@imtbl/generated-clients';
8
+ import { Auth, TypedEventEmitter, User } from '@imtbl/auth';
9
+ import { trackFlow, trackError, identify } from '@imtbl/metrics';
10
+ import {
11
+ Provider,
12
+ ProviderEvent,
13
+ ProviderEventMap,
14
+ RequestArguments,
15
+ ChainConfig,
16
+ EvmChain,
17
+ } from '../types';
18
+ import { JsonRpcError, ProviderErrorCode, RpcErrorCode } from '../zkEvm/JsonRpcError';
19
+ import GuardianClient from '../guardian';
20
+ import { SequenceSigner } from './signer';
21
+ import { registerUser } from './user';
22
+ import { getEvmChainFromChainId } from '../network/chainRegistry';
23
+
24
+ export type SequenceProviderInput = {
25
+ auth: Auth;
26
+ chainConfig: ChainConfig;
27
+ multiRollupApiClients: MultiRollupApiClients;
28
+ guardianClient: GuardianClient;
29
+ ethSigner: SequenceSigner;
30
+ passportEventEmitter: TypedEventEmitter<ProviderEventMap>;
31
+ };
32
+
33
+ /** Non-zkEVM chain type */
34
+ type SequenceChain = Exclude<EvmChain, EvmChain.ZKEVM>;
35
+
36
+ /**
37
+ * Check if user is registered for a non-zkEVM chain.
38
+ * The chain data is stored as user[chainName] (e.g., user.arbitrum_one).
39
+ */
40
+ function isUserRegisteredForChain(user: User, chain: SequenceChain): boolean {
41
+ return chain in user && !!(user as any)[chain]?.ethAddress;
42
+ }
43
+
44
+ /**
45
+ * Get the user's eth address for a non-zkEVM chain.
46
+ */
47
+ function getUserChainAddress(user: User, chain: SequenceChain): string | undefined {
48
+ const chainData = (user as any)[chain];
49
+ return chainData?.ethAddress;
50
+ }
51
+
52
+ export class SequenceProvider implements Provider {
53
+ readonly #auth: Auth;
54
+
55
+ readonly #chainConfig: ChainConfig;
56
+
57
+ readonly #multiRollupApiClients: MultiRollupApiClients;
58
+
59
+ readonly #rpcProvider: PublicClient;
60
+
61
+ readonly #providerEventEmitter: TypedEventEmitter<ProviderEventMap>;
62
+
63
+ readonly #guardianClient: GuardianClient;
64
+
65
+ readonly #ethSigner: SequenceSigner;
66
+
67
+ readonly #evmChain: SequenceChain;
68
+
69
+ public readonly isPassport: boolean = true;
70
+
71
+ constructor({
72
+ auth,
73
+ chainConfig,
74
+ multiRollupApiClients,
75
+ guardianClient,
76
+ ethSigner,
77
+ passportEventEmitter,
78
+ }: SequenceProviderInput) {
79
+ // Validate this is not a zkEVM chain
80
+ const evmChain = getEvmChainFromChainId(chainConfig.chainId);
81
+ if (evmChain === EvmChain.ZKEVM) {
82
+ throw new Error('SequenceProvider cannot be used for zkEVM chains. Use ZkEvmProvider instead.');
83
+ }
84
+ this.#evmChain = evmChain;
85
+
86
+ this.#auth = auth;
87
+ this.#chainConfig = chainConfig;
88
+ this.#multiRollupApiClients = multiRollupApiClients;
89
+ this.#guardianClient = guardianClient;
90
+ this.#ethSigner = ethSigner;
91
+ this.#providerEventEmitter = passportEventEmitter;
92
+
93
+ // Create PublicClient for reading from the chain using viem
94
+ this.#rpcProvider = createPublicClient({
95
+ transport: http(this.#chainConfig.rpcUrl),
96
+ });
97
+ }
98
+
99
+ /**
100
+ * Get the user's address for this chain if already registered.
101
+ */
102
+ async #getChainAddress(): Promise<string | undefined> {
103
+ const user = await this.#auth.getUser();
104
+ if (user && isUserRegisteredForChain(user, this.#evmChain)) {
105
+ return getUserChainAddress(user, this.#evmChain);
106
+ }
107
+ return undefined;
108
+ }
109
+
110
+ async #performRequest(request: RequestArguments): Promise<any> {
111
+ switch (request.method) {
112
+ case 'eth_requestAccounts': {
113
+ // Check if already registered
114
+ const existingAddress = await this.#getChainAddress();
115
+ if (existingAddress) return [existingAddress];
116
+
117
+ const flow = trackFlow('passport', 'ethRequestAccounts');
118
+
119
+ try {
120
+ const user = await this.#auth.getUserOrLogin();
121
+ flow.addEvent('endGetUserOrLogin');
122
+
123
+ let userEthAddress: string | undefined;
124
+
125
+ if (!isUserRegisteredForChain(user, this.#evmChain)) {
126
+ flow.addEvent('startUserRegistration');
127
+
128
+ userEthAddress = await registerUser({
129
+ auth: this.#auth,
130
+ ethSigner: this.#ethSigner,
131
+ multiRollupApiClients: this.#multiRollupApiClients,
132
+ accessToken: user.accessToken,
133
+ rpcProvider: this.#rpcProvider,
134
+ flow,
135
+ });
136
+ flow.addEvent('endUserRegistration');
137
+ } else {
138
+ userEthAddress = getUserChainAddress(user, this.#evmChain);
139
+ }
140
+
141
+ if (!userEthAddress) {
142
+ throw new JsonRpcError(
143
+ RpcErrorCode.INTERNAL_ERROR,
144
+ 'Failed to get user address after registration',
145
+ );
146
+ }
147
+
148
+ this.#providerEventEmitter.emit(ProviderEvent.ACCOUNTS_CHANGED, [
149
+ userEthAddress,
150
+ ]);
151
+ identify({
152
+ passportId: user.profile.sub,
153
+ });
154
+ return [userEthAddress];
155
+ } catch (error) {
156
+ if (error instanceof Error) {
157
+ trackError('passport', 'ethRequestAccounts', error, { flowId: flow.details.flowId });
158
+ } else {
159
+ flow.addEvent('errored');
160
+ }
161
+ throw error;
162
+ } finally {
163
+ flow.addEvent('End');
164
+ }
165
+ }
166
+
167
+ case 'eth_accounts': {
168
+ const address = await this.#getChainAddress();
169
+ return address ? [address] : [];
170
+ }
171
+
172
+ // TODO: Implement eth_sendTransaction
173
+ case 'eth_sendTransaction': {
174
+ throw new JsonRpcError(
175
+ ProviderErrorCode.UNSUPPORTED_METHOD,
176
+ 'eth_sendTransaction not yet implemented for this chain',
177
+ );
178
+ }
179
+
180
+ // TODO: Implement personal_sign
181
+ case 'personal_sign': {
182
+ throw new JsonRpcError(
183
+ ProviderErrorCode.UNSUPPORTED_METHOD,
184
+ 'personal_sign not yet implemented for this chain',
185
+ );
186
+ }
187
+
188
+ // TODO: Implement eth_signTypedData
189
+ case 'eth_signTypedData':
190
+ case 'eth_signTypedData_v4': {
191
+ throw new JsonRpcError(
192
+ ProviderErrorCode.UNSUPPORTED_METHOD,
193
+ 'eth_signTypedData not yet implemented for this chain',
194
+ );
195
+ }
196
+
197
+ case 'eth_chainId': {
198
+ const chainId = await this.#rpcProvider.getChainId();
199
+ return toHex(chainId);
200
+ }
201
+
202
+ // Pass through methods
203
+ case 'eth_getBalance':
204
+ case 'eth_getCode':
205
+ case 'eth_getTransactionCount': {
206
+ const [address, blockNumber] = request.params || [];
207
+ return this.#rpcProvider.request({
208
+ method: request.method as any,
209
+ params: [address, blockNumber || 'latest'],
210
+ });
211
+ }
212
+
213
+ case 'eth_getStorageAt': {
214
+ const [address, storageSlot, blockNumber] = request.params || [];
215
+ return this.#rpcProvider.request({
216
+ method: 'eth_getStorageAt',
217
+ params: [address, storageSlot, blockNumber || 'latest'],
218
+ });
219
+ }
220
+
221
+ case 'eth_call':
222
+ case 'eth_estimateGas': {
223
+ const [transaction, blockNumber] = request.params || [];
224
+ return this.#rpcProvider.request({
225
+ method: request.method as any,
226
+ params: [transaction, blockNumber || 'latest'],
227
+ });
228
+ }
229
+
230
+ case 'eth_gasPrice':
231
+ case 'eth_blockNumber':
232
+ case 'eth_getBlockByHash':
233
+ case 'eth_getBlockByNumber':
234
+ case 'eth_getTransactionByHash':
235
+ case 'eth_getTransactionReceipt': {
236
+ return this.#rpcProvider.request({
237
+ method: request.method as any,
238
+ params: (request.params || []) as any,
239
+ });
240
+ }
241
+
242
+ default: {
243
+ throw new JsonRpcError(
244
+ ProviderErrorCode.UNSUPPORTED_METHOD,
245
+ 'Method not supported',
246
+ );
247
+ }
248
+ }
249
+ }
250
+
251
+ public async request(request: RequestArguments): Promise<any> {
252
+ try {
253
+ return this.#performRequest(request);
254
+ } catch (error: unknown) {
255
+ if (error instanceof JsonRpcError) {
256
+ throw error;
257
+ }
258
+ if (error instanceof Error) {
259
+ throw new JsonRpcError(RpcErrorCode.INTERNAL_ERROR, error.message);
260
+ }
261
+
262
+ throw new JsonRpcError(RpcErrorCode.INTERNAL_ERROR, 'Internal error');
263
+ }
264
+ }
265
+
266
+ public on(event: string, listener: (...args: any[]) => void): void {
267
+ this.#providerEventEmitter.on(event, listener);
268
+ }
269
+
270
+ public removeListener(
271
+ event: string,
272
+ listener: (...args: any[]) => void,
273
+ ): void {
274
+ this.#providerEventEmitter.removeListener(event, listener);
275
+ }
276
+ }