@walletmesh/aztec-rpc-wallet 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +201 -0
  3. package/README.md +260 -0
  4. package/dist/.tsbuildinfo +1 -0
  5. package/dist/aztecRemoteWallet.d.ts +73 -0
  6. package/dist/aztecRemoteWallet.d.ts.map +1 -0
  7. package/dist/aztecRemoteWallet.js +354 -0
  8. package/dist/chainProvider.d.ts +56 -0
  9. package/dist/chainProvider.d.ts.map +1 -0
  10. package/dist/chainProvider.js +98 -0
  11. package/dist/contractArtifactCache.d.ts +50 -0
  12. package/dist/contractArtifactCache.d.ts.map +1 -0
  13. package/dist/contractArtifactCache.js +66 -0
  14. package/dist/errors.d.ts +50 -0
  15. package/dist/errors.d.ts.map +1 -0
  16. package/dist/errors.js +62 -0
  17. package/dist/handlers/aztecAccountWallet.d.ts +4 -0
  18. package/dist/handlers/aztecAccountWallet.d.ts.map +1 -0
  19. package/dist/handlers/aztecAccountWallet.js +329 -0
  20. package/dist/handlers/transactions.d.ts +21 -0
  21. package/dist/handlers/transactions.d.ts.map +1 -0
  22. package/dist/handlers/transactions.js +90 -0
  23. package/dist/handlers.d.ts +27 -0
  24. package/dist/handlers.d.ts.map +1 -0
  25. package/dist/handlers.js +55 -0
  26. package/dist/index.d.ts +58 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +33 -0
  29. package/dist/provider.d.ts +105 -0
  30. package/dist/provider.d.ts.map +1 -0
  31. package/dist/provider.js +160 -0
  32. package/dist/serializers/account.d.ts +167 -0
  33. package/dist/serializers/account.d.ts.map +1 -0
  34. package/dist/serializers/account.js +245 -0
  35. package/dist/serializers/contract-utils.d.ts +40 -0
  36. package/dist/serializers/contract-utils.d.ts.map +1 -0
  37. package/dist/serializers/contract-utils.js +102 -0
  38. package/dist/serializers/contract.d.ts +168 -0
  39. package/dist/serializers/contract.d.ts.map +1 -0
  40. package/dist/serializers/contract.js +268 -0
  41. package/dist/serializers/core.d.ts +110 -0
  42. package/dist/serializers/core.d.ts.map +1 -0
  43. package/dist/serializers/core.js +130 -0
  44. package/dist/serializers/index.d.ts +28 -0
  45. package/dist/serializers/index.d.ts.map +1 -0
  46. package/dist/serializers/index.js +159 -0
  47. package/dist/serializers/log.d.ts +113 -0
  48. package/dist/serializers/log.d.ts.map +1 -0
  49. package/dist/serializers/log.js +231 -0
  50. package/dist/serializers/note.d.ts +127 -0
  51. package/dist/serializers/note.d.ts.map +1 -0
  52. package/dist/serializers/note.js +182 -0
  53. package/dist/serializers/transaction-utils.d.ts +107 -0
  54. package/dist/serializers/transaction-utils.d.ts.map +1 -0
  55. package/dist/serializers/transaction-utils.js +130 -0
  56. package/dist/serializers/transaction.d.ts +103 -0
  57. package/dist/serializers/transaction.d.ts.map +1 -0
  58. package/dist/serializers/transaction.js +238 -0
  59. package/dist/serializers/types.d.ts +49 -0
  60. package/dist/serializers/types.d.ts.map +1 -0
  61. package/dist/serializers/types.js +22 -0
  62. package/dist/types.d.ts +391 -0
  63. package/dist/types.d.ts.map +1 -0
  64. package/dist/types.js +8 -0
  65. package/dist/wallet.d.ts +62 -0
  66. package/dist/wallet.d.ts.map +1 -0
  67. package/dist/wallet.js +77 -0
  68. package/package.json +44 -0
  69. package/src/aztecRemoteWallet.test.ts +542 -0
  70. package/src/aztecRemoteWallet.ts +484 -0
  71. package/src/chainProvider.test.ts +322 -0
  72. package/src/chainProvider.ts +122 -0
  73. package/src/contractArtifactCache.test.ts +126 -0
  74. package/src/contractArtifactCache.ts +75 -0
  75. package/src/errors.ts +71 -0
  76. package/src/handlers/aztecAccountWallet.test.ts +720 -0
  77. package/src/handlers/aztecAccountWallet.ts +593 -0
  78. package/src/handlers/transactions.ts +110 -0
  79. package/src/handlers.test.ts +270 -0
  80. package/src/handlers.ts +70 -0
  81. package/src/index.test.ts +23 -0
  82. package/src/index.ts +64 -0
  83. package/src/provider.test.ts +276 -0
  84. package/src/provider.ts +189 -0
  85. package/src/serializers/account.test.ts +125 -0
  86. package/src/serializers/account.ts +319 -0
  87. package/src/serializers/contract-utils.ts +104 -0
  88. package/src/serializers/contract.test.ts +162 -0
  89. package/src/serializers/contract.ts +350 -0
  90. package/src/serializers/core.test.ts +56 -0
  91. package/src/serializers/core.ts +141 -0
  92. package/src/serializers/index.test.ts +122 -0
  93. package/src/serializers/index.ts +213 -0
  94. package/src/serializers/log.test.ts +119 -0
  95. package/src/serializers/log.ts +283 -0
  96. package/src/serializers/note.test.ts +100 -0
  97. package/src/serializers/note.ts +227 -0
  98. package/src/serializers/transaction-utils.ts +237 -0
  99. package/src/serializers/transaction.test.ts +153 -0
  100. package/src/serializers/transaction.ts +342 -0
  101. package/src/serializers/types.ts +58 -0
  102. package/src/types.ts +295 -0
  103. package/src/wallet.test.ts +275 -0
  104. package/src/wallet.ts +94 -0
  105. package/tsconfig.build.json +6 -0
  106. package/tsconfig.json +11 -0
  107. package/typedoc.json +15 -0
  108. package/vitest.config.ts +10 -0
@@ -0,0 +1,270 @@
1
+ import { describe, expect, it, vi, beforeEach } from 'vitest';
2
+ import type { AccountWallet, PXE, TxHash, AztecAddress } from '@aztec/aztec.js';
3
+ import { Fr } from '@aztec/aztec.js';
4
+ import { handler } from './handlers.js';
5
+ import { AztecWalletError } from './errors.js';
6
+ import { ContractArtifactCache } from './contractArtifactCache.js';
7
+ import type {
8
+ AztecWalletContext,
9
+ AztecWalletMethodMap,
10
+ TransactionParams,
11
+ TransactionFunctionCall,
12
+ } from './types.js';
13
+
14
+ // Mock Contract.at and NoFeePaymentMethod at the top level
15
+ // Mock Aztec.js dependencies
16
+ vi.mock('@aztec/aztec.js', async () => {
17
+ const actual = await vi.importActual('@aztec/aztec.js');
18
+ return {
19
+ ...actual,
20
+ Contract: {
21
+ at: vi.fn(),
22
+ },
23
+ NoFeePaymentMethod: class {},
24
+ AztecAddress: {
25
+ fromString: vi.fn().mockImplementation((str) => ({
26
+ toString: () => str,
27
+ toField: () => new Fr(1),
28
+ equals: () => false,
29
+ isZero: () => false,
30
+ })),
31
+ },
32
+ AuthWitness: {
33
+ fromString: vi.fn().mockImplementation((str) => ({
34
+ toString: () => str,
35
+ })),
36
+ },
37
+ GasSettings: {
38
+ default: vi.fn().mockReturnValue({
39
+ maxFeePerGas: BigInt(1000),
40
+ maxPriorityFeePerGas: BigInt(100),
41
+ }),
42
+ },
43
+ };
44
+ });
45
+
46
+ // Mock circuits.js dependencies
47
+ vi.mock('@aztec/circuits.js', () => ({
48
+ GasSettings: {
49
+ default: vi.fn().mockReturnValue({
50
+ maxFeePerGas: BigInt(1000),
51
+ maxPriorityFeePerGas: BigInt(100),
52
+ }),
53
+ },
54
+ }));
55
+
56
+ describe('RPC Handlers', () => {
57
+ let context: AztecWalletContext;
58
+ let pxe: PXE;
59
+ // Define a type for our mocked wallet that includes the methods we need
60
+ type MockedWallet = AccountWallet & {
61
+ sendTransaction: ReturnType<typeof vi.fn>;
62
+ simulateTransaction: ReturnType<typeof vi.fn>;
63
+ getContractInstance: ReturnType<typeof vi.fn>;
64
+ getContractArtifact: ReturnType<typeof vi.fn>;
65
+ getCurrentBaseFees: ReturnType<typeof vi.fn>;
66
+ createTxExecutionRequest: ReturnType<typeof vi.fn>;
67
+ simulateTx: ReturnType<typeof vi.fn>;
68
+ proveTx: ReturnType<typeof vi.fn>;
69
+ sendTx: ReturnType<typeof vi.fn>;
70
+ };
71
+ let wallet: MockedWallet;
72
+ let contractArtifactCache: ContractArtifactCache;
73
+
74
+ beforeEach(() => {
75
+ // Mock wallet with common methods
76
+ wallet = {
77
+ getAddress: vi.fn().mockResolvedValue('mockAddress'),
78
+ getContractInstance: vi.fn().mockResolvedValue(undefined),
79
+ getContractArtifact: vi.fn().mockResolvedValue(undefined),
80
+ sendTransaction: vi.fn(),
81
+ simulateTransaction: vi.fn(),
82
+ getCurrentBaseFees: vi.fn().mockResolvedValue(BigInt(1000)),
83
+ createTxExecutionRequest: vi.fn().mockResolvedValue({
84
+ id: 'mockTxId',
85
+ data: new Uint8Array(),
86
+ }),
87
+ simulateTx: vi.fn().mockResolvedValue({
88
+ privateExecutionResult: {
89
+ success: true,
90
+ data: new Uint8Array(),
91
+ },
92
+ }),
93
+ proveTx: vi.fn().mockResolvedValue({
94
+ toTx: () => ({ id: 'mockTxId' }),
95
+ }),
96
+ sendTx: vi.fn().mockResolvedValue({
97
+ toString: () => 'txHash',
98
+ } as unknown as TxHash),
99
+ } as unknown as MockedWallet;
100
+
101
+ // Mock PXE
102
+ pxe = {
103
+ // Add PXE methods as needed
104
+ } as unknown as PXE;
105
+
106
+ // Create contract artifact cache
107
+ contractArtifactCache = new ContractArtifactCache(wallet);
108
+
109
+ // Setup context
110
+ context = {
111
+ pxe,
112
+ wallet,
113
+ contractArtifactCache,
114
+ };
115
+ });
116
+
117
+ describe('Base wallet methods', () => {
118
+ it('handles wm_getSupportedMethods', async () => {
119
+ const result = await handler(context, 'wm_getSupportedMethods', []);
120
+ expect(Array.isArray(result)).toBe(true);
121
+ expect(result.length).toBeGreaterThan(0);
122
+ expect(result).toContain('aztec_connect');
123
+ expect(result).toContain('aztec_getAccount');
124
+ });
125
+
126
+ it('handles aztec_connect', async () => {
127
+ const result = await handler(context, 'aztec_connect', []);
128
+ expect(result).toBe(true);
129
+ });
130
+
131
+ it('handles aztec_getAccount', async () => {
132
+ const result = await handler(context, 'aztec_getAccount', []);
133
+ expect(result).toBe('mockAddress');
134
+ expect(wallet.getAddress).toHaveBeenCalled();
135
+ });
136
+ });
137
+
138
+ describe('Transaction methods', () => {
139
+ // Create a valid AztecAddress for testing
140
+ // Create a valid hex string for AztecAddress (32 bytes = 64 hex chars)
141
+ const mockAddressHex = `0x${'1'.repeat(64)}`;
142
+ const mockAddress = {
143
+ toString: () => mockAddressHex,
144
+ toField: () => new Fr(1),
145
+ equals: () => false,
146
+ isZero: () => false,
147
+ _hex: mockAddressHex,
148
+ } as unknown as AztecAddress;
149
+
150
+ const mockFunctionCall: TransactionFunctionCall = {
151
+ contractAddress: mockAddress.toString(),
152
+ functionName: 'test',
153
+ args: ['arg1', 'arg2'],
154
+ };
155
+
156
+ const mockTxParams: TransactionParams = {
157
+ functionCalls: [mockFunctionCall],
158
+ authwits: [],
159
+ };
160
+
161
+ beforeEach(async () => {
162
+ // Mock contract instance with proper request data
163
+ const mockContract = {
164
+ methods: {
165
+ test: vi.fn().mockReturnValue({
166
+ simulate: vi.fn().mockResolvedValue({
167
+ success: true,
168
+ returnValue: '0x123',
169
+ }),
170
+ request: vi.fn().mockResolvedValue({
171
+ contractAddress: mockAddress,
172
+ functionData: new Uint8Array([1, 2, 3]), // Non-empty function data
173
+ functionSignature: 'test(uint256,uint256)',
174
+ args: ['arg1', 'arg2'],
175
+ }),
176
+ }),
177
+ },
178
+ address: mockAddress,
179
+ };
180
+
181
+ // Configure Contract.at mock
182
+ const { Contract } = await import('@aztec/aztec.js');
183
+ (Contract.at as ReturnType<typeof vi.fn>).mockResolvedValue(mockContract);
184
+
185
+ // Configure mock return values for contract artifact cache
186
+ const mockArtifact = {
187
+ functions: {
188
+ test: {
189
+ name: 'test',
190
+ parameters: [
191
+ { name: 'arg1', type: 'uint256' },
192
+ { name: 'arg2', type: 'uint256' },
193
+ ],
194
+ },
195
+ },
196
+ };
197
+
198
+ // Mock contract artifact cache methods
199
+ contractArtifactCache.getContractArtifact = vi.fn().mockResolvedValue(mockArtifact);
200
+ });
201
+
202
+ it('handles aztec_sendTransaction', async () => {
203
+ const result = await handler(context, 'aztec_sendTransaction', mockTxParams);
204
+ expect(result).toBe('txHash');
205
+ expect(contractArtifactCache.getContractArtifact).toHaveBeenCalled();
206
+ expect(wallet.createTxExecutionRequest).toHaveBeenCalled();
207
+ expect(wallet.simulateTx).toHaveBeenCalled();
208
+ expect(wallet.proveTx).toHaveBeenCalled();
209
+ expect(wallet.sendTx).toHaveBeenCalled();
210
+ });
211
+
212
+ it('handles aztec_simulateTransaction', async () => {
213
+ const result = await handler(context, 'aztec_simulateTransaction', mockFunctionCall);
214
+ expect(result).toEqual({
215
+ success: true,
216
+ returnValue: '0x123',
217
+ });
218
+ expect(contractArtifactCache.getContractArtifact).toHaveBeenCalled();
219
+ });
220
+
221
+ it('handles transaction errors', async () => {
222
+ wallet.createTxExecutionRequest.mockRejectedValue(new Error('Transaction failed'));
223
+ await expect(handler(context, 'aztec_sendTransaction', mockTxParams)).rejects.toThrow(AztecWalletError);
224
+ });
225
+ });
226
+
227
+ describe('Error handling', () => {
228
+ it('throws error for unsupported method', async () => {
229
+ await expect(handler(context, 'unsupported_method' as keyof AztecWalletMethodMap, [])).rejects.toThrow(
230
+ AztecWalletError,
231
+ );
232
+ });
233
+
234
+ it('throws error for invalid parameters', async () => {
235
+ await expect(
236
+ handler(context, 'aztec_sendTransaction', [] as unknown as TransactionParams),
237
+ ).rejects.toThrow(AztecWalletError);
238
+ });
239
+
240
+ it('handles null context values', async () => {
241
+ // Mock the handler to wrap errors
242
+ const mockHandler = async () => {
243
+ try {
244
+ await handler(
245
+ { pxe, wallet: null, contractArtifactCache } as unknown as AztecWalletContext,
246
+ 'aztec_getAccount',
247
+ [],
248
+ );
249
+ } catch (error) {
250
+ if (error instanceof Error) {
251
+ throw new AztecWalletError('unknownInternalError', error.message);
252
+ }
253
+ throw error;
254
+ }
255
+ };
256
+
257
+ await expect(mockHandler()).rejects.toThrow(AztecWalletError);
258
+ });
259
+ });
260
+
261
+ describe('Account wallet methods', () => {
262
+ // Add tests for account wallet specific methods
263
+ // These would test the routing to accountWalletHandler
264
+ it('routes account wallet methods correctly', async () => {
265
+ // Mock an account wallet method
266
+ const accountMethod = 'aztec_getBlock';
267
+ await expect(handler(context, accountMethod, { number: 1 })).rejects.toThrow(); // Should attempt to route to accountWalletHandler
268
+ });
269
+ });
270
+ });
@@ -0,0 +1,70 @@
1
+ /**
2
+ * @module handlers
3
+ *
4
+ * This module provides the core RPC method handling logic for the Aztec wallet.
5
+ * It routes incoming RPC requests to appropriate specialized handlers based on the method type.
6
+ *
7
+ * The handlers are organized into categories:
8
+ * - Base wallet methods (connect, getAccount, etc.)
9
+ * - Account wallet methods (chain operations, contract management, etc.)
10
+ * - Transaction methods (send, simulate)
11
+ *
12
+ * Each method handler validates inputs, performs the requested operation through the wallet,
13
+ * and returns properly formatted responses.
14
+ */
15
+
16
+ import type { AztecWalletMethodMap } from './types.js';
17
+ import { type AztecWalletContext, BASE_WALLET_METHODS } from './types.js';
18
+ import { AztecWalletError } from './errors.js';
19
+ import { sendTransaction, simulateTransaction } from './handlers/transactions.js';
20
+ import { aztecWalletHandler, AZTEC_WALLET_METHODS } from './handlers/aztecAccountWallet.js';
21
+
22
+ /**
23
+ * Main handler function that routes RPC method calls to appropriate specialized handlers.
24
+ *
25
+ * @param context - The wallet context containing PXE and wallet instances
26
+ * @param method - The RPC method being called
27
+ * @param params - Parameters passed to the method
28
+ * @returns Result from the method handler
29
+ * @throws {AztecWalletError} If method not supported or handler fails
30
+ */
31
+
32
+ export async function handler<M extends keyof AztecWalletMethodMap>(
33
+ context: AztecWalletContext,
34
+ method: M,
35
+ params: AztecWalletMethodMap[M]['params'],
36
+ ): Promise<AztecWalletMethodMap[M]['result']> {
37
+ if (AZTEC_WALLET_METHODS.includes(method)) {
38
+ return aztecWalletHandler(context, method, params);
39
+ }
40
+ switch (method) {
41
+ // Base wallet methods
42
+ case 'wm_getSupportedMethods': {
43
+ // Return combined list of supported methods from all handlers
44
+ return [...BASE_WALLET_METHODS, ...AZTEC_WALLET_METHODS] as string[];
45
+ }
46
+ case 'aztec_connect': {
47
+ // Basic connection validation
48
+ // Note: Main connection logic handled by provider
49
+ return true;
50
+ }
51
+ // Core wallet methods
52
+ case 'aztec_getAccount':
53
+ return (await context.wallet.getAddress()).toString();
54
+
55
+ // Transaction methods
56
+ case 'aztec_sendTransaction':
57
+ return await sendTransaction(
58
+ context,
59
+ params as AztecWalletMethodMap['aztec_sendTransaction']['params'],
60
+ );
61
+ case 'aztec_simulateTransaction':
62
+ return await simulateTransaction(
63
+ context,
64
+ params as AztecWalletMethodMap['aztec_simulateTransaction']['params'],
65
+ );
66
+
67
+ default:
68
+ throw new AztecWalletError('invalidRequest', `Method not supported: ${String(method)}`);
69
+ }
70
+ }
@@ -0,0 +1,23 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import * as exports from './index.js';
3
+
4
+ describe('index exports', () => {
5
+ it('should export AztecProvider', () => {
6
+ expect(exports.AztecProvider).toBeDefined();
7
+ });
8
+
9
+ it('should export AztecChainWallet', () => {
10
+ expect(exports.AztecChainWallet).toBeDefined();
11
+ });
12
+
13
+ it('should export error utilities', () => {
14
+ expect(exports.AztecWalletError).toBeDefined();
15
+ expect(exports.AztecWalletErrorMap).toBeDefined();
16
+ });
17
+
18
+ // Type exports can't be tested at runtime, but we can verify the file compiles
19
+ it('should compile with type exports', () => {
20
+ // This test passes by virtue of the file compiling
21
+ expect(true).toBe(true);
22
+ });
23
+ });
package/src/index.ts ADDED
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @module @walletmesh/aztec-rpc-wallet
3
+ *
4
+ * This module provides a JSON-RPC implementation for interacting with Aztec Network.
5
+ * It enables communication between dApps and wallets through a standardized interface.
6
+ */
7
+
8
+ /**
9
+ * Provider class for dApps to interact with Aztec wallets
10
+ * @see AztecProvider
11
+ */
12
+ export { AztecProvider } from './provider.js';
13
+
14
+ /**
15
+ * Minimal provider for direct interaction with an Aztec chain wallet
16
+ * @see AztecChainProvider
17
+ */
18
+ export { AztecChainProvider } from './chainProvider.js';
19
+
20
+ /**
21
+ * Wallet implementation that handles RPC requests from dApps
22
+ * @see AztecChainWallet
23
+ */
24
+ export { AztecChainWallet } from './wallet.js';
25
+ export { AztecChainWalletMiddleware } from './types.js';
26
+
27
+ /**
28
+ * Cache for contract artifacts
29
+ * @see ContractArtifactCache
30
+ */
31
+ export { ContractArtifactCache } from './contractArtifactCache.js';
32
+
33
+ /**
34
+ * Error handling utilities for RPC communication
35
+ * @see AztecWalletError
36
+ * @see AztecWalletErrorMap
37
+ */
38
+ export { AztecWalletError, AztecWalletErrorMap } from './errors.js';
39
+
40
+ /**
41
+ * Type definitions for RPC interfaces
42
+ */
43
+ export type {
44
+ /** Chain identifier type */
45
+ AztecChainId,
46
+ /** Context passed through RPC middleware */
47
+ AztecWalletContext,
48
+ /** Event map for wallet events */
49
+ AztecWalletEventMap,
50
+ /** Base method map for core wallet functionality */
51
+ AztecWalletBaseMethodMap,
52
+ /** Complete method map including all Aztec methods */
53
+ AztecWalletMethodMap,
54
+ /** Middleware type for processing RPC requests */
55
+ AztecWalletMiddleware,
56
+ /** Router client type for wallet mesh integration */
57
+ AztecWalletRouterClient,
58
+ /** Handler type for wallet methods */
59
+ AztecWalletMethodHandler,
60
+ /** Type for contract function calls */
61
+ TransactionFunctionCall,
62
+ /** Parameters for transaction requests */
63
+ TransactionParams,
64
+ } from './types.js';
@@ -0,0 +1,276 @@
1
+ import { describe, test, expect, vi, beforeEach } from 'vitest';
2
+ import { AztecProvider } from './provider.js';
3
+ import { AztecWalletError, AztecWalletErrorType } from './errors.js';
4
+ import type { JSONRPCTransport } from '@walletmesh/jsonrpc';
5
+ import type { ContractInstanceWithAddress, AztecAddress, ContractArtifact } from '@aztec/aztec.js';
6
+ import { WalletRouterProvider } from '@walletmesh/router';
7
+ import type { OperationBuilder } from '@walletmesh/router';
8
+ import type { Mock } from 'vitest';
9
+
10
+ const createMockTransport = () => ({
11
+ send: vi.fn(),
12
+ on: vi.fn(),
13
+ off: vi.fn(),
14
+ close: vi.fn(),
15
+ });
16
+
17
+ describe('AztecProvider', () => {
18
+ let provider: AztecProvider;
19
+ let mockTransport: ReturnType<typeof createMockTransport>;
20
+ let mockChainBuilder: {
21
+ chainId: string;
22
+ provider: WalletRouterProvider;
23
+ calls: unknown[];
24
+ call: Mock;
25
+ execute: Mock;
26
+ };
27
+
28
+ beforeEach(() => {
29
+ mockTransport = createMockTransport();
30
+ provider = new AztecProvider(mockTransport);
31
+
32
+ // Setup chain builder mock after provider creation
33
+ mockChainBuilder = {
34
+ chainId: 'aztec:testnet',
35
+ provider: provider,
36
+ calls: [],
37
+ call: vi.fn(),
38
+ execute: vi.fn(),
39
+ };
40
+
41
+ // Setup mock chain builder
42
+ mockChainBuilder.call.mockImplementation(() => mockChainBuilder);
43
+ mockChainBuilder.execute.mockImplementation(() => Promise.resolve());
44
+
45
+ // Setup additional mocks
46
+ vi.spyOn(provider as WalletRouterProvider, 'sessionId', 'get').mockReturnValue('test-session-id');
47
+ vi.spyOn(provider, 'chain').mockImplementation((chainId) => {
48
+ mockChainBuilder.chainId = chainId;
49
+ mockChainBuilder.call.mockImplementation((method, params) => {
50
+ mockChainBuilder.calls.push({ method, params });
51
+ return mockChainBuilder;
52
+ });
53
+ mockChainBuilder.execute.mockImplementation(async () => {
54
+ const result = await Promise.resolve(null);
55
+ if (result === null) {
56
+ throw new AztecWalletError(AztecWalletErrorType.invalidResponse, 'Invalid response');
57
+ }
58
+ return result;
59
+ });
60
+ return mockChainBuilder as unknown as OperationBuilder;
61
+ });
62
+ });
63
+
64
+ describe('constructor', () => {
65
+ test('registers event handlers', () => {
66
+ // Create a spy on the on method before creating provider
67
+ const onSpy = vi.spyOn(WalletRouterProvider.prototype, 'on');
68
+ const provider = new AztecProvider(mockTransport);
69
+
70
+ expect(onSpy).toHaveBeenCalledWith('wm_walletStateChanged', expect.any(Function));
71
+ expect(onSpy).toHaveBeenCalledWith('wm_sessionTerminated', expect.any(Function));
72
+
73
+ onSpy.mockRestore();
74
+ });
75
+
76
+ test('initializes with empty chain sets', () => {
77
+ expect(provider.getSupportedChains()).toEqual([]);
78
+ });
79
+ });
80
+
81
+ describe('handleWalletStateChanged', () => {
82
+ test('adds chain when accounts become available', () => {
83
+ const chainId = 'aztec:testnet';
84
+ provider['requestedChains'].add(chainId);
85
+
86
+ provider['handleWalletStateChanged']({
87
+ chainId,
88
+ changes: { accounts: ['0x123'] },
89
+ });
90
+
91
+ expect(provider.getSupportedChains()).toContain(chainId);
92
+ });
93
+
94
+ test('removes chain when accounts become unavailable', () => {
95
+ const chainId = 'aztec:testnet';
96
+ provider['requestedChains'].add(chainId);
97
+ provider['connectedChains'].add(chainId);
98
+
99
+ provider['handleWalletStateChanged']({
100
+ chainId,
101
+ changes: { accounts: [] },
102
+ });
103
+
104
+ expect(provider.getSupportedChains()).not.toContain(chainId);
105
+ });
106
+
107
+ test('ignores events for non-requested chains', () => {
108
+ const chainId = 'aztec:testnet';
109
+ // Chain not added to requestedChains
110
+
111
+ provider['handleWalletStateChanged']({
112
+ chainId,
113
+ changes: { accounts: ['0x123'] },
114
+ });
115
+
116
+ expect(provider.getSupportedChains()).not.toContain(chainId);
117
+ });
118
+ });
119
+
120
+ describe('handleSessionTerminated', () => {
121
+ test('clears chains when session matches', () => {
122
+ const chainId = 'aztec:testnet';
123
+ provider['requestedChains'].add(chainId);
124
+ provider['connectedChains'].add(chainId);
125
+
126
+ provider['handleSessionTerminated']({
127
+ sessionId: 'test-session-id',
128
+ reason: 'test termination',
129
+ });
130
+
131
+ expect(provider.getSupportedChains()).toEqual([]);
132
+ expect(provider['requestedChains'].size).toBe(0);
133
+ });
134
+
135
+ test('ignores termination for different sessions', () => {
136
+ const chainId = 'aztec:testnet';
137
+ provider['requestedChains'].add(chainId);
138
+ provider['connectedChains'].add(chainId);
139
+
140
+ provider['handleSessionTerminated']({
141
+ sessionId: 'different-session',
142
+ reason: 'test termination',
143
+ });
144
+
145
+ expect(provider.getSupportedChains()).toContain(chainId);
146
+ expect(provider['requestedChains'].has(chainId)).toBe(true);
147
+ });
148
+ });
149
+
150
+ describe('getAccount', () => {
151
+ test('returns account address on success', async () => {
152
+ const expectedAddress = '0x123';
153
+ mockChainBuilder.execute.mockResolvedValueOnce(expectedAddress);
154
+
155
+ const result = await provider.getAccount('aztec:testnet');
156
+ expect(result).toBe(expectedAddress);
157
+ });
158
+
159
+ test('throws on invalid response', async () => {
160
+ mockChainBuilder.execute.mockResolvedValueOnce(null);
161
+
162
+ await expect(provider.getAccount('aztec:testnet')).rejects.toThrowError(
163
+ new AztecWalletError(AztecWalletErrorType.invalidResponse, 'Invalid account address returned'),
164
+ );
165
+ });
166
+ });
167
+
168
+ describe('sendTransaction', () => {
169
+ const mockTxParams = {
170
+ functionCalls: [
171
+ {
172
+ contractAddress: '0x456',
173
+ functionName: 'transfer',
174
+ args: ['0x789', 100],
175
+ },
176
+ ],
177
+ };
178
+
179
+ test('returns transaction hash on success', async () => {
180
+ const expectedHash = '0xabc';
181
+ mockChainBuilder.execute.mockResolvedValueOnce(expectedHash);
182
+
183
+ const result = await provider.sendTransaction('aztec:testnet', mockTxParams);
184
+ expect(result).toBe(expectedHash);
185
+ });
186
+
187
+ test('throws on invalid response', async () => {
188
+ mockChainBuilder.execute.mockResolvedValueOnce(null);
189
+
190
+ await expect(provider.sendTransaction('aztec:testnet', mockTxParams)).rejects.toThrowError(
191
+ new AztecWalletError(AztecWalletErrorType.invalidResponse, 'Invalid transaction hash returned'),
192
+ );
193
+ });
194
+ });
195
+
196
+ describe('simulateTransaction', () => {
197
+ const mockSimParams = {
198
+ contractAddress: '0x456',
199
+ functionName: 'transfer',
200
+ args: ['0x789', 100],
201
+ };
202
+
203
+ test('returns simulation result on success', async () => {
204
+ const expectedResult = { success: true, gas: 1000 };
205
+ mockChainBuilder.execute.mockResolvedValueOnce(expectedResult);
206
+
207
+ const result = await provider.simulateTransaction('aztec:testnet', mockSimParams);
208
+ expect(result).toEqual(expectedResult);
209
+ });
210
+
211
+ test('throws on invalid response', async () => {
212
+ mockChainBuilder.execute.mockResolvedValueOnce(null);
213
+
214
+ await expect(provider.simulateTransaction('aztec:testnet', mockSimParams)).rejects.toThrowError(
215
+ new AztecWalletError(AztecWalletErrorType.invalidResponse, 'Invalid simulation result returned'),
216
+ );
217
+ });
218
+ });
219
+
220
+ describe('registration methods', () => {
221
+ test('registerContract executes without error', async () => {
222
+ mockChainBuilder.execute.mockResolvedValueOnce(undefined);
223
+
224
+ await expect(
225
+ provider.registerContract('aztec:testnet', {
226
+ instance: {
227
+ address: '0x123' as unknown as AztecAddress,
228
+ version: 1,
229
+ salt: '0x0' as unknown as AztecAddress,
230
+ deployer: '0x0' as unknown as AztecAddress,
231
+ contractClassId: '0x0' as unknown as AztecAddress,
232
+ contractClassVersion: 1,
233
+ publicKey: '0x0' as unknown as AztecAddress,
234
+ } as unknown as ContractInstanceWithAddress,
235
+ artifact: {
236
+ name: 'TestContract',
237
+ bytecode: '0x',
238
+ functionSelectors: {},
239
+ functions: {},
240
+ outputs: {},
241
+ storageLayout: {},
242
+ events: {},
243
+ } as unknown as ContractArtifact,
244
+ }),
245
+ ).resolves.not.toThrow();
246
+ });
247
+
248
+ test('registerContractClass executes without error', async () => {
249
+ mockChainBuilder.execute.mockResolvedValueOnce(undefined);
250
+
251
+ await expect(
252
+ provider.registerContractClass('aztec:testnet', {
253
+ artifact: {
254
+ name: 'TestContract',
255
+ bytecode: '0x',
256
+ functionSelectors: {},
257
+ functions: {},
258
+ outputs: {},
259
+ storageLayout: {},
260
+ events: {},
261
+ } as unknown as ContractArtifact,
262
+ }),
263
+ ).resolves.not.toThrow();
264
+ });
265
+
266
+ test('registerSender executes without error', async () => {
267
+ mockChainBuilder.execute.mockResolvedValueOnce(undefined);
268
+
269
+ await expect(
270
+ provider.registerSender('aztec:testnet', {
271
+ sender: '0x123' as unknown as AztecAddress,
272
+ }),
273
+ ).resolves.not.toThrow();
274
+ });
275
+ });
276
+ });