@walletmesh/aztec-rpc-wallet 0.1.0

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 (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
+ });