@aztec/aztec-node 0.1.0-alpha20 → 0.1.0-alpha22

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.
@@ -0,0 +1,428 @@
1
+ import { AztecAddress, CircuitsWasm, Fr } from '@aztec/circuits.js';
2
+ import { randomBytes } from '@aztec/foundation/crypto';
3
+ import { Pedersen, SiblingPath } from '@aztec/merkle-tree';
4
+ import {
5
+ ContractData,
6
+ ContractPublicData,
7
+ L1ToL2Message,
8
+ L2Block,
9
+ L2BlockL2Logs,
10
+ LogType,
11
+ MerkleTreeId,
12
+ mockTx,
13
+ TxHash,
14
+ } from '@aztec/types';
15
+ import { jest } from '@jest/globals';
16
+ import { HttpNode } from './http-node.js';
17
+
18
+ const TEST_URL = 'http://aztec-node-url.com/';
19
+
20
+ const setFetchMock = (response: any, status = 200): void => {
21
+ global.fetch = jest
22
+ .fn<typeof global.fetch>()
23
+ .mockImplementation((_input: RequestInfo | URL, _init?: RequestInit | undefined) => {
24
+ return Promise.resolve({
25
+ status,
26
+ ok: true,
27
+ json: () => response,
28
+ arrayBuffer: () => response,
29
+ } as Response);
30
+ });
31
+ };
32
+
33
+ describe('HttpNode', () => {
34
+ let httpNode: HttpNode;
35
+ let pedersen: Pedersen;
36
+
37
+ beforeAll(async () => {
38
+ httpNode = new HttpNode(TEST_URL);
39
+ pedersen = new Pedersen(await CircuitsWasm.get());
40
+ });
41
+
42
+ afterEach(() => {
43
+ jest.clearAllMocks();
44
+ });
45
+
46
+ describe('isReady', () => {
47
+ it.each([true, false])('should return %s when the node is ready', async () => {
48
+ const response = { isReady: true };
49
+ setFetchMock(response);
50
+
51
+ const result = await httpNode.isReady();
52
+
53
+ expect(fetch).toHaveBeenCalledWith(TEST_URL);
54
+ expect(result).toBe(true);
55
+ });
56
+ });
57
+
58
+ describe('getBlocks', () => {
59
+ it('should fetch and parse blocks', async () => {
60
+ const block1 = L2Block.random(1);
61
+ const block2 = L2Block.random(2);
62
+ const response = {
63
+ blocks: [block1.encode(), block2.encode()],
64
+ };
65
+ setFetchMock(response);
66
+
67
+ const result = await httpNode.getBlocks(0, 3);
68
+
69
+ expect(fetch).toHaveBeenCalledWith(`${TEST_URL}get-blocks?from=0&take=3`);
70
+ expect(result).toEqual([block1, block2]);
71
+ });
72
+
73
+ it('should return an empty array if blocks are not available', async () => {
74
+ const response = { blocks: [] };
75
+ setFetchMock(response);
76
+
77
+ const result = await httpNode.getBlocks(0, 2);
78
+
79
+ expect(fetch).toHaveBeenCalledWith(`${TEST_URL}get-blocks?from=0&take=2`);
80
+ expect(result).toEqual([]);
81
+ });
82
+ });
83
+
84
+ describe('getBlockHeight', () => {
85
+ it('should fetch and return the block height', async () => {
86
+ const response = { blockHeight: 100 };
87
+ setFetchMock(response);
88
+
89
+ const result = await httpNode.getBlockHeight();
90
+
91
+ expect(fetch).toHaveBeenCalledWith(`${TEST_URL}get-block-height`);
92
+ expect(result).toBe(100);
93
+ });
94
+ });
95
+
96
+ describe('getVersion', () => {
97
+ it('should fetch and return the version', async () => {
98
+ const response = { version: 5 };
99
+ setFetchMock(response);
100
+
101
+ const result = await httpNode.getVersion();
102
+
103
+ expect(fetch).toHaveBeenCalledWith(`${TEST_URL}get-version`);
104
+ expect(result).toBe(5);
105
+ });
106
+ });
107
+
108
+ describe('getChainId', () => {
109
+ it('should fetch and return the chain ID', async () => {
110
+ const response = { chainId: 1234 };
111
+ setFetchMock(response);
112
+
113
+ const result = await httpNode.getChainId();
114
+
115
+ expect(fetch).toHaveBeenCalledWith(`${TEST_URL}get-chain-id`);
116
+ expect(result).toBe(1234);
117
+ });
118
+ });
119
+
120
+ describe('getContractData', () => {
121
+ it('should fetch and return contract public data', async () => {
122
+ const contractData = ContractPublicData.random();
123
+ const response = {
124
+ contractData: contractData.toBuffer(),
125
+ };
126
+
127
+ setFetchMock(response);
128
+
129
+ const result = await httpNode.getContractData(contractData.contractData.contractAddress);
130
+
131
+ expect(fetch).toHaveBeenCalledWith(
132
+ `${TEST_URL}contract-data?address=${contractData.contractData.contractAddress.toString()}`,
133
+ );
134
+ expect(result).toEqual(contractData);
135
+ });
136
+
137
+ it('should return undefined if contract data is not available', async () => {
138
+ const response = {
139
+ contractData: undefined,
140
+ };
141
+ setFetchMock(response);
142
+
143
+ const randomAddress = AztecAddress.random();
144
+
145
+ const result = await httpNode.getContractData(randomAddress);
146
+
147
+ expect(fetch).toHaveBeenCalledWith(`${TEST_URL}contract-data?address=${randomAddress.toString()}`);
148
+ expect(result).toEqual(undefined);
149
+ });
150
+ });
151
+
152
+ describe('getLogs', () => {
153
+ it.each(['encrypted', 'unencrypted'])('should fetch and return %s logs', async logType => {
154
+ const processedLogType = logType === 'encrypted' ? LogType.ENCRYPTED : LogType.UNENCRYPTED;
155
+
156
+ const from = 0;
157
+ const take = 3;
158
+ const log1 = L2BlockL2Logs.random(2, 3, 4);
159
+ const log2 = L2BlockL2Logs.random(1, 5, 2);
160
+ const response = {
161
+ logs: [log1.toBuffer(), log2.toBuffer()],
162
+ };
163
+ setFetchMock(response);
164
+
165
+ const result = await httpNode.getLogs(from, take, processedLogType);
166
+
167
+ expect(fetch).toHaveBeenCalledWith(`${TEST_URL}get-logs?from=${from}&take=${take}&logType=${processedLogType}`);
168
+ expect(result).toEqual([log1, log2]);
169
+ });
170
+
171
+ it.each(['encrypted', 'unencrypted'])(
172
+ 'should return an empty array if %s logs are not available',
173
+ async logType => {
174
+ const processedLogType = logType === 'encrypted' ? LogType.ENCRYPTED : LogType.UNENCRYPTED;
175
+
176
+ const from = 0;
177
+ const take = 2;
178
+ const response = {};
179
+ setFetchMock(response);
180
+
181
+ const result = await httpNode.getLogs(from, take, processedLogType);
182
+
183
+ expect(fetch).toHaveBeenCalledWith(`${TEST_URL}get-logs?from=${from}&take=${take}&logType=${processedLogType}`);
184
+ expect(result).toEqual([]);
185
+ },
186
+ );
187
+ });
188
+
189
+ describe('getContractInfo', () => {
190
+ it('should fetch and return contract data', async () => {
191
+ const contractInfo = ContractData.random();
192
+ const response = {
193
+ contractInfo: contractInfo.toBuffer(),
194
+ };
195
+ setFetchMock(response);
196
+
197
+ const result = await httpNode.getContractInfo(contractInfo.contractAddress);
198
+
199
+ expect(fetch).toHaveBeenCalledWith(`${TEST_URL}contract-info?address=${contractInfo.contractAddress.toString()}`);
200
+ expect(result).toEqual(contractInfo);
201
+ });
202
+
203
+ it('should return undefined if contract data is not available', async () => {
204
+ const response = {
205
+ contractInfo: undefined,
206
+ };
207
+ setFetchMock(response);
208
+
209
+ const randomAddress = AztecAddress.random();
210
+
211
+ const result = await httpNode.getContractInfo(randomAddress);
212
+
213
+ expect(fetch).toHaveBeenCalledWith(`${TEST_URL}contract-info?address=${randomAddress.toString()}`);
214
+ expect(result).toBeUndefined();
215
+ });
216
+ });
217
+
218
+ describe('sendTx', () => {
219
+ it('should submit a transaction to the p2p pool', async () => {
220
+ const tx = mockTx();
221
+ const irrelevantResponse = {};
222
+ setFetchMock(irrelevantResponse);
223
+
224
+ await httpNode.sendTx(tx);
225
+
226
+ const init: RequestInit = {
227
+ method: 'POST',
228
+ body: tx.toBuffer(),
229
+ };
230
+ const call = (fetch as jest.Mock).mock.calls[0] as any[];
231
+ expect(call[0].href).toBe(`${TEST_URL}tx`);
232
+ expect(call[1]).toStrictEqual(init);
233
+ });
234
+ });
235
+
236
+ describe('getPendingTxByHash', () => {
237
+ it('should fetch and return a pending tx', async () => {
238
+ const txHash = new TxHash(randomBytes(TxHash.SIZE));
239
+ const tx = mockTx();
240
+ const response = tx.toBuffer();
241
+ setFetchMock(response);
242
+
243
+ const result = await httpNode.getPendingTxByHash(txHash);
244
+
245
+ expect(fetch).toHaveBeenCalledWith(`${TEST_URL}get-pending-tx?hash=${txHash}`);
246
+ expect(result).toEqual(tx);
247
+ });
248
+
249
+ it('should return undefined if the pending tx does not exist', async () => {
250
+ const txHash = new TxHash(randomBytes(TxHash.SIZE));
251
+ const response = undefined;
252
+ setFetchMock(response, 404);
253
+
254
+ const result = await httpNode.getPendingTxByHash(txHash);
255
+
256
+ expect(fetch).toHaveBeenCalledWith(`${TEST_URL}get-pending-tx?hash=${txHash}`);
257
+ expect(result).toBeUndefined();
258
+ });
259
+ });
260
+
261
+ describe('findContractIndex', () => {
262
+ it('should fetch and return the index of the given contract', async () => {
263
+ const leafValue = Buffer.from('abc123', 'hex');
264
+ const index = '123456';
265
+ const response = { index };
266
+ setFetchMock(response);
267
+
268
+ const result = await httpNode.findContractIndex(leafValue);
269
+
270
+ expect(fetch).toHaveBeenCalledWith(`${TEST_URL}contract-index?leaf=${leafValue.toString('hex')}`);
271
+ expect(result).toBe(BigInt(index));
272
+ });
273
+
274
+ it('should return undefined if the contract index is not found', async () => {
275
+ const leafValue = Buffer.from('def456', 'hex');
276
+ const response = {};
277
+ setFetchMock(response);
278
+
279
+ const result = await httpNode.findContractIndex(leafValue);
280
+
281
+ expect(fetch).toHaveBeenCalledWith(`${TEST_URL}contract-index?leaf=${leafValue.toString('hex')}`);
282
+ expect(result).toBeUndefined();
283
+ });
284
+ });
285
+
286
+ describe('getContractPath', () => {
287
+ it('should fetch and return the sibling path for the given leaf index', async () => {
288
+ const leafIndex = BigInt(123456);
289
+ const siblingPath = SiblingPath.ZERO(3, Buffer.alloc(32), pedersen);
290
+ const response = { path: siblingPath.toBuffer().toString('hex') };
291
+ setFetchMock(response);
292
+
293
+ const result = await httpNode.getContractPath(leafIndex);
294
+
295
+ expect(fetch).toHaveBeenCalledWith(`${TEST_URL}contract-path?leaf=${leafIndex.toString()}`);
296
+ expect(result).toEqual(siblingPath);
297
+ });
298
+ });
299
+
300
+ describe('findCommitmentIndex', () => {
301
+ it('should fetch and return the index of the given leaf', async () => {
302
+ const leafValue = Buffer.from('0123456789', 'hex');
303
+ const expectedIndex = BigInt(123);
304
+ const response = { index: expectedIndex.toString() };
305
+ setFetchMock(response);
306
+
307
+ const result = await httpNode.findCommitmentIndex(leafValue);
308
+
309
+ expect(fetch).toHaveBeenCalledWith(`${TEST_URL}commitment-index?leaf=${leafValue.toString('hex')}`);
310
+ expect(result).toBe(expectedIndex);
311
+ });
312
+
313
+ it('should return undefined if the commitment index is not found', async () => {
314
+ const leafValue = Buffer.from('def456', 'hex');
315
+ const response = {};
316
+ setFetchMock(response);
317
+
318
+ const result = await httpNode.findCommitmentIndex(leafValue);
319
+
320
+ expect(fetch).toHaveBeenCalledWith(`${TEST_URL}commitment-index?leaf=${leafValue.toString('hex')}`);
321
+ expect(result).toBeUndefined();
322
+ });
323
+ });
324
+
325
+ describe('getDataTreePath', () => {
326
+ it('should fetch and return the sibling path for the given leaf index', async () => {
327
+ const leafIndex = BigInt(123456);
328
+ const siblingPath = SiblingPath.ZERO(3, Buffer.alloc(32), pedersen);
329
+ const response = { path: siblingPath.toBuffer().toString('hex') };
330
+ setFetchMock(response);
331
+
332
+ const result = await httpNode.getDataTreePath(leafIndex);
333
+
334
+ expect(fetch).toHaveBeenCalledWith(`${TEST_URL}data-path?leaf=${leafIndex.toString()}`);
335
+ expect(result).toEqual(siblingPath);
336
+ });
337
+ });
338
+
339
+ describe('getL1ToL2MessageAndIndex', () => {
340
+ it('should fetch and return the L1 to L2 message and index for the given message key', async () => {
341
+ const messageKey = new Fr(789);
342
+ const expectedMessage = L1ToL2Message.random();
343
+ const expectedIndex = BigInt(123);
344
+ const response = { message: expectedMessage.toBuffer().toString('hex'), index: expectedIndex.toString() };
345
+ setFetchMock(response);
346
+
347
+ const result = await httpNode.getL1ToL2MessageAndIndex(messageKey);
348
+
349
+ expect(fetch).toHaveBeenCalledWith(`${TEST_URL}l1-l2-message?messageKey=${messageKey.toString()}`);
350
+ expect(result).toEqual({
351
+ message: expectedMessage,
352
+ index: expectedIndex,
353
+ });
354
+ });
355
+ });
356
+
357
+ describe('getL1ToL2MessagesTreePath', () => {
358
+ it('should fetch and return the sibling path for the given leaf index', async () => {
359
+ const leafIndex = BigInt(123456);
360
+ const siblingPath = SiblingPath.ZERO(3, Buffer.alloc(32), pedersen);
361
+ const response = { path: siblingPath.toBuffer().toString('hex') };
362
+ setFetchMock(response);
363
+
364
+ const result = await httpNode.getL1ToL2MessagesTreePath(leafIndex);
365
+
366
+ const url = `${TEST_URL}l1-l2-path?leaf=${leafIndex.toString()}`;
367
+ expect(fetch).toHaveBeenCalledWith(url);
368
+ expect(result).toEqual(siblingPath);
369
+ });
370
+ });
371
+
372
+ describe('getStorageAt', () => {
373
+ it('should fetch and return the storage value at the given contract slot', async () => {
374
+ const contractAddress = AztecAddress.random();
375
+ const slot = BigInt(789);
376
+ const storageValue = Buffer.from('0123456789', 'hex');
377
+ const response = { value: storageValue.toString('hex') };
378
+ setFetchMock(response);
379
+
380
+ const result = await httpNode.getStorageAt(contractAddress, slot);
381
+
382
+ const url = `${TEST_URL}storage-at?address=${contractAddress}&slot=${slot.toString()}`;
383
+ expect(fetch).toHaveBeenCalledWith(url);
384
+ expect(result).toEqual(storageValue);
385
+ });
386
+
387
+ it('should return undefined if the storage value is not found', async () => {
388
+ const contractAddress = AztecAddress.random();
389
+ const slot = BigInt(987);
390
+ const response = {};
391
+ setFetchMock(response);
392
+
393
+ const result = await httpNode.getStorageAt(contractAddress, slot);
394
+
395
+ const url = `${TEST_URL}storage-at?address=${contractAddress}&slot=${slot.toString()}`;
396
+ expect(fetch).toHaveBeenCalledWith(url);
397
+ expect(result).toBeUndefined();
398
+ });
399
+ });
400
+
401
+ describe('getTreeRoots', () => {
402
+ it('should fetch and return the current committed roots for the data trees', async () => {
403
+ const roots: Record<MerkleTreeId, Fr> = {
404
+ [MerkleTreeId.CONTRACT_TREE]: Fr.random(),
405
+ [MerkleTreeId.PRIVATE_DATA_TREE]: Fr.random(),
406
+ [MerkleTreeId.NULLIFIER_TREE]: Fr.random(),
407
+ [MerkleTreeId.PUBLIC_DATA_TREE]: Fr.random(),
408
+ [MerkleTreeId.L1_TO_L2_MESSAGES_TREE]: Fr.random(),
409
+ [MerkleTreeId.L1_TO_L2_MESSAGES_ROOTS_TREE]: Fr.random(),
410
+ [MerkleTreeId.CONTRACT_TREE_ROOTS_TREE]: Fr.random(),
411
+ [MerkleTreeId.PRIVATE_DATA_TREE_ROOTS_TREE]: Fr.random(),
412
+ };
413
+
414
+ const rootsInResponse: Record<MerkleTreeId, string> = Object.fromEntries(
415
+ Object.entries(roots).map(([key, value]) => [key, value.toString()]),
416
+ ) as Record<MerkleTreeId, string>;
417
+ const response = { roots: rootsInResponse };
418
+
419
+ setFetchMock(response);
420
+
421
+ const result = await httpNode.getTreeRoots();
422
+
423
+ const url = `${TEST_URL}tree-roots`;
424
+ expect(fetch).toHaveBeenCalledWith(url);
425
+ expect(result).toEqual(roots);
426
+ });
427
+ });
428
+ });
@@ -3,76 +3,34 @@ import {
3
3
  AztecAddress,
4
4
  CONTRACT_TREE_HEIGHT,
5
5
  Fr,
6
- KernelCircuitPublicInputs,
7
- L1_TO_L2_MESSAGES_TREE_HEIGHT,
6
+ L1_TO_L2_MSG_TREE_HEIGHT,
8
7
  PRIVATE_DATA_TREE_HEIGHT,
9
- Proof,
10
- PublicCallRequest,
11
8
  } from '@aztec/circuits.js';
9
+ import { Logger, createLogger } from '@aztec/foundation/log';
12
10
  import { SiblingPath } from '@aztec/merkle-tree';
13
11
  import {
14
12
  ContractData,
15
13
  ContractPublicData,
16
- EncodedContractFunction,
17
14
  L1ToL2Message,
18
15
  L1ToL2MessageAndIndex,
19
16
  L2Block,
20
17
  L2BlockL2Logs,
18
+ LogType,
21
19
  MerkleTreeId,
22
20
  Tx,
23
21
  TxHash,
24
- TxL2Logs,
25
22
  } from '@aztec/types';
26
23
 
27
- /**
28
- * Serialises a transaction to JSON representation.
29
- * @param tx - The transaction to serialise.
30
- * @returns The serialsied transaction.
31
- */
32
- export function txToJson(tx: Tx) {
33
- return {
34
- data: tx.data?.toBuffer().toString('hex'),
35
- encryptedLogs: tx.encryptedLogs?.toBuffer().toString('hex'),
36
- unencryptedLogs: tx.unencryptedLogs?.toBuffer().toString('hex'),
37
- proof: tx.proof?.toBuffer().toString('hex'),
38
- newContractPublicFunctions: tx.newContractPublicFunctions?.map(f => f.toBuffer().toString('hex')) ?? [],
39
- enqueuedPublicFunctions: tx.enqueuedPublicFunctionCalls?.map(f => f.toBuffer().toString('hex')) ?? [],
40
- };
41
- }
42
-
43
- /**
44
- * Deserialises a transaction from JSON.
45
- * @param json - The JSON representation of the transaction.
46
- * @returns The deserialised transaction.
47
- */
48
- export function txFromJson(json: any) {
49
- const publicInputs = KernelCircuitPublicInputs.fromBuffer(Buffer.from(json.data, 'hex'));
50
- const encryptedLogs = TxL2Logs.fromBuffer(Buffer.from(json.encryptedLogs, 'hex'));
51
- const unencryptedLogs = TxL2Logs.fromBuffer(Buffer.from(json.unencryptedLogs, 'hex'));
52
- const proof = Buffer.from(json.proof, 'hex');
53
- const newContractPublicFunctions = json.newContractPublicFunctions?.length
54
- ? json.newContractPublicFunctions.map((x: string) => EncodedContractFunction.fromBuffer(Buffer.from(x, 'hex')))
55
- : [];
56
- const enqueuedPublicFunctions = json.enqueuedPublicFunctions?.length
57
- ? json.enqueuedPublicFunctions.map((x: string) => PublicCallRequest.fromBuffer(Buffer.from(x, 'hex')))
58
- : [];
59
- return new Tx(
60
- publicInputs,
61
- Proof.fromBuffer(proof),
62
- encryptedLogs,
63
- unencryptedLogs,
64
- newContractPublicFunctions,
65
- enqueuedPublicFunctions,
66
- );
67
- }
68
-
69
24
  /**
70
25
  * A Http client based implementation of Aztec Node.
71
26
  */
72
27
  export class HttpNode implements AztecNode {
73
28
  private baseUrl: string;
74
- constructor(baseUrl: string) {
29
+ private log: Logger;
30
+
31
+ constructor(baseUrl: string, log = createLogger('aztec:http-node')) {
75
32
  this.baseUrl = baseUrl.toString().replace(/\/$/, '');
33
+ this.log = log;
76
34
  }
77
35
  /**
78
36
  * Method to determine if the node is ready to accept transactions.
@@ -120,7 +78,7 @@ export class HttpNode implements AztecNode {
120
78
  * Method to fetch the version of the rollup the node is connected to.
121
79
  * @returns The rollup version.
122
80
  */
123
- public async getVersion(): Promise<Fr> {
81
+ public async getVersion(): Promise<number> {
124
82
  const url = new URL(`${this.baseUrl}/get-version`);
125
83
  const response = await fetch(url.toString());
126
84
  const respJson = await response.json();
@@ -131,7 +89,7 @@ export class HttpNode implements AztecNode {
131
89
  * Method to fetch the chain id of the base-layer for the rollup.
132
90
  * @returns The chain id.
133
91
  */
134
- public async getChainId(): Promise<Fr> {
92
+ public async getChainId(): Promise<number> {
135
93
  const url = new URL(`${this.baseUrl}/get-chain-id`);
136
94
  const response = await fetch(url.toString());
137
95
  const respJson = await response.json();
@@ -148,55 +106,39 @@ export class HttpNode implements AztecNode {
148
106
  const url = new URL(`${this.baseUrl}/contract-data`);
149
107
  url.searchParams.append('address', contractAddress.toString());
150
108
  const response = await (await fetch(url.toString())).json();
109
+ if (!response || !response.contractData) {
110
+ return undefined;
111
+ }
151
112
  const contract = response.contractData as string;
152
113
  return Promise.resolve(ContractPublicData.fromBuffer(Buffer.from(contract, 'hex')));
153
114
  }
154
115
 
155
116
  /**
156
- * Gets the `take` amount of encrypted logs starting from `from`.
157
- * @param from - Number of the L2 block to which corresponds the first encrypted logs to be returned.
158
- * @param take - The number of encrypted logs to return.
159
- * @returns The requested encrypted logs.
117
+ * Gets the `take` amount of logs starting from `from`.
118
+ * @param from - Number of the L2 block to which corresponds the first logs to be returned.
119
+ * @param take - The number of logs to return.
120
+ * @param logType - Specifies whether to return encrypted or unencrypted logs.
121
+ * @returns The requested logs.
160
122
  */
161
- public async getEncryptedLogs(from: number, take: number): Promise<L2BlockL2Logs[]> {
162
- const url = new URL(`${this.baseUrl}/get-encrypted-logs`);
163
- url.searchParams.append('from', from.toString());
164
- if (take !== undefined) {
165
- url.searchParams.append('take', take.toString());
166
- }
167
- const response = await (await fetch(url.toString())).json();
168
- const encryptedLogs = response.encryptedLogs as string[];
123
+ public async getLogs(from: number, take: number, logType: LogType): Promise<L2BlockL2Logs[]> {
124
+ const url = new URL(`${this.baseUrl}/get-logs`);
169
125
 
170
- if (!encryptedLogs) {
171
- return Promise.resolve([]);
172
- }
173
- return Promise.resolve(encryptedLogs.map(x => L2BlockL2Logs.fromBuffer(Buffer.from(x, 'hex'))));
174
- }
175
-
176
- /**
177
- * Gets the `take` amount of unencrypted logs starting from `from`.
178
- * @param from - Number of the L2 block to which corresponds the first unencrypted logs to be returned.
179
- * @param take - The number of unencrypted logs to return.
180
- * @returns The requested unencrypted logs.
181
- */
182
- public async getUnencryptedLogs(from: number, take: number): Promise<L2BlockL2Logs[]> {
183
- const url = new URL(`${this.baseUrl}/get-unencrypted-logs`);
184
126
  url.searchParams.append('from', from.toString());
185
- if (take !== undefined) {
186
- url.searchParams.append('take', take.toString());
187
- }
127
+ url.searchParams.append('take', take.toString());
128
+ url.searchParams.append('logType', logType.toString());
129
+
188
130
  const response = await (await fetch(url.toString())).json();
189
- const unencryptedLogs = response.unencryptedLogs as string[];
131
+ const logs = response.logs as string[];
190
132
 
191
- if (!unencryptedLogs) {
133
+ if (!logs) {
192
134
  return Promise.resolve([]);
193
135
  }
194
- return Promise.resolve(unencryptedLogs.map(x => L2BlockL2Logs.fromBuffer(Buffer.from(x, 'hex'))));
136
+ return Promise.resolve(logs.map(x => L2BlockL2Logs.fromBuffer(Buffer.from(x, 'hex'))));
195
137
  }
196
138
 
197
139
  /**
198
140
  * Lookup the L2 contract info for this contract.
199
- * Contains the ethereum portal address .
141
+ * Contains the ethereum portal address.
200
142
  * @param contractAddress - The contract data address.
201
143
  * @returns The contract's address & portal address.
202
144
  */
@@ -204,6 +146,9 @@ export class HttpNode implements AztecNode {
204
146
  const url = new URL(`${this.baseUrl}/contract-info`);
205
147
  url.searchParams.append('address', contractAddress.toString());
206
148
  const response = await (await fetch(url.toString())).json();
149
+ if (!response || !response.contractInfo) {
150
+ return undefined;
151
+ }
207
152
  const contract = response.contractInfo as string;
208
153
  return Promise.resolve(ContractData.fromBuffer(Buffer.from(contract, 'hex')));
209
154
  }
@@ -214,10 +159,9 @@ export class HttpNode implements AztecNode {
214
159
  */
215
160
  async sendTx(tx: Tx): Promise<void> {
216
161
  const url = new URL(`${this.baseUrl}/tx`);
217
- const json = txToJson(tx);
218
162
  const init: RequestInit = {};
219
163
  init['method'] = 'POST';
220
- init['body'] = JSON.stringify(json);
164
+ init['body'] = tx.toBuffer();
221
165
  await fetch(url, init);
222
166
  }
223
167
 
@@ -237,8 +181,14 @@ export class HttpNode implements AztecNode {
237
181
  async getPendingTxByHash(txHash: TxHash): Promise<Tx | undefined> {
238
182
  const url = new URL(`${this.baseUrl}/get-pending-tx`);
239
183
  url.searchParams.append('hash', txHash.toString());
240
- const response = await (await fetch(url.toString())).json();
241
- return Promise.resolve(txFromJson(response));
184
+ const response = await fetch(url.toString());
185
+ if (response.status === 404) {
186
+ this.log(`Tx ${txHash.toString()} not found`);
187
+ return undefined;
188
+ }
189
+ const txBuffer = Buffer.from(await (await fetch(url.toString())).arrayBuffer());
190
+ const tx = Tx.fromBuffer(txBuffer);
191
+ return Promise.resolve(tx);
242
192
  }
243
193
 
244
194
  /**
@@ -250,6 +200,9 @@ export class HttpNode implements AztecNode {
250
200
  const url = new URL(`${this.baseUrl}/contract-index`);
251
201
  url.searchParams.append('leaf', leafValue.toString('hex'));
252
202
  const response = await (await fetch(url.toString())).json();
203
+ if (!response || !response.index) {
204
+ return undefined;
205
+ }
253
206
  const index = response.index as string;
254
207
  return Promise.resolve(BigInt(index));
255
208
  }
@@ -276,6 +229,9 @@ export class HttpNode implements AztecNode {
276
229
  const url = new URL(`${this.baseUrl}/commitment-index`);
277
230
  url.searchParams.append('leaf', leafValue.toString('hex'));
278
231
  const response = await (await fetch(url.toString())).json();
232
+ if (!response || !response.index) {
233
+ return undefined;
234
+ }
279
235
  const index = response.index as string;
280
236
  return Promise.resolve(BigInt(index));
281
237
  }
@@ -313,7 +269,7 @@ export class HttpNode implements AztecNode {
313
269
  * @param leafIndex - Index of the leaf in the tree.
314
270
  * @returns The sibling path.
315
271
  */
316
- async getL1ToL2MessagesTreePath(leafIndex: bigint): Promise<SiblingPath<typeof L1_TO_L2_MESSAGES_TREE_HEIGHT>> {
272
+ async getL1ToL2MessagesTreePath(leafIndex: bigint): Promise<SiblingPath<typeof L1_TO_L2_MSG_TREE_HEIGHT>> {
317
273
  const url = new URL(`${this.baseUrl}/l1-l2-path`);
318
274
  url.searchParams.append('leaf', leafIndex.toString());
319
275
  const response = await (await fetch(url.toString())).json();
@@ -333,6 +289,9 @@ export class HttpNode implements AztecNode {
333
289
  url.searchParams.append('address', contract.toString());
334
290
  url.searchParams.append('slot', slot.toString());
335
291
  const response = await (await fetch(url.toString())).json();
292
+ if (!response || !response.value) {
293
+ return undefined;
294
+ }
336
295
  const value = response.value as string;
337
296
  return Promise.resolve(Buffer.from(value, 'hex'));
338
297
  }
@@ -345,7 +304,11 @@ export class HttpNode implements AztecNode {
345
304
  const url = new URL(`${this.baseUrl}/tree-roots`);
346
305
  const response = await (await fetch(url.toString())).json();
347
306
 
348
- const extractRoot = (treeId: MerkleTreeId) => Fr.fromBuffer(Buffer.from(response.roots[`${treeId}`], 'hex'));
307
+ const extractRoot = (treeId: MerkleTreeId) => {
308
+ // Buffer.from(...) returns an empty buffer when a hex string is prefixed with "0x"
309
+ const rootHexString = response.roots[treeId].replace(/^0x/, '');
310
+ return Fr.fromBuffer(Buffer.from(rootHexString, 'hex'));
311
+ };
349
312
 
350
313
  return {
351
314
  [MerkleTreeId.CONTRACT_TREE]: extractRoot(MerkleTreeId.CONTRACT_TREE),