@walletmesh/aztec-rpc-wallet 0.3.1 → 0.4.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 (185) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +290 -228
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/client/aztec-dapp-wallet.d.ts +401 -0
  5. package/dist/client/aztec-dapp-wallet.d.ts.map +1 -0
  6. package/dist/client/aztec-dapp-wallet.js +705 -0
  7. package/dist/client/aztec-router-provider.d.ts +58 -0
  8. package/dist/client/aztec-router-provider.d.ts.map +1 -0
  9. package/dist/client/aztec-router-provider.js +62 -0
  10. package/dist/client/helpers.d.ts +44 -0
  11. package/dist/client/helpers.d.ts.map +1 -0
  12. package/dist/client/helpers.js +79 -0
  13. package/dist/client/register-serializers.d.ts +41 -0
  14. package/dist/client/register-serializers.d.ts.map +1 -0
  15. package/dist/client/register-serializers.js +97 -0
  16. package/dist/contractArtifactCache.d.ts +49 -32
  17. package/dist/contractArtifactCache.d.ts.map +1 -1
  18. package/dist/contractArtifactCache.js +47 -34
  19. package/dist/errors.d.ts +50 -8
  20. package/dist/errors.d.ts.map +1 -1
  21. package/dist/errors.js +50 -10
  22. package/dist/index.d.ts +53 -40
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +52 -17
  25. package/dist/types.d.ts +345 -270
  26. package/dist/types.d.ts.map +1 -1
  27. package/dist/types.js +10 -8
  28. package/dist/wallet/create-node.d.ts +73 -0
  29. package/dist/wallet/create-node.d.ts.map +1 -0
  30. package/dist/wallet/create-node.js +99 -0
  31. package/dist/wallet/handlers/account.d.ts +67 -0
  32. package/dist/wallet/handlers/account.d.ts.map +1 -0
  33. package/dist/wallet/handlers/account.js +85 -0
  34. package/dist/wallet/handlers/contract-interaction.d.ts +77 -0
  35. package/dist/wallet/handlers/contract-interaction.d.ts.map +1 -0
  36. package/dist/wallet/handlers/contract-interaction.js +219 -0
  37. package/dist/wallet/handlers/contract.d.ts +96 -0
  38. package/dist/wallet/handlers/contract.d.ts.map +1 -0
  39. package/dist/wallet/handlers/contract.js +146 -0
  40. package/dist/wallet/handlers/event.d.ts +62 -0
  41. package/dist/wallet/handlers/event.d.ts.map +1 -0
  42. package/dist/wallet/handlers/event.js +85 -0
  43. package/dist/wallet/handlers/index.d.ts +88 -0
  44. package/dist/wallet/handlers/index.d.ts.map +1 -0
  45. package/dist/wallet/handlers/index.js +47 -0
  46. package/dist/wallet/handlers/node.d.ts +117 -0
  47. package/dist/wallet/handlers/node.d.ts.map +1 -0
  48. package/dist/wallet/handlers/node.js +196 -0
  49. package/dist/wallet/handlers/senders.d.ts +70 -0
  50. package/dist/wallet/handlers/senders.d.ts.map +1 -0
  51. package/dist/wallet/handlers/senders.js +92 -0
  52. package/dist/wallet/handlers/transaction.d.ts +123 -0
  53. package/dist/wallet/handlers/transaction.d.ts.map +1 -0
  54. package/dist/wallet/handlers/transaction.js +191 -0
  55. package/dist/wallet/serializers.d.ts +75 -0
  56. package/dist/wallet/serializers.d.ts.map +1 -0
  57. package/dist/wallet/serializers.js +498 -0
  58. package/docs/README.md +290 -229
  59. package/docs/classes/AztecDappWallet.md +1304 -0
  60. package/docs/classes/AztecRouterProvider.md +1058 -0
  61. package/docs/classes/AztecWalletError.md +124 -47
  62. package/docs/classes/ContractArtifactCache.md +48 -31
  63. package/docs/functions/connectAztec.md +62 -0
  64. package/docs/functions/createAztecWallet.md +46 -0
  65. package/docs/functions/createAztecWalletNode.md +96 -0
  66. package/docs/functions/registerAztecSerializers.md +61 -0
  67. package/docs/functions/registerWalletAztecSerializers.md +39 -0
  68. package/docs/globals.md +16 -14
  69. package/docs/interfaces/AztecHandlerContext.md +54 -0
  70. package/docs/interfaces/AztecWalletContext.md +50 -0
  71. package/docs/interfaces/AztecWalletMethodMap.md +470 -477
  72. package/docs/type-aliases/AztecChainId.md +16 -3
  73. package/docs/variables/ALL_AZTEC_METHODS.md +20 -0
  74. package/docs/variables/AztecWalletErrorMap.md +9 -4
  75. package/docs/variables/AztecWalletSerializer.md +45 -0
  76. package/package.json +11 -9
  77. package/src/client/aztec-dapp-wallet.test.ts +628 -0
  78. package/src/client/aztec-dapp-wallet.ts +879 -0
  79. package/src/client/aztec-router-provider.test.ts +235 -0
  80. package/src/client/aztec-router-provider.ts +64 -0
  81. package/src/client/helpers.test.ts +187 -0
  82. package/src/client/helpers.ts +91 -0
  83. package/src/client/register-serializers.ts +108 -0
  84. package/src/contractArtifactCache.test.ts +21 -10
  85. package/src/contractArtifactCache.ts +54 -35
  86. package/src/errors.ts +58 -10
  87. package/src/index.test.ts +2 -6
  88. package/src/index.ts +73 -37
  89. package/src/types.ts +379 -217
  90. package/src/wallet/create-node.test.ts +332 -0
  91. package/src/wallet/create-node.ts +120 -0
  92. package/src/wallet/handlers/account.test.ts +172 -0
  93. package/src/wallet/handlers/account.ts +99 -0
  94. package/src/wallet/handlers/contract-interaction.test.ts +248 -0
  95. package/src/wallet/handlers/contract-interaction.ts +269 -0
  96. package/src/wallet/handlers/contract.test.ts +245 -0
  97. package/src/wallet/handlers/contract.ts +174 -0
  98. package/src/wallet/handlers/event.test.ts +216 -0
  99. package/src/wallet/handlers/event.ts +99 -0
  100. package/src/wallet/handlers/index.ts +84 -0
  101. package/src/wallet/handlers/node.test.ts +304 -0
  102. package/src/wallet/handlers/node.ts +230 -0
  103. package/src/wallet/handlers/senders.test.ts +172 -0
  104. package/src/wallet/handlers/senders.ts +106 -0
  105. package/src/wallet/handlers/transaction.test.ts +371 -0
  106. package/src/wallet/handlers/transaction.ts +239 -0
  107. package/src/wallet/serializers.test.ts +253 -0
  108. package/src/wallet/serializers.ts +584 -0
  109. package/typedoc.json +23 -1
  110. package/dist/aztecRemoteWallet.d.ts +0 -70
  111. package/dist/aztecRemoteWallet.d.ts.map +0 -1
  112. package/dist/aztecRemoteWallet.js +0 -335
  113. package/dist/chainProvider.d.ts +0 -56
  114. package/dist/chainProvider.d.ts.map +0 -1
  115. package/dist/chainProvider.js +0 -98
  116. package/dist/handlers/aztecAccountWallet.d.ts +0 -4
  117. package/dist/handlers/aztecAccountWallet.d.ts.map +0 -1
  118. package/dist/handlers/aztecAccountWallet.js +0 -295
  119. package/dist/handlers/transactions.d.ts +0 -21
  120. package/dist/handlers/transactions.d.ts.map +0 -1
  121. package/dist/handlers/transactions.js +0 -98
  122. package/dist/handlers.d.ts +0 -27
  123. package/dist/handlers.d.ts.map +0 -1
  124. package/dist/handlers.js +0 -55
  125. package/dist/provider.d.ts +0 -105
  126. package/dist/provider.d.ts.map +0 -1
  127. package/dist/provider.js +0 -160
  128. package/dist/serializers/account.d.ts +0 -164
  129. package/dist/serializers/account.d.ts.map +0 -1
  130. package/dist/serializers/account.js +0 -244
  131. package/dist/serializers/contract.d.ts +0 -62
  132. package/dist/serializers/contract.d.ts.map +0 -1
  133. package/dist/serializers/contract.js +0 -130
  134. package/dist/serializers/index.d.ts +0 -21
  135. package/dist/serializers/index.d.ts.map +0 -1
  136. package/dist/serializers/index.js +0 -154
  137. package/dist/serializers/log.d.ts +0 -66
  138. package/dist/serializers/log.d.ts.map +0 -1
  139. package/dist/serializers/log.js +0 -222
  140. package/dist/serializers/note.d.ts +0 -124
  141. package/dist/serializers/note.d.ts.map +0 -1
  142. package/dist/serializers/note.js +0 -208
  143. package/dist/serializers/transaction.d.ts +0 -99
  144. package/dist/serializers/transaction.d.ts.map +0 -1
  145. package/dist/serializers/transaction.js +0 -275
  146. package/dist/wallet.d.ts +0 -62
  147. package/dist/wallet.d.ts.map +0 -1
  148. package/dist/wallet.js +0 -77
  149. package/docs/classes/AztecChainProvider.md +0 -553
  150. package/docs/classes/AztecChainWallet.md +0 -409
  151. package/docs/classes/AztecProvider.md +0 -1112
  152. package/docs/interfaces/AztecWalletBaseMethodMap.md +0 -135
  153. package/docs/interfaces/AztecWalletEventMap.md +0 -17
  154. package/docs/type-aliases/AztecChainWalletMiddleware.md +0 -13
  155. package/docs/type-aliases/AztecWalletContext.md +0 -29
  156. package/docs/type-aliases/AztecWalletMethodHandler.md +0 -37
  157. package/docs/type-aliases/AztecWalletMiddleware.md +0 -13
  158. package/docs/type-aliases/AztecWalletRouterClient.md +0 -13
  159. package/docs/type-aliases/TransactionFunctionCall.md +0 -33
  160. package/docs/type-aliases/TransactionParams.md +0 -27
  161. package/src/aztecRemoteWallet.test.ts +0 -505
  162. package/src/aztecRemoteWallet.ts +0 -467
  163. package/src/chainProvider.test.ts +0 -401
  164. package/src/chainProvider.ts +0 -116
  165. package/src/handlers/aztecAccountWallet.test.ts +0 -650
  166. package/src/handlers/aztecAccountWallet.ts +0 -531
  167. package/src/handlers/transactions.ts +0 -124
  168. package/src/handlers.test.ts +0 -270
  169. package/src/handlers.ts +0 -70
  170. package/src/provider.test.ts +0 -277
  171. package/src/provider.ts +0 -189
  172. package/src/serializers/account.test.ts +0 -125
  173. package/src/serializers/account.ts +0 -301
  174. package/src/serializers/contract.test.ts +0 -24
  175. package/src/serializers/contract.ts +0 -183
  176. package/src/serializers/index.test.ts +0 -136
  177. package/src/serializers/index.ts +0 -191
  178. package/src/serializers/log.test.ts +0 -286
  179. package/src/serializers/log.ts +0 -292
  180. package/src/serializers/note.test.ts +0 -125
  181. package/src/serializers/note.ts +0 -250
  182. package/src/serializers/transaction.test.ts +0 -320
  183. package/src/serializers/transaction.ts +0 -409
  184. package/src/wallet.test.ts +0 -275
  185. package/src/wallet.ts +0 -94
@@ -0,0 +1,99 @@
1
+ import type { AztecHandlerContext } from './index.js';
2
+ import type { AztecWalletMethodMap } from '../../types.js';
3
+ import { createLogger } from '@aztec/foundation/log';
4
+
5
+ const logger = createLogger('aztec-rpc-wallet:account');
6
+
7
+ /**
8
+ * Creates handlers for account-related Aztec wallet JSON-RPC methods.
9
+ * These handlers are responsible for managing wallet identity, retrieving addresses,
10
+ * and creating authorization witnesses.
11
+ *
12
+ * Each handler function receives an {@link AztecHandlerContext} which provides access
13
+ * to the core {@link AccountWallet} instance, the {@link PXE} client, and a
14
+ * {@link ContractArtifactCache}.
15
+ *
16
+ * @returns An object where keys are account-related method names
17
+ * (e.g., "aztec_getAddress", "aztec_createAuthWit") and values are their
18
+ * corresponding handler functions.
19
+ * @see {@link AztecWalletMethodMap} for method definitions.
20
+ */
21
+ export function createAccountHandlers() {
22
+ return {
23
+ /**
24
+ * Handles the "aztec_getAddress" JSON-RPC method.
25
+ * Retrieves the primary {@link AztecAddress} of the account associated with the
26
+ * {@link AccountWallet} in the current context.
27
+ *
28
+ * @param ctx - The {@link AztecHandlerContext} containing the `wallet` instance.
29
+ * @param _paramsTuple - Parameters for this method (expected to be an empty array).
30
+ * Defined by {@link AztecWalletMethodMap.aztec_getAddress.params}.
31
+ * @returns A promise that resolves to the {@link AztecAddress} of the wallet.
32
+ * Type defined by {@link AztecWalletMethodMap.aztec_getAddress.result}.
33
+ */
34
+ aztec_getAddress: async (
35
+ ctx: AztecHandlerContext,
36
+ _paramsTuple: AztecWalletMethodMap['aztec_getAddress']['params'], // Will be `[]`
37
+ ): Promise<AztecWalletMethodMap['aztec_getAddress']['result']> => {
38
+ logger.debug('[HANDLER] aztec_getAddress');
39
+ return ctx.wallet.getAddress();
40
+ },
41
+
42
+ /**
43
+ * Handles the "aztec_getCompleteAddress" JSON-RPC method.
44
+ * Retrieves the {@link CompleteAddress} (which includes public keys and partial address)
45
+ * of the account associated with the {@link AccountWallet} in the current context.
46
+ *
47
+ * The complete address typically contains:
48
+ * - The {@link AztecAddress}
49
+ * - Public keys (e.g., nullifier key, incoming viewing key)
50
+ * - Partial address
51
+ *
52
+ * @param ctx - The {@link AztecHandlerContext} containing the `wallet` instance.
53
+ * @param _paramsTuple - Parameters for this method (expected to be an empty array).
54
+ * Defined by {@link AztecWalletMethodMap.aztec_getCompleteAddress.params}.
55
+ * @returns A promise that resolves to the {@link CompleteAddress} of the wallet.
56
+ * Type defined by {@link AztecWalletMethodMap.aztec_getCompleteAddress.result}.
57
+ */
58
+ aztec_getCompleteAddress: async (
59
+ ctx: AztecHandlerContext,
60
+ _paramsTuple: AztecWalletMethodMap['aztec_getCompleteAddress']['params'], // Will be `[]`
61
+ ): Promise<AztecWalletMethodMap['aztec_getCompleteAddress']['result']> => {
62
+ logger.debug('[HANDLER] aztec_getCompleteAddress');
63
+ return ctx.wallet.getCompleteAddress();
64
+ },
65
+
66
+ /**
67
+ * Handles the "aztec_createAuthWit" JSON-RPC method.
68
+ * Creates an {@link AuthWitness} for a given message hash or intent, using the
69
+ * {@link AccountWallet} in the current context.
70
+ *
71
+ * Authorization witnesses are used to delegate actions, allowing a contract or another
72
+ * entity to perform operations on behalf of the wallet owner (e.g., for token approvals).
73
+ *
74
+ * @param ctx - The {@link AztecHandlerContext} containing the `wallet` instance.
75
+ * @param paramsTuple - A tuple containing the intent to authorize.
76
+ * Defined by {@link AztecWalletMethodMap.aztec_createAuthWit.params}.
77
+ * @param paramsTuple.0 - The intent to authorize, which can be a message hash ({@link Fr} or `Buffer`),
78
+ * an {@link IntentInnerHash}, or an {@link IntentAction}.
79
+ * @returns A promise that resolves to the created {@link AuthWitness}.
80
+ * Type defined by {@link AztecWalletMethodMap.aztec_createAuthWit.result}.
81
+ * @throws {Error} If the `intent` parameter is missing or invalid, though type checking
82
+ * and serializer validation should ideally catch this earlier.
83
+ */
84
+ aztec_createAuthWit: async (
85
+ ctx: AztecHandlerContext,
86
+ paramsTuple: AztecWalletMethodMap['aztec_createAuthWit']['params'],
87
+ ): Promise<AztecWalletMethodMap['aztec_createAuthWit']['result']> => {
88
+ const [intent] = paramsTuple;
89
+ logger.debug(`[HANDLER] aztec_createAuthWit: intent type = ${typeof intent}`);
90
+ // Intent is not optional in the tuple type.
91
+ // Add runtime check for robustness if needed.
92
+ if (intent === undefined) {
93
+ // Basic check, though TS should prevent this if tuple type is correct
94
+ throw new Error('Invalid intent parameter received in tuple');
95
+ }
96
+ return await ctx.wallet.createAuthWit(intent);
97
+ },
98
+ };
99
+ }
@@ -0,0 +1,248 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import { createContractInteractionHandlers } from './contract-interaction.js';
3
+ import type { AztecHandlerContext } from './index.js';
4
+ import { AztecAddress, Fr, type TxReceipt, TxHash } from '@aztec/aztec.js';
5
+ import { GasFees } from '@aztec/stdlib/gas';
6
+ import { FeeJuicePaymentMethod } from '@aztec/aztec.js';
7
+ import type { ExecutionPayload } from '@aztec/entrypoints/payload';
8
+
9
+ // Mock the aztec.js module
10
+ vi.mock('@aztec/aztec.js', async () => {
11
+ const actual = await vi.importActual('@aztec/aztec.js');
12
+ return {
13
+ ...actual,
14
+ Contract: {
15
+ deploy: vi.fn(),
16
+ },
17
+ };
18
+ });
19
+
20
+ describe('createContractInteractionHandlers', () => {
21
+ let mockContext: AztecHandlerContext;
22
+ let handlers: ReturnType<typeof createContractInteractionHandlers>;
23
+
24
+ const mockAddress = AztecAddress.fromString(
25
+ '0x1111111111111111111111111111111111111111111111111111111111111111',
26
+ );
27
+ const mockTxHash = TxHash.fromString('0x2222222222222222222222222222222222222222222222222222222222222222');
28
+ const mockTxReceipt = {
29
+ txHash: mockTxHash,
30
+ blockNumber: 1,
31
+ status: 'success',
32
+ } as unknown as TxReceipt;
33
+
34
+ const mockExecutionPayload: ExecutionPayload = {
35
+ calls: [], // Add calls property
36
+ } as unknown as ExecutionPayload;
37
+
38
+ beforeEach(() => {
39
+ mockContext = {
40
+ wallet: {
41
+ getAddress: vi.fn().mockReturnValue(mockAddress),
42
+ getCurrentBaseFees: vi.fn().mockResolvedValue(new GasFees(new Fr(100n), new Fr(100n))),
43
+ createTxExecutionRequest: vi.fn().mockResolvedValue({}),
44
+ simulateTx: vi.fn().mockResolvedValue({ privateExecutionResult: {} }),
45
+ proveTx: vi.fn().mockResolvedValue({ toTx: vi.fn().mockReturnValue({}) }),
46
+ sendTx: vi.fn().mockResolvedValue(mockTxHash),
47
+ getTxReceipt: vi.fn().mockResolvedValue(mockTxReceipt),
48
+ registerContract: vi.fn().mockResolvedValue(undefined),
49
+ getContractClassMetadata: vi.fn().mockResolvedValue({
50
+ artifactHash: new Fr(123n),
51
+ privateFunctionsRoot: new Fr(456n),
52
+ publicBytecodeCommitment: new Fr(789n),
53
+ }),
54
+ getContractMetadata: vi.fn().mockResolvedValue(undefined),
55
+ registerContractClass: vi.fn().mockResolvedValue(undefined),
56
+ },
57
+ pxe: {},
58
+ cache: {},
59
+ } as unknown as AztecHandlerContext;
60
+
61
+ handlers = createContractInteractionHandlers();
62
+ });
63
+
64
+ describe('aztec_wmExecuteTx', () => {
65
+ it('should execute a contract interaction', async () => {
66
+ const result = await handlers.aztec_wmExecuteTx(mockContext, [mockExecutionPayload]);
67
+
68
+ expect(result).toBe(mockTxHash);
69
+ expect(mockContext.wallet.getCurrentBaseFees).toHaveBeenCalled();
70
+ expect(mockContext.wallet.createTxExecutionRequest).toHaveBeenCalled();
71
+ expect(mockContext.wallet.simulateTx).toHaveBeenCalled();
72
+ expect(mockContext.wallet.proveTx).toHaveBeenCalled();
73
+ expect(mockContext.wallet.sendTx).toHaveBeenCalled();
74
+ });
75
+
76
+ it('should handle contract interaction with proper fee configuration', async () => {
77
+ await handlers.aztec_wmExecuteTx(mockContext, [mockExecutionPayload]);
78
+
79
+ // Verify fee configuration
80
+ const createTxCall = vi.mocked(mockContext.wallet.createTxExecutionRequest).mock.calls[0];
81
+ expect(createTxCall).toBeDefined();
82
+ expect(createTxCall?.[0]).toBe(mockExecutionPayload);
83
+
84
+ const feeOpts = createTxCall?.[1];
85
+ expect(feeOpts).toBeDefined();
86
+ expect(feeOpts?.paymentMethod).toBeInstanceOf(FeeJuicePaymentMethod);
87
+ expect(feeOpts?.gasSettings).toBeDefined();
88
+ });
89
+ });
90
+
91
+ describe('aztec_wmDeployContract', () => {
92
+ it('should deploy a contract with new interface', async () => {
93
+ const { Contract } = await import('@aztec/aztec.js');
94
+
95
+ // Create a minimal artifact that won't trigger complex contract deployment logic
96
+ const mockArtifact = {
97
+ name: 'TestContract',
98
+ functions: [],
99
+ } as unknown as import('@aztec/aztec.js').ContractArtifact;
100
+
101
+ const mockArgs: unknown[] = [];
102
+
103
+ const mockSentTx = {
104
+ getTxHash: vi.fn().mockResolvedValue(mockTxHash),
105
+ };
106
+
107
+ const mockProvenTx = {
108
+ send: vi.fn().mockResolvedValue(mockSentTx),
109
+ };
110
+
111
+ const mockDeployMethod = {
112
+ prove: vi.fn().mockResolvedValue(mockProvenTx),
113
+ getInstance: vi.fn().mockResolvedValue({
114
+ address: mockAddress,
115
+ }),
116
+ };
117
+
118
+ vi.mocked(Contract.deploy).mockReturnValue(
119
+ mockDeployMethod as unknown as ReturnType<typeof Contract.deploy>,
120
+ );
121
+
122
+ const params = {
123
+ artifact: mockArtifact,
124
+ args: mockArgs,
125
+ };
126
+
127
+ const result = await handlers.aztec_wmDeployContract(mockContext, [params]);
128
+
129
+ expect(result).toEqual({
130
+ txHash: mockTxHash,
131
+ contractAddress: mockAddress,
132
+ });
133
+ expect(Contract.deploy).toHaveBeenCalledWith(mockContext.wallet, mockArtifact, mockArgs, undefined);
134
+ expect(mockDeployMethod.prove).toHaveBeenCalled();
135
+ expect(mockProvenTx.send).toHaveBeenCalled();
136
+ expect(mockSentTx.getTxHash).toHaveBeenCalled();
137
+ expect(mockContext.wallet.getCurrentBaseFees).toHaveBeenCalled();
138
+ });
139
+
140
+ it('should deploy a contract with custom constructor name', async () => {
141
+ const { Contract } = await import('@aztec/aztec.js');
142
+
143
+ const mockArtifact = {
144
+ name: 'TestContract',
145
+ functions: [],
146
+ } as unknown as import('@aztec/aztec.js').ContractArtifact;
147
+
148
+ const mockArgs: unknown[] = [];
149
+
150
+ const mockSentTx = {
151
+ getTxHash: vi.fn().mockResolvedValue(mockTxHash),
152
+ };
153
+
154
+ const mockProvenTx = {
155
+ send: vi.fn().mockResolvedValue(mockSentTx),
156
+ };
157
+
158
+ const mockDeployMethod = {
159
+ prove: vi.fn().mockResolvedValue(mockProvenTx),
160
+ getInstance: vi.fn().mockResolvedValue({
161
+ address: mockAddress,
162
+ }),
163
+ };
164
+
165
+ vi.mocked(Contract.deploy).mockReturnValue(
166
+ mockDeployMethod as unknown as ReturnType<typeof Contract.deploy>,
167
+ );
168
+
169
+ const params = {
170
+ artifact: mockArtifact,
171
+ args: mockArgs,
172
+ constructorName: 'customConstructor',
173
+ };
174
+
175
+ const result = await handlers.aztec_wmDeployContract(mockContext, [params]);
176
+
177
+ expect(result).toEqual({
178
+ txHash: mockTxHash,
179
+ contractAddress: mockAddress,
180
+ });
181
+ expect(Contract.deploy).toHaveBeenCalledWith(
182
+ mockContext.wallet,
183
+ mockArtifact,
184
+ mockArgs,
185
+ 'customConstructor',
186
+ );
187
+ expect(mockDeployMethod.prove).toHaveBeenCalled();
188
+ expect(mockProvenTx.send).toHaveBeenCalled();
189
+ expect(mockSentTx.getTxHash).toHaveBeenCalled();
190
+ });
191
+
192
+ it('should register contract instance before deployment', async () => {
193
+ const { Contract } = await import('@aztec/aztec.js');
194
+
195
+ const mockArtifact = {
196
+ name: 'TestContract',
197
+ functions: [],
198
+ } as unknown as import('@aztec/aztec.js').ContractArtifact;
199
+
200
+ const mockSentTx = {
201
+ getTxHash: vi.fn().mockResolvedValue(mockTxHash),
202
+ };
203
+
204
+ const mockProvenTx = {
205
+ send: vi.fn().mockResolvedValue(mockSentTx),
206
+ };
207
+
208
+ const mockDeployMethod = {
209
+ prove: vi.fn().mockResolvedValue(mockProvenTx),
210
+ getInstance: vi.fn().mockResolvedValue({
211
+ address: mockAddress,
212
+ }),
213
+ };
214
+
215
+ vi.mocked(Contract.deploy).mockReturnValue(
216
+ mockDeployMethod as unknown as ReturnType<typeof Contract.deploy>,
217
+ );
218
+
219
+ const params = {
220
+ artifact: mockArtifact,
221
+ args: [],
222
+ };
223
+
224
+ // Track the order of calls
225
+ const callOrder: string[] = [];
226
+ vi.mocked(mockContext.wallet.getCurrentBaseFees).mockImplementation(async () => {
227
+ callOrder.push('getCurrentBaseFees');
228
+ return new GasFees(new Fr(100n), new Fr(100n));
229
+ });
230
+ vi.mocked(mockDeployMethod.prove).mockImplementation(async () => {
231
+ callOrder.push('prove');
232
+ return mockProvenTx;
233
+ });
234
+ vi.mocked(mockProvenTx.send).mockImplementation(async () => {
235
+ callOrder.push('send');
236
+ return mockSentTx;
237
+ });
238
+
239
+ await handlers.aztec_wmDeployContract(mockContext, [params]);
240
+
241
+ // Verify that the deployment flow is correct
242
+ expect(callOrder.includes('getCurrentBaseFees')).toBe(true);
243
+ expect(callOrder.includes('prove')).toBe(true);
244
+ expect(callOrder.includes('send')).toBe(true);
245
+ expect(callOrder.indexOf('prove') < callOrder.indexOf('send')).toBe(true);
246
+ });
247
+ });
248
+ });
@@ -0,0 +1,269 @@
1
+ import type { AztecHandlerContext } from './index.js';
2
+ import type { AztecWalletMethodMap } from '../../types.js';
3
+ import { Contract, FeeJuicePaymentMethod, Fr, type DeployOptions, type TxHash } from '@aztec/aztec.js';
4
+ import type { ExecutionPayload } from '@aztec/entrypoints/payload';
5
+ import type { FeeOptions, TxExecutionOptions } from '@aztec/entrypoints/interfaces';
6
+ import { GasSettings } from '@aztec/stdlib/gas';
7
+ import { createLogger } from '@aztec/foundation/log';
8
+ import type { TxExecutionRequest, TxSimulationResult } from '@aztec/stdlib/tx';
9
+
10
+ const logger = createLogger('aztec-rpc-wallet:contract-interaction:handler');
11
+
12
+ /**
13
+ * @module @walletmesh/aztec-rpc-wallet/wallet/handlers/contract-interaction
14
+ * This module provides handlers for WalletMesh-specific high-level contract
15
+ * interaction and deployment methods (e.g., `aztec_wmExecuteTx`, `aztec_wmDeployContract`).
16
+ * These methods simplify common contract operations for dApp developers by accepting
17
+ * an {@link ExecutionPayload} or deployment parameters, with the wallet-side
18
+ * handling more of the transaction construction, simulation, proving, and sending flow.
19
+ */
20
+
21
+ /**
22
+ * Creates handlers for WalletMesh-specific contract interaction and deployment JSON-RPC methods.
23
+ *
24
+ * These handlers manage high-level contract operations such as:
25
+ * - `aztec_wmExecuteTx`: Executing a pre-constructed {@link ExecutionPayload}.
26
+ * - `aztec_wmSimulateTx`: Simulating an {@link ExecutionPayload}.
27
+ * - `aztec_wmDeployContract`: Deploying a new contract from its artifact and arguments.
28
+ *
29
+ * The primary goal of these "wm" (WalletMesh) methods is to simplify the dApp's
30
+ * interaction with the wallet by abstracting parts of the standard Aztec transaction
31
+ * lifecycle (e.g., fee estimation, `createTxExecutionRequest`, `proveTx`, `sendTx`).
32
+ * The wallet takes on more responsibility, which can lead to a better user experience
33
+ * as the wallet can provide more context or apply its own policies.
34
+ *
35
+ * @returns An object where keys are "wm" prefixed method names and values are their
36
+ * corresponding handler functions.
37
+ * @see {@link AztecWalletMethodMap} for method definitions.
38
+ */
39
+ export function createContractInteractionHandlers() {
40
+ /** @internal Helper to configure fee options. TODO: Make this more configurable. */
41
+ async function getFeeOptions(ctx: AztecHandlerContext): Promise<FeeOptions> {
42
+ // TODO: Provide gas settings from the context
43
+ logger.debug('Getting current base fees...');
44
+ const baseFees = await ctx.wallet.getCurrentBaseFees();
45
+ logger.debug('Base fees:', baseFees);
46
+
47
+ const maxFeesPerGas = baseFees.mul(1.5);
48
+ logger.debug('Calculated max fees per gas:', maxFeesPerGas);
49
+
50
+ const feeOpts: FeeOptions = {
51
+ paymentMethod: new FeeJuicePaymentMethod(ctx.wallet.getAddress()),
52
+ gasSettings: GasSettings.default({ maxFeesPerGas }),
53
+ };
54
+ logger.debug('Fee options configured:', feeOpts);
55
+
56
+ return feeOpts;
57
+ }
58
+
59
+ /** @internal Helper to configure transaction execution options. TODO: Make this more configurable. */
60
+ async function getTxOptions(_ctx: AztecHandlerContext): Promise<TxExecutionOptions> {
61
+ // TODO(twt): Enable setting cancellable flag & nonce in the options
62
+ const txOpts: TxExecutionOptions = {};
63
+ return txOpts;
64
+ }
65
+
66
+ async function createTxExecutionRequest(
67
+ ctx: AztecHandlerContext,
68
+ executionPayload: ExecutionPayload,
69
+ ): Promise<TxExecutionRequest> {
70
+ logger.debug('Creating transaction execution request...');
71
+ try {
72
+ // TODO(twt): Provide gas settings from the context
73
+ logger.debug('Getting current base fees...');
74
+ const baseFees = await ctx.wallet.getCurrentBaseFees();
75
+ logger.debug('Base fees:', baseFees);
76
+
77
+ const maxFeesPerGas = baseFees.mul(1.5);
78
+ logger.debug('Calculated max fees per gas:', maxFeesPerGas);
79
+
80
+ const feeOpts = await getFeeOptions(ctx);
81
+ const txOpts = await getTxOptions(ctx);
82
+
83
+ // Create a transaction execution request from the payload
84
+ const txRequest = await ctx.wallet.createTxExecutionRequest(executionPayload, feeOpts, txOpts);
85
+
86
+ return txRequest;
87
+ } catch (error) {
88
+ logger.error('Failed to create transaction execution request:', error);
89
+ throw error;
90
+ }
91
+ }
92
+
93
+ async function simulateTransaction(
94
+ ctx: AztecHandlerContext,
95
+ executionPayload: ExecutionPayload,
96
+ txExecutionRequest?: TxExecutionRequest,
97
+ ): Promise<TxSimulationResult> {
98
+ try {
99
+ const txRequest = txExecutionRequest || (await createTxExecutionRequest(ctx, executionPayload));
100
+ // Execute the transaction using the standard flow
101
+ logger.debug('Starting transaction simulation...');
102
+ const simStartTime = Date.now();
103
+ const simulationResult = await ctx.wallet.simulateTx(txRequest, true);
104
+ logger.debug(`Transaction simulation completed in ${Date.now() - simStartTime}ms`);
105
+ return simulationResult;
106
+ } catch (error) {
107
+ logger.error('Transaction simulation failed:', error);
108
+ throw error;
109
+ }
110
+ }
111
+
112
+ /**
113
+ * @internal
114
+ * Helper function to execute a transaction from an {@link ExecutionPayload}.
115
+ * This consolidates the common flow:
116
+ * 1. Create TxExecutionRequest (if needed, though typically done by `aztec_wmExecuteTx` caller or here).
117
+ * 2. Simulate transaction.
118
+ * 3. Prove transaction.
119
+ * 4. Send transaction.
120
+ *
121
+ * @param ctx - The {@link AztecHandlerContext}.
122
+ * @param executionPayload - The {@link ExecutionPayload} for the transaction.
123
+ * @returns A promise resolving to the {@link TxHash} of the sent transaction.
124
+ */
125
+ async function executeTransaction(
126
+ ctx: AztecHandlerContext,
127
+ executionPayload: ExecutionPayload,
128
+ ): Promise<TxHash> {
129
+ const startTime = Date.now();
130
+ logger.debug(
131
+ `Starting transaction execution. Wallet: ${ctx.wallet.getAddress().toString()}, Payload: ${executionPayload.calls.length} calls`,
132
+ );
133
+ logger.debug('Execution payload:', executionPayload);
134
+
135
+ try {
136
+ const txRequest = await createTxExecutionRequest(ctx, executionPayload);
137
+ const simulationResult = await simulateTransaction(ctx, executionPayload, txRequest);
138
+
139
+ logger.debug('Starting transaction proving...');
140
+ const proveStartTime = Date.now();
141
+ const provingResult = await ctx.wallet.proveTx(txRequest, simulationResult.privateExecutionResult);
142
+ logger.debug(`Transaction proving completed in ${Date.now() - proveStartTime}ms`);
143
+ logger.debug('Proving result:', provingResult);
144
+
145
+ logger.debug('Creating transaction from proving result...');
146
+ const tx = provingResult.toTx();
147
+ logger.debug('Transaction created:', tx);
148
+
149
+ logger.debug('Sending transaction to network...');
150
+ const sendStartTime = Date.now();
151
+ const txHash = await ctx.wallet.sendTx(tx);
152
+ logger.debug(`Transaction sent in ${Date.now() - sendStartTime}ms, hash: ${txHash.toString()}`);
153
+
154
+ return txHash;
155
+ } catch (error) {
156
+ const totalTime = Date.now() - startTime;
157
+ logger.error(`Transaction execution failed after ${totalTime}ms}`);
158
+ logger.error('Error details:', error);
159
+ throw error;
160
+ }
161
+ }
162
+
163
+ return {
164
+ /**
165
+ * Handles the "aztec_wmExecuteTx" JSON-RPC method.
166
+ * This WalletMesh-specific method takes an {@link ExecutionPayload} and handles
167
+ * the full lifecycle of simulating, proving, and sending the transaction.
168
+ *
169
+ * @param ctx - The {@link AztecHandlerContext}.
170
+ * @param paramsTuple - A tuple containing the {@link ExecutionPayload}.
171
+ * Defined by {@link AztecWalletMethodMap.aztec_wmExecuteTx.params}.
172
+ * @param paramsTuple.0 - The {@link ExecutionPayload} to execute.
173
+ * @returns A promise that resolves to the {@link TxHash} of the sent transaction.
174
+ * Type defined by {@link AztecWalletMethodMap.aztec_wmExecuteTx.result}.
175
+ */
176
+ aztec_wmExecuteTx: async (
177
+ ctx: AztecHandlerContext,
178
+ paramsTuple: AztecWalletMethodMap['aztec_wmExecuteTx']['params'],
179
+ ): Promise<AztecWalletMethodMap['aztec_wmExecuteTx']['result']> => {
180
+ const [executionPayload] = paramsTuple;
181
+ return executeTransaction(ctx, executionPayload);
182
+ },
183
+
184
+ /**
185
+ * Handles the "aztec_wmSimulateTx" JSON-RPC method.
186
+ * This WalletMesh-specific method takes an {@link ExecutionPayload} and simulates
187
+ * the transaction, returning the {@link TxSimulationResult}.
188
+ *
189
+ * @param ctx - The {@link AztecHandlerContext}.
190
+ * @param paramsTuple - A tuple containing the {@link ExecutionPayload}.
191
+ * Defined by {@link AztecWalletMethodMap.aztec_wmSimulateTx.params}.
192
+ * @param paramsTuple.0 - The {@link ExecutionPayload} to simulate.
193
+ * @returns A promise that resolves to the {@link TxSimulationResult}.
194
+ * Type defined by {@link AztecWalletMethodMap.aztec_wmSimulateTx.result}.
195
+ */
196
+ aztec_wmSimulateTx: async (
197
+ ctx: AztecHandlerContext,
198
+ paramsTuple: AztecWalletMethodMap['aztec_wmSimulateTx']['params'],
199
+ ): Promise<AztecWalletMethodMap['aztec_wmSimulateTx']['result']> => {
200
+ const [executionPayload] = paramsTuple;
201
+ return await simulateTransaction(ctx, executionPayload);
202
+ },
203
+
204
+ /**
205
+ * Handles the "aztec_wmDeployContract" JSON-RPC method.
206
+ * This WalletMesh-specific method deploys a new contract using its {@link ContractArtifact}
207
+ * and constructor arguments. It manages the deployment transaction lifecycle, including
208
+ * computing the contract address, proving, and sending the deployment transaction.
209
+ *
210
+ * Fee configuration is determined internally by the `getFeeOptions` helper.
211
+ *
212
+ * @param ctx - The {@link AztecHandlerContext}.
213
+ * @param paramsTuple - A tuple containing the deployment parameters (artifact, args, constructorName).
214
+ * Defined by {@link AztecWalletMethodMap.aztec_wmDeployContract.params}.
215
+ * @param paramsTuple.0.artifact - The {@link ContractArtifact} of the contract to deploy.
216
+ * @param paramsTuple.0.args - An array of arguments for the contract's constructor.
217
+ * @param paramsTuple.0.constructorName - Optional name of the constructor function if the artifact has multiple.
218
+ * @returns A promise that resolves to an object containing the `txHash` ({@link TxHash})
219
+ * of the deployment transaction and the `contractAddress` ({@link AztecAddress})
220
+ * of the newly deployed contract.
221
+ * Type defined by {@link AztecWalletMethodMap.aztec_wmDeployContract.result}.
222
+ */
223
+ aztec_wmDeployContract: async (
224
+ ctx: AztecHandlerContext,
225
+ paramsTuple: AztecWalletMethodMap['aztec_wmDeployContract']['params'],
226
+ ): Promise<AztecWalletMethodMap['aztec_wmDeployContract']['result']> => {
227
+ const [params] = paramsTuple;
228
+ const { artifact, args, constructorName } = params;
229
+
230
+ logger.debug(`aztec_wmDeployContract: deploying ${artifact.name} with ${args.length} args`);
231
+
232
+ try {
233
+ // Create deployment method using the server-side wallet
234
+ const deployMethod = Contract.deploy(ctx.wallet, artifact, args, constructorName);
235
+
236
+ const contractAddressSalt = Fr.random();
237
+ const txOpts = await getTxOptions(ctx);
238
+ const opts: DeployOptions = {
239
+ contractAddressSalt,
240
+ fee: await getFeeOptions(ctx),
241
+ };
242
+ if (txOpts.nonce) {
243
+ opts.nonce = txOpts.nonce;
244
+ }
245
+ if (txOpts.cancellable) {
246
+ opts.cancellable = txOpts.cancellable;
247
+ }
248
+
249
+ // Compute the contract address
250
+ const { address: contractAddress } = await deployMethod.getInstance(opts);
251
+ logger.debug(`Computed contract address: ${contractAddress.toString()}`);
252
+
253
+ const deployProvenTx = await deployMethod.prove(opts);
254
+
255
+ const deploySentTx = await deployProvenTx.send();
256
+ const txHash = await deploySentTx.getTxHash();
257
+ logger.debug(`Contract deployed, hash: ${txHash.toString()}`);
258
+
259
+ return {
260
+ txHash,
261
+ contractAddress,
262
+ };
263
+ } catch (error) {
264
+ logger.error(`Contract deployment failed for ${artifact.name}:`, error);
265
+ throw error;
266
+ }
267
+ },
268
+ };
269
+ }