@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.
- package/CHANGELOG.md +7 -0
- package/LICENSE +201 -0
- package/README.md +260 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/aztecRemoteWallet.d.ts +73 -0
- package/dist/aztecRemoteWallet.d.ts.map +1 -0
- package/dist/aztecRemoteWallet.js +354 -0
- package/dist/chainProvider.d.ts +56 -0
- package/dist/chainProvider.d.ts.map +1 -0
- package/dist/chainProvider.js +98 -0
- package/dist/contractArtifactCache.d.ts +50 -0
- package/dist/contractArtifactCache.d.ts.map +1 -0
- package/dist/contractArtifactCache.js +66 -0
- package/dist/errors.d.ts +50 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +62 -0
- package/dist/handlers/aztecAccountWallet.d.ts +4 -0
- package/dist/handlers/aztecAccountWallet.d.ts.map +1 -0
- package/dist/handlers/aztecAccountWallet.js +329 -0
- package/dist/handlers/transactions.d.ts +21 -0
- package/dist/handlers/transactions.d.ts.map +1 -0
- package/dist/handlers/transactions.js +90 -0
- package/dist/handlers.d.ts +27 -0
- package/dist/handlers.d.ts.map +1 -0
- package/dist/handlers.js +55 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/provider.d.ts +105 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +160 -0
- package/dist/serializers/account.d.ts +167 -0
- package/dist/serializers/account.d.ts.map +1 -0
- package/dist/serializers/account.js +245 -0
- package/dist/serializers/contract-utils.d.ts +40 -0
- package/dist/serializers/contract-utils.d.ts.map +1 -0
- package/dist/serializers/contract-utils.js +102 -0
- package/dist/serializers/contract.d.ts +168 -0
- package/dist/serializers/contract.d.ts.map +1 -0
- package/dist/serializers/contract.js +268 -0
- package/dist/serializers/core.d.ts +110 -0
- package/dist/serializers/core.d.ts.map +1 -0
- package/dist/serializers/core.js +130 -0
- package/dist/serializers/index.d.ts +28 -0
- package/dist/serializers/index.d.ts.map +1 -0
- package/dist/serializers/index.js +159 -0
- package/dist/serializers/log.d.ts +113 -0
- package/dist/serializers/log.d.ts.map +1 -0
- package/dist/serializers/log.js +231 -0
- package/dist/serializers/note.d.ts +127 -0
- package/dist/serializers/note.d.ts.map +1 -0
- package/dist/serializers/note.js +182 -0
- package/dist/serializers/transaction-utils.d.ts +107 -0
- package/dist/serializers/transaction-utils.d.ts.map +1 -0
- package/dist/serializers/transaction-utils.js +130 -0
- package/dist/serializers/transaction.d.ts +103 -0
- package/dist/serializers/transaction.d.ts.map +1 -0
- package/dist/serializers/transaction.js +238 -0
- package/dist/serializers/types.d.ts +49 -0
- package/dist/serializers/types.d.ts.map +1 -0
- package/dist/serializers/types.js +22 -0
- package/dist/types.d.ts +391 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/wallet.d.ts +62 -0
- package/dist/wallet.d.ts.map +1 -0
- package/dist/wallet.js +77 -0
- package/package.json +44 -0
- package/src/aztecRemoteWallet.test.ts +542 -0
- package/src/aztecRemoteWallet.ts +484 -0
- package/src/chainProvider.test.ts +322 -0
- package/src/chainProvider.ts +122 -0
- package/src/contractArtifactCache.test.ts +126 -0
- package/src/contractArtifactCache.ts +75 -0
- package/src/errors.ts +71 -0
- package/src/handlers/aztecAccountWallet.test.ts +720 -0
- package/src/handlers/aztecAccountWallet.ts +593 -0
- package/src/handlers/transactions.ts +110 -0
- package/src/handlers.test.ts +270 -0
- package/src/handlers.ts +70 -0
- package/src/index.test.ts +23 -0
- package/src/index.ts +64 -0
- package/src/provider.test.ts +276 -0
- package/src/provider.ts +189 -0
- package/src/serializers/account.test.ts +125 -0
- package/src/serializers/account.ts +319 -0
- package/src/serializers/contract-utils.ts +104 -0
- package/src/serializers/contract.test.ts +162 -0
- package/src/serializers/contract.ts +350 -0
- package/src/serializers/core.test.ts +56 -0
- package/src/serializers/core.ts +141 -0
- package/src/serializers/index.test.ts +122 -0
- package/src/serializers/index.ts +213 -0
- package/src/serializers/log.test.ts +119 -0
- package/src/serializers/log.ts +283 -0
- package/src/serializers/note.test.ts +100 -0
- package/src/serializers/note.ts +227 -0
- package/src/serializers/transaction-utils.ts +237 -0
- package/src/serializers/transaction.test.ts +153 -0
- package/src/serializers/transaction.ts +342 -0
- package/src/serializers/types.ts +58 -0
- package/src/types.ts +295 -0
- package/src/wallet.test.ts +275 -0
- package/src/wallet.ts +94 -0
- package/tsconfig.build.json +6 -0
- package/tsconfig.json +11 -0
- package/typedoc.json +15 -0
- package/vitest.config.ts +10 -0
@@ -0,0 +1,322 @@
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
2
|
+
import type { JSONRPCTransport, JSONRPCRequest } from '@walletmesh/jsonrpc';
|
3
|
+
import { AztecChainProvider } from './chainProvider.js';
|
4
|
+
import { AztecWalletError } from './errors.js';
|
5
|
+
import type { ContractInstanceWithAddress, ContractArtifact, AztecAddress } from '@aztec/aztec.js';
|
6
|
+
import type { AztecWalletMethodMap } from './types.js';
|
7
|
+
|
8
|
+
const createMockTransport = () => ({
|
9
|
+
send: vi.fn().mockImplementation(() => Promise.resolve()),
|
10
|
+
});
|
11
|
+
|
12
|
+
describe('AztecChainProvider', () => {
|
13
|
+
let provider: AztecChainProvider;
|
14
|
+
let mockTransport: ReturnType<typeof createMockTransport>;
|
15
|
+
|
16
|
+
beforeEach(() => {
|
17
|
+
mockTransport = createMockTransport();
|
18
|
+
provider = new AztecChainProvider(mockTransport);
|
19
|
+
});
|
20
|
+
|
21
|
+
afterEach(() => {
|
22
|
+
vi.clearAllMocks();
|
23
|
+
});
|
24
|
+
|
25
|
+
describe('getAccount', () => {
|
26
|
+
it('returns account address on success', async () => {
|
27
|
+
const expectedAddress = '0x1234567890abcdef';
|
28
|
+
const promise = provider.getAccount();
|
29
|
+
|
30
|
+
// Get the request ID from the sent message
|
31
|
+
const [[sentRequest]] = mockTransport.send.mock.calls as [
|
32
|
+
[JSONRPCRequest<AztecWalletMethodMap, 'aztec_getAccount'>],
|
33
|
+
];
|
34
|
+
expect(sentRequest).toEqual({
|
35
|
+
jsonrpc: '2.0',
|
36
|
+
id: expect.any(String),
|
37
|
+
method: 'aztec_getAccount',
|
38
|
+
});
|
39
|
+
|
40
|
+
// Simulate response
|
41
|
+
await provider.receiveMessage({
|
42
|
+
jsonrpc: '2.0',
|
43
|
+
result: expectedAddress,
|
44
|
+
id: sentRequest.id,
|
45
|
+
});
|
46
|
+
|
47
|
+
const result = await promise;
|
48
|
+
expect(result).toBe(expectedAddress);
|
49
|
+
});
|
50
|
+
|
51
|
+
it('throws on invalid response', async () => {
|
52
|
+
const promise = provider.getAccount();
|
53
|
+
|
54
|
+
// Get the request ID
|
55
|
+
const [[sentRequest]] = mockTransport.send.mock.calls as [
|
56
|
+
[JSONRPCRequest<AztecWalletMethodMap, 'aztec_getAccount'>],
|
57
|
+
];
|
58
|
+
|
59
|
+
// Simulate error response
|
60
|
+
await provider.receiveMessage({
|
61
|
+
jsonrpc: '2.0',
|
62
|
+
result: null,
|
63
|
+
id: sentRequest.id,
|
64
|
+
});
|
65
|
+
|
66
|
+
await expect(promise).rejects.toThrow(AztecWalletError);
|
67
|
+
});
|
68
|
+
});
|
69
|
+
|
70
|
+
describe('sendTransaction', () => {
|
71
|
+
const txParams = {
|
72
|
+
functionCalls: [
|
73
|
+
{
|
74
|
+
contractAddress: '0x1234',
|
75
|
+
functionName: 'transfer',
|
76
|
+
args: ['0x5678', 100],
|
77
|
+
},
|
78
|
+
],
|
79
|
+
};
|
80
|
+
|
81
|
+
it('returns transaction hash on success', async () => {
|
82
|
+
const expectedHash = '0xabcd';
|
83
|
+
const promise = provider.sendTransaction(txParams);
|
84
|
+
|
85
|
+
// Get the request ID
|
86
|
+
const [[sentRequest]] = mockTransport.send.mock.calls as [
|
87
|
+
[JSONRPCRequest<AztecWalletMethodMap, 'aztec_sendTransaction'>],
|
88
|
+
];
|
89
|
+
expect(sentRequest).toEqual({
|
90
|
+
jsonrpc: '2.0',
|
91
|
+
id: expect.any(String),
|
92
|
+
method: 'aztec_sendTransaction',
|
93
|
+
params: txParams,
|
94
|
+
});
|
95
|
+
|
96
|
+
// Simulate response
|
97
|
+
await provider.receiveMessage({
|
98
|
+
jsonrpc: '2.0',
|
99
|
+
result: expectedHash,
|
100
|
+
id: sentRequest.id,
|
101
|
+
});
|
102
|
+
|
103
|
+
const result = await promise;
|
104
|
+
expect(result).toBe(expectedHash);
|
105
|
+
});
|
106
|
+
|
107
|
+
it('throws on invalid response', async () => {
|
108
|
+
const promise = provider.sendTransaction(txParams);
|
109
|
+
|
110
|
+
// Get the request ID
|
111
|
+
const [[sentRequest]] = mockTransport.send.mock.calls as [
|
112
|
+
[JSONRPCRequest<AztecWalletMethodMap, 'aztec_sendTransaction'>],
|
113
|
+
];
|
114
|
+
|
115
|
+
// Simulate error response
|
116
|
+
await provider.receiveMessage({
|
117
|
+
jsonrpc: '2.0',
|
118
|
+
result: null,
|
119
|
+
id: sentRequest.id,
|
120
|
+
});
|
121
|
+
|
122
|
+
await expect(promise).rejects.toThrow(AztecWalletError);
|
123
|
+
});
|
124
|
+
});
|
125
|
+
|
126
|
+
describe('simulateTransaction', () => {
|
127
|
+
const txParams = {
|
128
|
+
contractAddress: '0x1234',
|
129
|
+
functionName: 'transfer',
|
130
|
+
args: ['0x5678', 100],
|
131
|
+
};
|
132
|
+
|
133
|
+
it('returns simulation result on success', async () => {
|
134
|
+
const expectedResult = { success: true, data: 'test' };
|
135
|
+
const promise = provider.simulateTransaction(txParams);
|
136
|
+
|
137
|
+
// Get the request ID
|
138
|
+
const [[sentRequest]] = mockTransport.send.mock.calls as [
|
139
|
+
[JSONRPCRequest<AztecWalletMethodMap, 'aztec_simulateTransaction'>],
|
140
|
+
];
|
141
|
+
expect(sentRequest).toEqual({
|
142
|
+
jsonrpc: '2.0',
|
143
|
+
id: expect.any(String),
|
144
|
+
method: 'aztec_simulateTransaction',
|
145
|
+
params: txParams,
|
146
|
+
});
|
147
|
+
|
148
|
+
// Simulate response
|
149
|
+
await provider.receiveMessage({
|
150
|
+
jsonrpc: '2.0',
|
151
|
+
result: expectedResult,
|
152
|
+
id: sentRequest.id,
|
153
|
+
});
|
154
|
+
|
155
|
+
const result = await promise;
|
156
|
+
expect(result).toEqual(expectedResult);
|
157
|
+
});
|
158
|
+
|
159
|
+
it('throws on invalid response', async () => {
|
160
|
+
const promise = provider.simulateTransaction(txParams);
|
161
|
+
|
162
|
+
// Get the request ID
|
163
|
+
const [[sentRequest]] = mockTransport.send.mock.calls as [
|
164
|
+
[JSONRPCRequest<AztecWalletMethodMap, 'aztec_simulateTransaction'>],
|
165
|
+
];
|
166
|
+
|
167
|
+
// Simulate error response
|
168
|
+
await provider.receiveMessage({
|
169
|
+
jsonrpc: '2.0',
|
170
|
+
result: null,
|
171
|
+
id: sentRequest.id,
|
172
|
+
});
|
173
|
+
|
174
|
+
await expect(promise).rejects.toThrow(AztecWalletError);
|
175
|
+
});
|
176
|
+
});
|
177
|
+
|
178
|
+
describe('registerContract', () => {
|
179
|
+
const contractParams = {
|
180
|
+
instance: { address: '0x1234' as unknown as AztecAddress } as ContractInstanceWithAddress,
|
181
|
+
artifact: { name: 'TestContract' } as ContractArtifact,
|
182
|
+
};
|
183
|
+
|
184
|
+
it('succeeds on valid response', async () => {
|
185
|
+
const promise = provider.registerContract(contractParams);
|
186
|
+
|
187
|
+
// Get the request ID
|
188
|
+
const [[sentRequest]] = mockTransport.send.mock.calls as [
|
189
|
+
[JSONRPCRequest<AztecWalletMethodMap, 'aztec_registerContract'>],
|
190
|
+
];
|
191
|
+
expect(sentRequest).toEqual({
|
192
|
+
jsonrpc: '2.0',
|
193
|
+
id: expect.any(String),
|
194
|
+
method: 'aztec_registerContract',
|
195
|
+
params: contractParams,
|
196
|
+
});
|
197
|
+
|
198
|
+
// Simulate response
|
199
|
+
await provider.receiveMessage({
|
200
|
+
jsonrpc: '2.0',
|
201
|
+
result: true,
|
202
|
+
id: sentRequest.id,
|
203
|
+
});
|
204
|
+
|
205
|
+
await expect(promise).resolves.toBeUndefined();
|
206
|
+
});
|
207
|
+
|
208
|
+
it('throws on invalid response', async () => {
|
209
|
+
const promise = provider.registerContract(contractParams);
|
210
|
+
|
211
|
+
// Get the request ID
|
212
|
+
const [[sentRequest]] = mockTransport.send.mock.calls as [
|
213
|
+
[JSONRPCRequest<AztecWalletMethodMap, 'aztec_registerContract'>],
|
214
|
+
];
|
215
|
+
|
216
|
+
// Simulate error response
|
217
|
+
await provider.receiveMessage({
|
218
|
+
jsonrpc: '2.0',
|
219
|
+
result: false,
|
220
|
+
id: sentRequest.id,
|
221
|
+
});
|
222
|
+
|
223
|
+
await expect(promise).rejects.toThrow(AztecWalletError);
|
224
|
+
});
|
225
|
+
});
|
226
|
+
|
227
|
+
describe('registerContractClass', () => {
|
228
|
+
const classParams = {
|
229
|
+
artifact: { name: 'TestContract' } as ContractArtifact,
|
230
|
+
};
|
231
|
+
|
232
|
+
it('succeeds on valid response', async () => {
|
233
|
+
const promise = provider.registerContractClass(classParams);
|
234
|
+
|
235
|
+
// Get the request ID
|
236
|
+
const [[sentRequest]] = mockTransport.send.mock.calls as [
|
237
|
+
[JSONRPCRequest<AztecWalletMethodMap, 'aztec_registerContractClass'>],
|
238
|
+
];
|
239
|
+
expect(sentRequest).toEqual({
|
240
|
+
jsonrpc: '2.0',
|
241
|
+
id: expect.any(String),
|
242
|
+
method: 'aztec_registerContractClass',
|
243
|
+
params: classParams,
|
244
|
+
});
|
245
|
+
|
246
|
+
// Simulate response
|
247
|
+
await provider.receiveMessage({
|
248
|
+
jsonrpc: '2.0',
|
249
|
+
result: true,
|
250
|
+
id: sentRequest.id,
|
251
|
+
});
|
252
|
+
|
253
|
+
await expect(promise).resolves.toBeUndefined();
|
254
|
+
});
|
255
|
+
|
256
|
+
it('throws on invalid response', async () => {
|
257
|
+
const promise = provider.registerContractClass(classParams);
|
258
|
+
|
259
|
+
// Get the request ID
|
260
|
+
const [[sentRequest]] = mockTransport.send.mock.calls as [
|
261
|
+
[JSONRPCRequest<AztecWalletMethodMap, 'aztec_registerContractClass'>],
|
262
|
+
];
|
263
|
+
|
264
|
+
// Simulate error response
|
265
|
+
await provider.receiveMessage({
|
266
|
+
jsonrpc: '2.0',
|
267
|
+
result: false,
|
268
|
+
id: sentRequest.id,
|
269
|
+
});
|
270
|
+
|
271
|
+
await expect(promise).rejects.toThrow(AztecWalletError);
|
272
|
+
});
|
273
|
+
});
|
274
|
+
|
275
|
+
describe('registerSender', () => {
|
276
|
+
const senderParams = {
|
277
|
+
sender: '0x1234' as unknown as AztecAddress,
|
278
|
+
};
|
279
|
+
|
280
|
+
it('succeeds on valid response', async () => {
|
281
|
+
const promise = provider.registerSender(senderParams);
|
282
|
+
|
283
|
+
// Get the request ID
|
284
|
+
const [[sentRequest]] = mockTransport.send.mock.calls as [
|
285
|
+
[JSONRPCRequest<AztecWalletMethodMap, 'aztec_registerSender'>],
|
286
|
+
];
|
287
|
+
expect(sentRequest).toEqual({
|
288
|
+
jsonrpc: '2.0',
|
289
|
+
id: expect.any(String),
|
290
|
+
method: 'aztec_registerSender',
|
291
|
+
params: senderParams,
|
292
|
+
});
|
293
|
+
|
294
|
+
// Simulate response
|
295
|
+
await provider.receiveMessage({
|
296
|
+
jsonrpc: '2.0',
|
297
|
+
result: '0x1234',
|
298
|
+
id: sentRequest.id,
|
299
|
+
});
|
300
|
+
|
301
|
+
await expect(promise).resolves.toBeUndefined();
|
302
|
+
});
|
303
|
+
|
304
|
+
it('throws on invalid response', async () => {
|
305
|
+
const promise = provider.registerSender(senderParams);
|
306
|
+
|
307
|
+
// Get the request ID
|
308
|
+
const [[sentRequest]] = mockTransport.send.mock.calls as [
|
309
|
+
[JSONRPCRequest<AztecWalletMethodMap, 'aztec_registerSender'>],
|
310
|
+
];
|
311
|
+
|
312
|
+
// Simulate error response
|
313
|
+
await provider.receiveMessage({
|
314
|
+
jsonrpc: '2.0',
|
315
|
+
result: null,
|
316
|
+
id: sentRequest.id,
|
317
|
+
});
|
318
|
+
|
319
|
+
await expect(promise).rejects.toThrow(AztecWalletError);
|
320
|
+
});
|
321
|
+
});
|
322
|
+
});
|
@@ -0,0 +1,122 @@
|
|
1
|
+
import { JSONRPCNode } from '@walletmesh/jsonrpc';
|
2
|
+
import type { JSONRPCTransport } from '@walletmesh/jsonrpc';
|
3
|
+
import { AztecWalletError, AztecWalletErrorType } from './errors.js';
|
4
|
+
import type {
|
5
|
+
AztecChainId,
|
6
|
+
AztecWalletMethodMap,
|
7
|
+
TransactionParams,
|
8
|
+
TransactionFunctionCall,
|
9
|
+
} from './types.js';
|
10
|
+
import type { ContractInstanceWithAddress, ContractArtifact } from '@aztec/aztec.js';
|
11
|
+
|
12
|
+
/**
|
13
|
+
* Provider for directly interacting with an Aztec chain wallet.
|
14
|
+
* This is a minimal implementation that supports core Aztec operations
|
15
|
+
* without the complexity of multi-chain routing.
|
16
|
+
*/
|
17
|
+
export class AztecChainProvider extends JSONRPCNode<AztecWalletMethodMap> {
|
18
|
+
protected async makeRequest<M extends keyof AztecWalletMethodMap>(
|
19
|
+
method: M,
|
20
|
+
params?: AztecWalletMethodMap[M]['params'],
|
21
|
+
): Promise<AztecWalletMethodMap[M]['result']> {
|
22
|
+
try {
|
23
|
+
return await this.callMethod(method, params);
|
24
|
+
} catch (error) {
|
25
|
+
throw new AztecWalletError(
|
26
|
+
AztecWalletErrorType.invalidResponse,
|
27
|
+
error instanceof Error ? error.message : 'Invalid response received',
|
28
|
+
);
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
public async connect(): Promise<boolean> {
|
33
|
+
try {
|
34
|
+
await this.makeRequest('aztec_connect');
|
35
|
+
return true;
|
36
|
+
} catch (error) {
|
37
|
+
return false;
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
/**
|
42
|
+
* Gets the account address from the wallet.
|
43
|
+
* @returns The account address as a string
|
44
|
+
* @throws {AztecWalletError} If response is invalid
|
45
|
+
*/
|
46
|
+
public async getAccount(): Promise<string> {
|
47
|
+
const result = await this.makeRequest('aztec_getAccount');
|
48
|
+
if (typeof result !== 'string' || !result) {
|
49
|
+
throw new AztecWalletError(AztecWalletErrorType.invalidResponse, 'Invalid account address returned');
|
50
|
+
}
|
51
|
+
return result;
|
52
|
+
}
|
53
|
+
|
54
|
+
/**
|
55
|
+
* Sends a transaction to the chain.
|
56
|
+
* @param params - Transaction parameters including function calls
|
57
|
+
* @returns Transaction hash
|
58
|
+
* @throws {AztecWalletError} If transaction fails or response invalid
|
59
|
+
*/
|
60
|
+
public async sendTransaction(params: TransactionParams): Promise<string> {
|
61
|
+
const result = await this.makeRequest('aztec_sendTransaction', params);
|
62
|
+
if (typeof result !== 'string' || !result) {
|
63
|
+
throw new AztecWalletError(AztecWalletErrorType.invalidResponse, 'Invalid transaction hash returned');
|
64
|
+
}
|
65
|
+
return result;
|
66
|
+
}
|
67
|
+
|
68
|
+
/**
|
69
|
+
* Simulates a transaction without submitting it.
|
70
|
+
* @param params - Transaction parameters to simulate
|
71
|
+
* @returns Simulation result
|
72
|
+
* @throws {AztecWalletError} If simulation fails
|
73
|
+
*/
|
74
|
+
public async simulateTransaction(params: TransactionFunctionCall): Promise<unknown> {
|
75
|
+
const result = await this.makeRequest('aztec_simulateTransaction', params);
|
76
|
+
if (result === undefined || result === null) {
|
77
|
+
throw new AztecWalletError(AztecWalletErrorType.invalidResponse, 'Invalid simulation result returned');
|
78
|
+
}
|
79
|
+
return result;
|
80
|
+
}
|
81
|
+
|
82
|
+
/**
|
83
|
+
* Registers a contract instance with the wallet.
|
84
|
+
* @param params - Contract registration parameters
|
85
|
+
* @throws {AztecWalletError} If registration fails
|
86
|
+
*/
|
87
|
+
public async registerContract(params: {
|
88
|
+
instance: ContractInstanceWithAddress;
|
89
|
+
artifact?: ContractArtifact;
|
90
|
+
}): Promise<void> {
|
91
|
+
const result = await this.makeRequest('aztec_registerContract', params);
|
92
|
+
if (result !== true) {
|
93
|
+
throw new AztecWalletError(AztecWalletErrorType.invalidResponse, 'Contract registration failed');
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
/**
|
98
|
+
* Registers a contract class with the wallet.
|
99
|
+
* @param params - Contract class registration parameters
|
100
|
+
* @throws {AztecWalletError} If registration fails
|
101
|
+
*/
|
102
|
+
public async registerContractClass(params: {
|
103
|
+
artifact: ContractArtifact;
|
104
|
+
}): Promise<void> {
|
105
|
+
const result = await this.makeRequest('aztec_registerContractClass', params);
|
106
|
+
if (result !== true) {
|
107
|
+
throw new AztecWalletError(AztecWalletErrorType.invalidResponse, 'Contract class registration failed');
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
111
|
+
/**
|
112
|
+
* Registers a sender with the wallet.
|
113
|
+
* @param params - Sender registration parameters
|
114
|
+
* @throws {AztecWalletError} If registration fails
|
115
|
+
*/
|
116
|
+
public async registerSender(params: AztecWalletMethodMap['aztec_registerSender']['params']): Promise<void> {
|
117
|
+
const result = await this.makeRequest('aztec_registerSender', params);
|
118
|
+
if (!result) {
|
119
|
+
throw new AztecWalletError(AztecWalletErrorType.invalidResponse, 'Sender registration failed');
|
120
|
+
}
|
121
|
+
}
|
122
|
+
}
|
@@ -0,0 +1,126 @@
|
|
1
|
+
import { describe, expect, it, vi, beforeEach, type Mock } from 'vitest';
|
2
|
+
import type { AztecAddress, ContractArtifact, ContractClassWithId, Wallet } from '@aztec/aztec.js';
|
3
|
+
import { ContractArtifactCache } from './contractArtifactCache.js';
|
4
|
+
import { AztecWalletError } from './errors.js';
|
5
|
+
|
6
|
+
describe('ContractArtifactCache', () => {
|
7
|
+
let wallet: Wallet;
|
8
|
+
let cache: ContractArtifactCache;
|
9
|
+
let mockContractAddress: AztecAddress;
|
10
|
+
let mockContractClassId: ContractClassWithId;
|
11
|
+
let mockArtifact: ContractArtifact;
|
12
|
+
|
13
|
+
beforeEach(() => {
|
14
|
+
// Mock contract address and class ID
|
15
|
+
// Create a complete mock of AztecAddress
|
16
|
+
mockContractAddress = {
|
17
|
+
toString: () => '0x123',
|
18
|
+
_branding: 'aztec.Address',
|
19
|
+
xCoord: BigInt(0),
|
20
|
+
size: 32,
|
21
|
+
equals: () => false,
|
22
|
+
toBuffer: () => Buffer.from([]),
|
23
|
+
toFields: () => [],
|
24
|
+
toField: () => BigInt(0),
|
25
|
+
toBigInt: () => BigInt(0),
|
26
|
+
isZero: () => false,
|
27
|
+
isValid: () => true,
|
28
|
+
toAddressPoint: () => ({ x: BigInt(0) }),
|
29
|
+
toJSON: () => ({ x: '0' }),
|
30
|
+
[Symbol.for('nodejs.util.inspect.custom')]: () => 'AztecAddress',
|
31
|
+
} as unknown as AztecAddress;
|
32
|
+
|
33
|
+
// Create a complete mock of ContractClassWithId
|
34
|
+
mockContractClassId = {
|
35
|
+
toString: () => '456',
|
36
|
+
id: BigInt(456),
|
37
|
+
version: 1,
|
38
|
+
artifactHash: BigInt(0),
|
39
|
+
privateFunctions: new Map(),
|
40
|
+
publicFunctions: new Map(),
|
41
|
+
packedBytecode: new Uint8Array(),
|
42
|
+
} as unknown as ContractClassWithId;
|
43
|
+
mockArtifact = { name: 'TestContract' } as ContractArtifact;
|
44
|
+
|
45
|
+
// Create mock wallet
|
46
|
+
wallet = {
|
47
|
+
getContractInstance: vi.fn(),
|
48
|
+
getContractArtifact: vi.fn(),
|
49
|
+
} as unknown as Wallet;
|
50
|
+
|
51
|
+
// Initialize cache with mock wallet
|
52
|
+
cache = new ContractArtifactCache(wallet);
|
53
|
+
});
|
54
|
+
|
55
|
+
it('returns cached artifact if available', async () => {
|
56
|
+
// Setup: Pre-populate cache
|
57
|
+
(cache as unknown as { cache: Map<string, ContractArtifact> }).cache.set(
|
58
|
+
mockContractAddress.toString(),
|
59
|
+
mockArtifact,
|
60
|
+
);
|
61
|
+
|
62
|
+
// Test: Get artifact
|
63
|
+
const result = await cache.getContractArtifact(mockContractAddress);
|
64
|
+
|
65
|
+
// Verify: Result is from cache, wallet methods not called
|
66
|
+
expect(result).toBe(mockArtifact);
|
67
|
+
expect(wallet.getContractInstance).not.toHaveBeenCalled();
|
68
|
+
expect(wallet.getContractArtifact).not.toHaveBeenCalled();
|
69
|
+
});
|
70
|
+
|
71
|
+
it('fetches and caches artifact on cache miss', async () => {
|
72
|
+
// Setup: Configure wallet mocks
|
73
|
+
(wallet.getContractInstance as Mock).mockResolvedValue({ contractClassId: mockContractClassId });
|
74
|
+
(wallet.getContractArtifact as Mock).mockResolvedValue(mockArtifact);
|
75
|
+
|
76
|
+
// Test: Get artifact
|
77
|
+
const result = await cache.getContractArtifact(mockContractAddress);
|
78
|
+
|
79
|
+
// Verify: Correct methods called and result cached
|
80
|
+
expect(wallet.getContractInstance).toHaveBeenCalledWith(mockContractAddress);
|
81
|
+
expect(wallet.getContractArtifact).toHaveBeenCalledWith(mockContractClassId);
|
82
|
+
expect(result).toBe(mockArtifact);
|
83
|
+
|
84
|
+
// Verify: Result was cached
|
85
|
+
expect(
|
86
|
+
(cache as unknown as { cache: Map<string, ContractArtifact> }).cache.get(
|
87
|
+
mockContractAddress.toString(),
|
88
|
+
),
|
89
|
+
).toBe(mockArtifact);
|
90
|
+
});
|
91
|
+
|
92
|
+
it('throws error if contract instance not found', async () => {
|
93
|
+
// Setup: Mock contract instance not found
|
94
|
+
(wallet.getContractInstance as Mock).mockResolvedValue(null);
|
95
|
+
|
96
|
+
// Test & Verify: Expect error
|
97
|
+
await expect(cache.getContractArtifact(mockContractAddress)).rejects.toThrow(
|
98
|
+
new AztecWalletError('contractInstanceNotRegistered', mockContractAddress.toString()),
|
99
|
+
);
|
100
|
+
|
101
|
+
// Verify: Nothing cached
|
102
|
+
expect(
|
103
|
+
(cache as unknown as { cache: Map<string, ContractArtifact> }).cache.get(
|
104
|
+
mockContractAddress.toString(),
|
105
|
+
),
|
106
|
+
).toBeUndefined();
|
107
|
+
});
|
108
|
+
|
109
|
+
it('throws error if contract artifact not found', async () => {
|
110
|
+
// Setup: Mock contract instance found but artifact missing
|
111
|
+
(wallet.getContractInstance as Mock).mockResolvedValue({ contractClassId: mockContractClassId });
|
112
|
+
(wallet.getContractArtifact as Mock).mockResolvedValue(null);
|
113
|
+
|
114
|
+
// Test & Verify: Expect error
|
115
|
+
await expect(cache.getContractArtifact(mockContractAddress)).rejects.toThrow(
|
116
|
+
new AztecWalletError('contractClassNotRegistered', mockContractClassId.toString()),
|
117
|
+
);
|
118
|
+
|
119
|
+
// Verify: Nothing cached
|
120
|
+
expect(
|
121
|
+
(cache as unknown as { cache: Map<string, ContractArtifact> }).cache.get(
|
122
|
+
mockContractAddress.toString(),
|
123
|
+
),
|
124
|
+
).toBeUndefined();
|
125
|
+
});
|
126
|
+
});
|
@@ -0,0 +1,75 @@
|
|
1
|
+
/**
|
2
|
+
* @module contractArtifactCache
|
3
|
+
*
|
4
|
+
* This module provides caching functionality for Aztec contract artifacts.
|
5
|
+
* It helps improve performance by avoiding repeated fetches of the same contract artifacts.
|
6
|
+
*/
|
7
|
+
|
8
|
+
import type { AztecAddress, ContractArtifact, Wallet } from '@aztec/aztec.js';
|
9
|
+
|
10
|
+
import { AztecWalletError } from './errors.js';
|
11
|
+
|
12
|
+
/**
|
13
|
+
* Caches contract artifacts to optimize contract interactions.
|
14
|
+
*
|
15
|
+
* This class maintains an in-memory cache of contract artifacts indexed by contract address.
|
16
|
+
* When a contract artifact is requested:
|
17
|
+
* 1. First checks the cache for an existing artifact
|
18
|
+
* 2. If not found, fetches the contract instance and its artifact from the wallet
|
19
|
+
* 3. Stores the artifact in the cache for future use
|
20
|
+
* 4. Returns the artifact to the caller
|
21
|
+
*
|
22
|
+
* This caching mechanism helps reduce:
|
23
|
+
* - Network requests to fetch contract data
|
24
|
+
* - Processing overhead of parsing contract artifacts
|
25
|
+
* - Memory usage by reusing existing artifacts
|
26
|
+
*/
|
27
|
+
export class ContractArtifactCache {
|
28
|
+
/** Map of contract addresses to their artifacts */
|
29
|
+
private cache = new Map<string, ContractArtifact>();
|
30
|
+
/** Reference to the wallet instance for fetching contract data */
|
31
|
+
private wallet: Wallet;
|
32
|
+
|
33
|
+
/**
|
34
|
+
* Creates a new ContractArtifactCache instance.
|
35
|
+
* @param wallet - Wallet instance used to fetch contract data when cache misses occur
|
36
|
+
*/
|
37
|
+
constructor(wallet: Wallet) {
|
38
|
+
this.wallet = wallet;
|
39
|
+
}
|
40
|
+
|
41
|
+
/**
|
42
|
+
* Retrieves the contract artifact for a given contract address.
|
43
|
+
* First checks the cache, then falls back to fetching from the wallet if needed.
|
44
|
+
*
|
45
|
+
* The process:
|
46
|
+
* 1. Check if artifact exists in cache
|
47
|
+
* 2. If not, get contract instance from wallet
|
48
|
+
* 3. Use instance to get contract class ID
|
49
|
+
* 4. Fetch artifact using class ID
|
50
|
+
* 5. Cache the artifact for future use
|
51
|
+
*
|
52
|
+
* @param contractAddress - The contract address to retrieve the artifact for
|
53
|
+
* @returns Promise resolving to the contract artifact
|
54
|
+
* @throws {AztecWalletError} If contract instance or class not registered
|
55
|
+
*/
|
56
|
+
public async getContractArtifact(contractAddress: AztecAddress): Promise<ContractArtifact> {
|
57
|
+
const addressStr = contractAddress.toString();
|
58
|
+
const cached = this.cache.get(addressStr);
|
59
|
+
if (cached) {
|
60
|
+
return cached;
|
61
|
+
}
|
62
|
+
|
63
|
+
const contract = await this.wallet.getContractInstance(contractAddress);
|
64
|
+
if (!contract) {
|
65
|
+
throw new AztecWalletError('contractInstanceNotRegistered', addressStr);
|
66
|
+
}
|
67
|
+
const artifact = await this.wallet.getContractArtifact(contract.contractClassId);
|
68
|
+
if (!artifact) {
|
69
|
+
throw new AztecWalletError('contractClassNotRegistered', contract.contractClassId.toString());
|
70
|
+
}
|
71
|
+
|
72
|
+
this.cache.set(addressStr, artifact);
|
73
|
+
return artifact;
|
74
|
+
}
|
75
|
+
}
|