@walletmesh/aztec-rpc-wallet 0.3.0 → 0.4.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.
- package/CHANGELOG.md +26 -0
- package/README.md +290 -228
- package/dist/.tsbuildinfo +1 -1
- package/dist/client/aztec-dapp-wallet.d.ts +401 -0
- package/dist/client/aztec-dapp-wallet.d.ts.map +1 -0
- package/dist/client/aztec-dapp-wallet.js +705 -0
- package/dist/client/aztec-router-provider.d.ts +58 -0
- package/dist/client/aztec-router-provider.d.ts.map +1 -0
- package/dist/client/aztec-router-provider.js +62 -0
- package/dist/client/helpers.d.ts +44 -0
- package/dist/client/helpers.d.ts.map +1 -0
- package/dist/client/helpers.js +79 -0
- package/dist/client/register-serializers.d.ts +41 -0
- package/dist/client/register-serializers.d.ts.map +1 -0
- package/dist/client/register-serializers.js +97 -0
- package/dist/contractArtifactCache.d.ts +49 -32
- package/dist/contractArtifactCache.d.ts.map +1 -1
- package/dist/contractArtifactCache.js +47 -34
- package/dist/errors.d.ts +50 -8
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +50 -10
- package/dist/index.d.ts +53 -40
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +52 -17
- package/dist/types.d.ts +345 -268
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +10 -8
- package/dist/wallet/create-node.d.ts +73 -0
- package/dist/wallet/create-node.d.ts.map +1 -0
- package/dist/wallet/create-node.js +99 -0
- package/dist/wallet/handlers/account.d.ts +67 -0
- package/dist/wallet/handlers/account.d.ts.map +1 -0
- package/dist/wallet/handlers/account.js +85 -0
- package/dist/wallet/handlers/contract-interaction.d.ts +77 -0
- package/dist/wallet/handlers/contract-interaction.d.ts.map +1 -0
- package/dist/wallet/handlers/contract-interaction.js +219 -0
- package/dist/wallet/handlers/contract.d.ts +96 -0
- package/dist/wallet/handlers/contract.d.ts.map +1 -0
- package/dist/wallet/handlers/contract.js +146 -0
- package/dist/wallet/handlers/event.d.ts +62 -0
- package/dist/wallet/handlers/event.d.ts.map +1 -0
- package/dist/wallet/handlers/event.js +85 -0
- package/dist/wallet/handlers/index.d.ts +88 -0
- package/dist/wallet/handlers/index.d.ts.map +1 -0
- package/dist/wallet/handlers/index.js +47 -0
- package/dist/wallet/handlers/node.d.ts +117 -0
- package/dist/wallet/handlers/node.d.ts.map +1 -0
- package/dist/wallet/handlers/node.js +196 -0
- package/dist/wallet/handlers/senders.d.ts +70 -0
- package/dist/wallet/handlers/senders.d.ts.map +1 -0
- package/dist/wallet/handlers/senders.js +92 -0
- package/dist/wallet/handlers/transaction.d.ts +123 -0
- package/dist/wallet/handlers/transaction.d.ts.map +1 -0
- package/dist/wallet/handlers/transaction.js +191 -0
- package/dist/wallet/serializers.d.ts +75 -0
- package/dist/wallet/serializers.d.ts.map +1 -0
- package/dist/wallet/serializers.js +501 -0
- package/docs/README.md +290 -229
- package/docs/classes/AztecDappWallet.md +1304 -0
- package/docs/classes/AztecRouterProvider.md +1058 -0
- package/docs/classes/AztecWalletError.md +124 -47
- package/docs/classes/ContractArtifactCache.md +48 -31
- package/docs/functions/connectAztec.md +62 -0
- package/docs/functions/createAztecWallet.md +46 -0
- package/docs/functions/createAztecWalletNode.md +96 -0
- package/docs/functions/registerAztecSerializers.md +61 -0
- package/docs/functions/registerWalletAztecSerializers.md +39 -0
- package/docs/globals.md +16 -14
- package/docs/interfaces/AztecHandlerContext.md +54 -0
- package/docs/interfaces/AztecWalletContext.md +50 -0
- package/docs/interfaces/AztecWalletMethodMap.md +471 -470
- package/docs/type-aliases/AztecChainId.md +16 -3
- package/docs/variables/ALL_AZTEC_METHODS.md +20 -0
- package/docs/variables/AztecWalletErrorMap.md +9 -4
- package/docs/variables/AztecWalletSerializer.md +45 -0
- package/package.json +9 -9
- package/src/client/aztec-dapp-wallet.test.ts +628 -0
- package/src/client/aztec-dapp-wallet.ts +879 -0
- package/src/client/aztec-router-provider.test.ts +235 -0
- package/src/client/aztec-router-provider.ts +64 -0
- package/src/client/helpers.test.ts +187 -0
- package/src/client/helpers.ts +91 -0
- package/src/client/register-serializers.ts +108 -0
- package/src/contractArtifactCache.test.ts +21 -10
- package/src/contractArtifactCache.ts +54 -35
- package/src/errors.ts +58 -10
- package/src/index.test.ts +2 -6
- package/src/index.ts +73 -37
- package/src/types.ts +379 -217
- package/src/wallet/create-node.test.ts +332 -0
- package/src/wallet/create-node.ts +120 -0
- package/src/wallet/handlers/account.test.ts +172 -0
- package/src/wallet/handlers/account.ts +99 -0
- package/src/wallet/handlers/contract-interaction.test.ts +248 -0
- package/src/wallet/handlers/contract-interaction.ts +269 -0
- package/src/wallet/handlers/contract.test.ts +245 -0
- package/src/wallet/handlers/contract.ts +174 -0
- package/src/wallet/handlers/event.test.ts +216 -0
- package/src/wallet/handlers/event.ts +99 -0
- package/src/wallet/handlers/index.ts +84 -0
- package/src/wallet/handlers/node.test.ts +304 -0
- package/src/wallet/handlers/node.ts +230 -0
- package/src/wallet/handlers/senders.test.ts +172 -0
- package/src/wallet/handlers/senders.ts +106 -0
- package/src/wallet/handlers/transaction.test.ts +371 -0
- package/src/wallet/handlers/transaction.ts +239 -0
- package/src/wallet/serializers.test.ts +253 -0
- package/src/wallet/serializers.ts +586 -0
- package/typedoc.json +23 -1
- package/dist/aztecRemoteWallet.d.ts +0 -70
- package/dist/aztecRemoteWallet.d.ts.map +0 -1
- package/dist/aztecRemoteWallet.js +0 -335
- package/dist/chainProvider.d.ts +0 -56
- package/dist/chainProvider.d.ts.map +0 -1
- package/dist/chainProvider.js +0 -98
- package/dist/handlers/aztecAccountWallet.d.ts +0 -4
- package/dist/handlers/aztecAccountWallet.d.ts.map +0 -1
- package/dist/handlers/aztecAccountWallet.js +0 -296
- package/dist/handlers/transactions.d.ts +0 -21
- package/dist/handlers/transactions.d.ts.map +0 -1
- package/dist/handlers/transactions.js +0 -98
- package/dist/handlers.d.ts +0 -27
- package/dist/handlers.d.ts.map +0 -1
- package/dist/handlers.js +0 -55
- package/dist/provider.d.ts +0 -105
- package/dist/provider.d.ts.map +0 -1
- package/dist/provider.js +0 -160
- package/dist/serializers/account.d.ts +0 -164
- package/dist/serializers/account.d.ts.map +0 -1
- package/dist/serializers/account.js +0 -244
- package/dist/serializers/contract.d.ts +0 -62
- package/dist/serializers/contract.d.ts.map +0 -1
- package/dist/serializers/contract.js +0 -130
- package/dist/serializers/index.d.ts +0 -21
- package/dist/serializers/index.d.ts.map +0 -1
- package/dist/serializers/index.js +0 -154
- package/dist/serializers/log.d.ts +0 -66
- package/dist/serializers/log.d.ts.map +0 -1
- package/dist/serializers/log.js +0 -222
- package/dist/serializers/note.d.ts +0 -124
- package/dist/serializers/note.d.ts.map +0 -1
- package/dist/serializers/note.js +0 -208
- package/dist/serializers/transaction.d.ts +0 -99
- package/dist/serializers/transaction.d.ts.map +0 -1
- package/dist/serializers/transaction.js +0 -275
- package/dist/wallet.d.ts +0 -62
- package/dist/wallet.d.ts.map +0 -1
- package/dist/wallet.js +0 -77
- package/docs/classes/AztecChainProvider.md +0 -553
- package/docs/classes/AztecChainWallet.md +0 -409
- package/docs/classes/AztecProvider.md +0 -1112
- package/docs/interfaces/AztecWalletBaseMethodMap.md +0 -135
- package/docs/interfaces/AztecWalletEventMap.md +0 -17
- package/docs/type-aliases/AztecChainWalletMiddleware.md +0 -13
- package/docs/type-aliases/AztecWalletContext.md +0 -29
- package/docs/type-aliases/AztecWalletMethodHandler.md +0 -37
- package/docs/type-aliases/AztecWalletMiddleware.md +0 -13
- package/docs/type-aliases/AztecWalletRouterClient.md +0 -13
- package/docs/type-aliases/TransactionFunctionCall.md +0 -33
- package/docs/type-aliases/TransactionParams.md +0 -27
- package/src/aztecRemoteWallet.test.ts +0 -504
- package/src/aztecRemoteWallet.ts +0 -467
- package/src/chainProvider.test.ts +0 -401
- package/src/chainProvider.ts +0 -116
- package/src/handlers/aztecAccountWallet.test.ts +0 -649
- package/src/handlers/aztecAccountWallet.ts +0 -532
- package/src/handlers/transactions.ts +0 -124
- package/src/handlers.test.ts +0 -270
- package/src/handlers.ts +0 -70
- package/src/provider.test.ts +0 -274
- package/src/provider.ts +0 -189
- package/src/serializers/account.test.ts +0 -125
- package/src/serializers/account.ts +0 -301
- package/src/serializers/contract.test.ts +0 -24
- package/src/serializers/contract.ts +0 -183
- package/src/serializers/index.test.ts +0 -136
- package/src/serializers/index.ts +0 -191
- package/src/serializers/log.test.ts +0 -286
- package/src/serializers/log.ts +0 -292
- package/src/serializers/note.test.ts +0 -125
- package/src/serializers/note.ts +0 -250
- package/src/serializers/transaction.test.ts +0 -320
- package/src/serializers/transaction.ts +0 -409
- package/src/wallet.test.ts +0 -275
- 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
|
+
}
|