@aztec/foundation 0.0.1-commit.f504929 → 0.0.1-commit.f5a9928

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (288) hide show
  1. package/dest/bigint-buffer/index.d.ts +1 -1
  2. package/dest/bigint-buffer/index.d.ts.map +1 -1
  3. package/dest/bigint-buffer/index.js +6 -1
  4. package/dest/branded-types/block_number.d.ts +3 -3
  5. package/dest/branded-types/block_number.d.ts.map +1 -1
  6. package/dest/branded-types/block_number.js +15 -4
  7. package/dest/branded-types/buffer32_hash.d.ts +27 -0
  8. package/dest/branded-types/buffer32_hash.d.ts.map +1 -0
  9. package/dest/branded-types/buffer32_hash.js +12 -0
  10. package/dest/branded-types/checkpoint_number.d.ts +9 -3
  11. package/dest/branded-types/checkpoint_number.d.ts.map +1 -1
  12. package/dest/branded-types/checkpoint_number.js +11 -0
  13. package/dest/branded-types/epoch.d.ts +2 -2
  14. package/dest/branded-types/epoch.d.ts.map +1 -1
  15. package/dest/branded-types/index.d.ts +2 -1
  16. package/dest/branded-types/index.d.ts.map +1 -1
  17. package/dest/branded-types/index.js +1 -0
  18. package/dest/branded-types/index_within_checkpoint.d.ts +2 -2
  19. package/dest/branded-types/index_within_checkpoint.d.ts.map +1 -1
  20. package/dest/branded-types/slot.d.ts +5 -2
  21. package/dest/branded-types/slot.d.ts.map +1 -1
  22. package/dest/branded-types/slot.js +3 -0
  23. package/dest/buffer/buffer16.d.ts +3 -1
  24. package/dest/buffer/buffer16.d.ts.map +1 -1
  25. package/dest/buffer/buffer32.d.ts +28 -61
  26. package/dest/buffer/buffer32.d.ts.map +1 -1
  27. package/dest/buffer/buffer32.js +29 -63
  28. package/dest/buffer/index.d.ts +2 -1
  29. package/dest/buffer/index.d.ts.map +1 -1
  30. package/dest/buffer/index.js +1 -0
  31. package/dest/buffer/utils.d.ts +3 -0
  32. package/dest/buffer/utils.d.ts.map +1 -0
  33. package/dest/buffer/utils.js +7 -0
  34. package/dest/collection/array.d.ts +11 -1
  35. package/dest/collection/array.d.ts.map +1 -1
  36. package/dest/collection/array.js +33 -0
  37. package/dest/collection/index.d.ts +3 -1
  38. package/dest/collection/index.d.ts.map +1 -1
  39. package/dest/collection/index.js +2 -0
  40. package/dest/collection/lru_map.d.ts +41 -0
  41. package/dest/collection/lru_map.d.ts.map +1 -0
  42. package/dest/collection/lru_map.js +119 -0
  43. package/dest/collection/lru_set.d.ts +35 -0
  44. package/dest/collection/lru_set.d.ts.map +1 -0
  45. package/dest/collection/lru_set.js +95 -0
  46. package/dest/committable/committable.js +1 -1
  47. package/dest/config/env_var.d.ts +2 -2
  48. package/dest/config/env_var.d.ts.map +1 -1
  49. package/dest/config/index.d.ts +67 -37
  50. package/dest/config/index.d.ts.map +1 -1
  51. package/dest/config/index.js +72 -71
  52. package/dest/config/network_config.d.ts +13 -45
  53. package/dest/config/network_config.d.ts.map +1 -1
  54. package/dest/config/network_config.js +3 -1
  55. package/dest/config/network_name.d.ts +2 -2
  56. package/dest/config/network_name.d.ts.map +1 -1
  57. package/dest/config/network_name.js +1 -3
  58. package/dest/config/secret_value.d.ts +2 -2
  59. package/dest/config/secret_value.d.ts.map +1 -1
  60. package/dest/crypto/aes128/index.d.ts +2 -1
  61. package/dest/crypto/aes128/index.d.ts.map +1 -1
  62. package/dest/crypto/aes128/index.js +11 -2
  63. package/dest/crypto/bls/bn254_keystore.d.ts +10 -177
  64. package/dest/crypto/bls/bn254_keystore.d.ts.map +1 -1
  65. package/dest/crypto/bls/bn254_keystore.js +22 -34
  66. package/dest/crypto/poseidon/index.d.ts +1 -1
  67. package/dest/crypto/poseidon/index.d.ts.map +1 -1
  68. package/dest/crypto/poseidon/index.js +40 -33
  69. package/dest/crypto/schnorr/index.d.ts +8 -7
  70. package/dest/crypto/schnorr/index.d.ts.map +1 -1
  71. package/dest/crypto/schnorr/index.js +6 -6
  72. package/dest/crypto/schnorr/signature.d.ts +9 -29
  73. package/dest/crypto/schnorr/signature.d.ts.map +1 -1
  74. package/dest/crypto/schnorr/signature.js +20 -36
  75. package/dest/curves/bls12/field.d.ts +3 -3
  76. package/dest/curves/bls12/field.d.ts.map +1 -1
  77. package/dest/curves/bls12/field.js +0 -5
  78. package/dest/curves/bls12/point.d.ts +2 -2
  79. package/dest/curves/bls12/point.d.ts.map +1 -1
  80. package/dest/curves/bn254/field.d.ts +23 -19
  81. package/dest/curves/bn254/field.d.ts.map +1 -1
  82. package/dest/curves/bn254/field.js +23 -17
  83. package/dest/curves/grumpkin/point.d.ts +14 -28
  84. package/dest/curves/grumpkin/point.d.ts.map +1 -1
  85. package/dest/curves/grumpkin/point.js +29 -43
  86. package/dest/eth-address/index.d.ts +2 -2
  87. package/dest/eth-address/index.d.ts.map +1 -1
  88. package/dest/eth-address/index.js +0 -3
  89. package/dest/eth-signature/eth_signature.d.ts +2 -2
  90. package/dest/eth-signature/eth_signature.d.ts.map +1 -1
  91. package/dest/fifo/fifo_frame_reader.d.ts +41 -0
  92. package/dest/fifo/fifo_frame_reader.d.ts.map +1 -0
  93. package/dest/fifo/fifo_frame_reader.js +74 -0
  94. package/dest/fifo/index.d.ts +2 -0
  95. package/dest/fifo/index.d.ts.map +1 -0
  96. package/dest/fifo/index.js +1 -0
  97. package/dest/fifo_set/fifo_set.d.ts +15 -0
  98. package/dest/fifo_set/fifo_set.d.ts.map +1 -0
  99. package/dest/fifo_set/fifo_set.js +39 -0
  100. package/dest/fifo_set/index.d.ts +2 -0
  101. package/dest/fifo_set/index.d.ts.map +1 -0
  102. package/dest/fifo_set/index.js +1 -0
  103. package/dest/iterable/first.d.ts +8 -0
  104. package/dest/iterable/first.d.ts.map +1 -0
  105. package/dest/iterable/first.js +11 -0
  106. package/dest/iterable/index.d.ts +2 -1
  107. package/dest/iterable/index.d.ts.map +1 -1
  108. package/dest/iterable/index.js +1 -0
  109. package/dest/json-rpc/client/fetch.d.ts +8 -3
  110. package/dest/json-rpc/client/fetch.d.ts.map +1 -1
  111. package/dest/json-rpc/client/fetch.js +11 -7
  112. package/dest/json-rpc/client/safe_json_rpc_client.d.ts +1 -1
  113. package/dest/json-rpc/client/safe_json_rpc_client.d.ts.map +1 -1
  114. package/dest/json-rpc/client/safe_json_rpc_client.js +2 -2
  115. package/dest/json-rpc/client/undici.d.ts +14 -3
  116. package/dest/json-rpc/client/undici.d.ts.map +1 -1
  117. package/dest/json-rpc/client/undici.js +47 -14
  118. package/dest/json-rpc/fixtures/test_state.d.ts +4 -8
  119. package/dest/json-rpc/fixtures/test_state.d.ts.map +1 -1
  120. package/dest/json-rpc/fixtures/test_state.js +57 -17
  121. package/dest/json-rpc/server/safe_json_rpc_server.d.ts +49 -11
  122. package/dest/json-rpc/server/safe_json_rpc_server.d.ts.map +1 -1
  123. package/dest/json-rpc/server/safe_json_rpc_server.js +159 -40
  124. package/dest/log/aws-logger-config.d.ts +8 -0
  125. package/dest/log/aws-logger-config.d.ts.map +1 -0
  126. package/dest/log/aws-logger-config.js +55 -0
  127. package/dest/log/pino-logger.d.ts +1 -1
  128. package/dest/log/pino-logger.d.ts.map +1 -1
  129. package/dest/log/pino-logger.js +29 -8
  130. package/dest/noir/noir_package_config.d.ts +19 -104
  131. package/dest/noir/noir_package_config.d.ts.map +1 -1
  132. package/dest/noir/noir_package_config.js +1 -1
  133. package/dest/promise/running-promise.d.ts +8 -2
  134. package/dest/promise/running-promise.d.ts.map +1 -1
  135. package/dest/promise/running-promise.js +17 -5
  136. package/dest/promise/utils.d.ts +14 -1
  137. package/dest/promise/utils.d.ts.map +1 -1
  138. package/dest/promise/utils.js +20 -0
  139. package/dest/queue/batch_queue.d.ts +1 -1
  140. package/dest/queue/batch_queue.d.ts.map +1 -1
  141. package/dest/queue/batch_queue.js +1 -0
  142. package/dest/retry/index.d.ts +31 -3
  143. package/dest/retry/index.d.ts.map +1 -1
  144. package/dest/retry/index.js +44 -2
  145. package/dest/schemas/api.d.ts +12 -10
  146. package/dest/schemas/api.d.ts.map +1 -1
  147. package/dest/schemas/api.js +7 -1
  148. package/dest/schemas/parse.d.ts +4 -4
  149. package/dest/schemas/parse.d.ts.map +1 -1
  150. package/dest/schemas/parse.js +6 -5
  151. package/dest/schemas/schemas.d.ts +15 -15
  152. package/dest/schemas/types.d.ts +3 -3
  153. package/dest/schemas/types.d.ts.map +1 -1
  154. package/dest/schemas/utils.d.ts +7 -11
  155. package/dest/schemas/utils.d.ts.map +1 -1
  156. package/dest/schemas/utils.js +2 -18
  157. package/dest/serialize/buffer_reader.d.ts +1 -1
  158. package/dest/serialize/buffer_reader.d.ts.map +1 -1
  159. package/dest/serialize/buffer_reader.js +5 -0
  160. package/dest/serialize/buffer_sink.d.ts +134 -0
  161. package/dest/serialize/buffer_sink.d.ts.map +1 -0
  162. package/dest/serialize/buffer_sink.js +297 -0
  163. package/dest/serialize/index.d.ts +2 -1
  164. package/dest/serialize/index.d.ts.map +1 -1
  165. package/dest/serialize/index.js +1 -0
  166. package/dest/serialize/serialize.d.ts +1 -32
  167. package/dest/serialize/serialize.d.ts.map +1 -1
  168. package/dest/serialize/serialize.js +0 -21
  169. package/dest/string/index.js +1 -1
  170. package/dest/testing/files/index.d.ts +2 -3
  171. package/dest/testing/files/index.d.ts.map +1 -1
  172. package/dest/testing/files/index.js +1 -2
  173. package/dest/timer/index.d.ts +2 -2
  174. package/dest/timer/index.d.ts.map +1 -1
  175. package/dest/timer/index.js +1 -1
  176. package/dest/timer/timeout.d.ts +3 -1
  177. package/dest/timer/timeout.d.ts.map +1 -1
  178. package/dest/timer/timeout.js +26 -0
  179. package/dest/transport/dispatch/create_dispatch_proxy.d.ts +11 -2
  180. package/dest/transport/dispatch/create_dispatch_proxy.d.ts.map +1 -1
  181. package/dest/transport/index.d.ts +1 -2
  182. package/dest/transport/index.d.ts.map +1 -1
  183. package/dest/transport/index.js +0 -1
  184. package/dest/trees/balanced_merkle_tree_root.d.ts +2 -3
  185. package/dest/trees/balanced_merkle_tree_root.d.ts.map +1 -1
  186. package/dest/trees/balanced_merkle_tree_root.js +2 -3
  187. package/dest/trees/hasher.d.ts +3 -2
  188. package/dest/trees/hasher.d.ts.map +1 -1
  189. package/dest/trees/hasher.js +5 -5
  190. package/dest/trees/indexed_merkle_tree_calculator.d.ts +1 -1
  191. package/dest/trees/indexed_merkle_tree_calculator.d.ts.map +1 -1
  192. package/dest/trees/indexed_merkle_tree_calculator.js +5 -1
  193. package/dest/trees/membership_witness.d.ts +2 -6
  194. package/dest/trees/membership_witness.d.ts.map +1 -1
  195. package/dest/trees/membership_witness.js +0 -9
  196. package/dest/trees/merkle_tree_calculator.d.ts +4 -2
  197. package/dest/trees/merkle_tree_calculator.d.ts.map +1 -1
  198. package/dest/trees/merkle_tree_calculator.js +1 -5
  199. package/dest/trees/sibling_path.d.ts +13 -14
  200. package/dest/trees/sibling_path.d.ts.map +1 -1
  201. package/dest/trees/sibling_path.js +23 -28
  202. package/dest/trees/unbalanced_merkle_tree_root.d.ts +2 -3
  203. package/dest/trees/unbalanced_merkle_tree_root.d.ts.map +1 -1
  204. package/dest/trees/unbalanced_merkle_tree_root.js +2 -3
  205. package/dest/types/index.d.ts +23 -1
  206. package/dest/types/index.d.ts.map +1 -1
  207. package/dest/types/index.js +15 -0
  208. package/package.json +6 -4
  209. package/src/bigint-buffer/index.ts +6 -1
  210. package/src/branded-types/block_number.ts +20 -2
  211. package/src/branded-types/buffer32_hash.ts +38 -0
  212. package/src/branded-types/checkpoint_number.ts +16 -1
  213. package/src/branded-types/epoch.ts +1 -1
  214. package/src/branded-types/index.ts +1 -0
  215. package/src/branded-types/index_within_checkpoint.ts +1 -1
  216. package/src/branded-types/slot.ts +6 -1
  217. package/src/buffer/buffer16.ts +3 -0
  218. package/src/buffer/buffer32.ts +39 -68
  219. package/src/buffer/index.ts +1 -0
  220. package/src/buffer/utils.ts +8 -0
  221. package/src/collection/array.ts +34 -0
  222. package/src/collection/index.ts +2 -0
  223. package/src/collection/lru_map.ts +143 -0
  224. package/src/collection/lru_set.ts +115 -0
  225. package/src/committable/committable.ts +1 -1
  226. package/src/config/env_var.ts +65 -25
  227. package/src/config/index.ts +143 -122
  228. package/src/config/network_config.ts +2 -0
  229. package/src/config/network_name.ts +2 -5
  230. package/src/config/secret_value.ts +1 -1
  231. package/src/crypto/aes128/index.ts +11 -2
  232. package/src/crypto/bls/bn254_keystore.ts +33 -43
  233. package/src/crypto/poseidon/index.ts +42 -34
  234. package/src/crypto/schnorr/index.ts +9 -8
  235. package/src/crypto/schnorr/signature.ts +17 -46
  236. package/src/curves/bls12/field.ts +0 -7
  237. package/src/curves/bn254/field.ts +35 -34
  238. package/src/curves/grumpkin/point.ts +23 -40
  239. package/src/eth-address/index.ts +0 -4
  240. package/src/fifo/fifo_frame_reader.ts +98 -0
  241. package/src/fifo/index.ts +1 -0
  242. package/src/fifo_set/fifo_set.ts +52 -0
  243. package/src/fifo_set/index.ts +1 -0
  244. package/src/iterable/first.ts +14 -0
  245. package/src/iterable/index.ts +1 -0
  246. package/src/json-rpc/client/fetch.ts +19 -5
  247. package/src/json-rpc/client/safe_json_rpc_client.ts +2 -2
  248. package/src/json-rpc/client/undici.ts +54 -12
  249. package/src/json-rpc/fixtures/test_state.ts +10 -10
  250. package/src/json-rpc/server/safe_json_rpc_server.ts +204 -47
  251. package/src/log/aws-logger-config.ts +32 -0
  252. package/src/log/pino-logger.ts +33 -6
  253. package/src/noir/noir_package_config.ts +32 -20
  254. package/src/promise/running-promise.ts +20 -7
  255. package/src/promise/utils.ts +31 -0
  256. package/src/queue/batch_queue.ts +1 -0
  257. package/src/retry/index.ts +66 -4
  258. package/src/schemas/api.ts +25 -25
  259. package/src/schemas/parse.ts +9 -6
  260. package/src/schemas/schemas.ts +4 -4
  261. package/src/schemas/types.ts +2 -2
  262. package/src/schemas/utils.ts +4 -38
  263. package/src/serialize/buffer_reader.ts +5 -0
  264. package/src/serialize/buffer_sink.ts +350 -0
  265. package/src/serialize/index.ts +1 -0
  266. package/src/serialize/serialize.ts +0 -50
  267. package/src/string/index.ts +1 -1
  268. package/src/testing/files/index.ts +1 -2
  269. package/src/timer/index.ts +1 -1
  270. package/src/timer/timeout.ts +31 -0
  271. package/src/transport/dispatch/create_dispatch_proxy.ts +11 -1
  272. package/src/transport/index.ts +0 -1
  273. package/src/trees/balanced_merkle_tree_root.ts +2 -5
  274. package/src/trees/hasher.ts +6 -3
  275. package/src/trees/indexed_merkle_tree_calculator.ts +5 -1
  276. package/src/trees/membership_witness.ts +0 -8
  277. package/src/trees/merkle_tree_calculator.ts +4 -10
  278. package/src/trees/sibling_path.ts +24 -30
  279. package/src/trees/unbalanced_merkle_tree_root.ts +2 -5
  280. package/src/types/index.ts +47 -0
  281. package/dest/crypto/serialize.d.ts +0 -51
  282. package/dest/crypto/serialize.d.ts.map +0 -1
  283. package/dest/crypto/serialize.js +0 -68
  284. package/dest/transport/dispatch/create_dispatch_fn.d.ts +0 -25
  285. package/dest/transport/dispatch/create_dispatch_fn.d.ts.map +0 -1
  286. package/dest/transport/dispatch/create_dispatch_fn.js +0 -17
  287. package/src/crypto/serialize.ts +0 -85
  288. package/src/transport/dispatch/create_dispatch_fn.ts +0 -35
@@ -0,0 +1,52 @@
1
+ /** A Set capped to a fixed number of entries, evicting the oldest inserted value when full. */
2
+ export class FifoSet<T> extends Set<T> {
3
+ private _limit: number | undefined;
4
+
5
+ private constructor(values?: Iterable<T>) {
6
+ super(values);
7
+ }
8
+
9
+ /** Creates a bounded set with a positive integer limit. */
10
+ static withLimit<T>(limit: number, values?: Iterable<T>): FifoSet<T> {
11
+ if (!Number.isSafeInteger(limit) || limit <= 0) {
12
+ throw new TypeError(`FifoSet limit must be a positive safe integer: ${limit}`);
13
+ }
14
+
15
+ const set = new FifoSet(values);
16
+ set._limit = limit;
17
+ set.compact();
18
+
19
+ return set;
20
+ }
21
+
22
+ override add(value: T): this {
23
+ super.add(value);
24
+ this.compact();
25
+ return this;
26
+ }
27
+
28
+ /** Maximum number of entries retained by this set. */
29
+ public get limit(): number {
30
+ return this._limit ?? Infinity;
31
+ }
32
+
33
+ /** Evicts oldest entries until the set is within its limit. */
34
+ public compact(): void {
35
+ while (this.size > this.limit) {
36
+ const head = this.values().next();
37
+ if (head.done) {
38
+ return;
39
+ }
40
+ this.delete(head.value);
41
+ }
42
+ }
43
+
44
+ /** Adds a value only if it is absent, returning whether the set changed. */
45
+ public addIfAbsent(value: T): boolean {
46
+ if (this.has(value)) {
47
+ return false;
48
+ }
49
+ this.add(value);
50
+ return true;
51
+ }
52
+ }
@@ -0,0 +1 @@
1
+ export * from './fifo_set.js';
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Returns the first entry of an iterable, or undefined if it yields none, closing the underlying
3
+ * iterator either way. Use this instead of calling `.next()` once and abandoning the iterator:
4
+ * an abandoned generator never runs its finally blocks, so any resource it holds is leaked — e.g.
5
+ * a kv-store iterator's LMDB cursor, where enough leaks deadlock the store.
6
+ */
7
+ export async function first<T>(
8
+ iterator: Iterable<T> | AsyncIterableIterator<T> | AsyncIterable<T> | IterableIterator<T>,
9
+ ): Promise<T | undefined> {
10
+ for await (const i of iterator) {
11
+ return i;
12
+ }
13
+ return undefined;
14
+ }
@@ -3,5 +3,6 @@ export * from './filter.js';
3
3
  export * from './sort.js';
4
4
  export * from './take.js';
5
5
  export * from './all.js';
6
+ export * from './first.js';
6
7
  export * from './peek.js';
7
8
  export * from './toArray.js';
@@ -13,6 +13,10 @@ export type JsonRpcFetch = (
13
13
  noRetry?: boolean,
14
14
  ) => Promise<{ response: any; headers: { get: (header: string) => string | null | undefined } }>;
15
15
 
16
+ export type JsonRpcFetchConfig = {
17
+ credentials?: RequestCredentials;
18
+ };
19
+
16
20
  /**
17
21
  * A normal fetch function that does not retry.
18
22
  * Alternatives are a fetch function with retries, or a mocked fetch.
@@ -21,6 +25,7 @@ export type JsonRpcFetch = (
21
25
  * @param body - The RPC payload.
22
26
  * @param noRetry - Whether to throw a `NoRetryError` in case the response is a 5xx error and the body contains an error
23
27
  * message (see `retry` function for more details).
28
+ * @param config - Fetch transport configuration.
24
29
  * @returns The parsed JSON response, or throws an error.
25
30
  */
26
31
  export async function defaultFetch(
@@ -28,6 +33,7 @@ export async function defaultFetch(
28
33
  body: unknown,
29
34
  extraHeaders: Record<string, string> = {},
30
35
  noRetry = false,
36
+ config: JsonRpcFetchConfig = {},
31
37
  ): Promise<{ response: any; headers: { get: (header: string) => string | null | undefined } }> {
32
38
  log.debug(format(`JsonRpcClient.fetch`, host, '->', body));
33
39
  let resp: Response;
@@ -36,6 +42,7 @@ export async function defaultFetch(
36
42
  method: 'POST',
37
43
  body: jsonStringify(body),
38
44
  headers: { 'content-type': 'application/json', ...extraHeaders },
45
+ credentials: config.credentials,
39
46
  });
40
47
  } catch (err) {
41
48
  const errorMessage = `Error fetching from host ${host}: ${inspect(err)}`;
@@ -43,17 +50,18 @@ export async function defaultFetch(
43
50
  }
44
51
 
45
52
  let responseJson;
53
+ const responseText = await resp.text();
46
54
  try {
47
- responseJson = await resp.json();
55
+ responseJson = JSON.parse(responseText);
48
56
  } catch {
49
57
  if (!resp.ok) {
50
58
  throw new Error(resp.statusText);
51
59
  }
52
- throw new Error(`Failed to parse body as JSON: ${await resp.text()}`);
60
+ throw new Error(`Failed to parse body as JSON: ${responseText}`);
53
61
  }
54
62
 
55
63
  if (!resp.ok) {
56
- const errorMessage = `Error ${resp.status} from server ${host}: ${responseJson.error.message}`;
64
+ const errorMessage = `Error ${resp.status} from server ${host}: ${responseJson?.error?.message ?? JSON.stringify(responseJson)}`;
57
65
  if (noRetry || (resp.status >= 400 && resp.status < 500)) {
58
66
  throw new NoRetryError(errorMessage);
59
67
  } else {
@@ -69,12 +77,18 @@ export async function defaultFetch(
69
77
  * @param retries - Sequence of intervals (in seconds) to retry.
70
78
  * @param noRetry - Whether to stop retries on server errors.
71
79
  * @param log - Optional logger for logging attempts.
80
+ * @param config - Fetch transport configuration.
72
81
  * @returns A fetch function.
73
82
  */
74
- export function makeFetch(retries: number[], defaultNoRetry: boolean, log?: Logger): typeof defaultFetch {
83
+ export function makeFetch(
84
+ retries: number[],
85
+ defaultNoRetry: boolean,
86
+ log?: Logger,
87
+ config: JsonRpcFetchConfig = {},
88
+ ): JsonRpcFetch {
75
89
  return async (host: string, body: unknown, extraHeaders: Record<string, string> = {}, noRetry?: boolean) => {
76
90
  return await retry(
77
- () => defaultFetch(host, body, extraHeaders, noRetry ?? defaultNoRetry),
91
+ () => defaultFetch(host, body, extraHeaders, noRetry ?? defaultNoRetry, config),
78
92
  `JsonRpcClient request to ${host}`,
79
93
  makeBackoff(retries),
80
94
  log,
@@ -2,7 +2,7 @@ import { format } from 'util';
2
2
 
3
3
  import { type Logger, createLogger } from '../../log/pino-logger.js';
4
4
  import { type PromiseWithResolvers, promiseWithResolvers } from '../../promise/utils.js';
5
- import { type ApiSchema, type ApiSchemaFor, schemaHasMethod } from '../../schemas/api.js';
5
+ import { type ApiSchema, type ApiSchemaFor, getSchemaReturnType, schemaHasMethod } from '../../schemas/api.js';
6
6
  import { jsonStringify } from '../convert.js';
7
7
  import { type JsonRpcFetch, defaultFetch } from './fetch.js';
8
8
 
@@ -236,7 +236,7 @@ export function createSafeJsonRpcClient<T extends object>(
236
236
  if ([null, undefined, 'null', 'undefined'].includes(response.result)) {
237
237
  return;
238
238
  }
239
- return (schema as ApiSchema)[methodName].returnType().parseAsync(response.result);
239
+ return getSchemaReturnType((schema as ApiSchema)[methodName]).parseAsync(response.result);
240
240
  };
241
241
 
242
242
  const clientId = nextClientId++;
@@ -17,24 +17,48 @@ const COMPRESSION_THRESHOLD = 1024;
17
17
 
18
18
  export { Agent };
19
19
 
20
- export function makeUndiciFetch(client = new Agent()): JsonRpcFetch {
20
+ /** Asynchronous cookie storage. */
21
+ export interface CookieJar {
22
+ getCookieString(url: string): Promise<string>;
23
+ setCookie(cookie: string, url: string): Promise<unknown>;
24
+ }
25
+
26
+ /**
27
+ * Creates an Undici JSON-RPC transport.
28
+ * @param client - Dispatcher used to make requests.
29
+ * @param cookieJar - Optional application-owned cookie storage. Cookies are ignored when omitted.
30
+ * @returns A JSON-RPC fetch implementation.
31
+ */
32
+ export function makeUndiciFetch(client: Dispatcher = new Agent(), cookieJar?: CookieJar): JsonRpcFetch {
21
33
  return async (host: string, body: unknown, extraHeaders: Record<string, string> = {}, noRetry = false) => {
22
34
  log.trace(`JsonRpcClient.fetch: ${host}`, { host, body });
35
+ const requestUrl = new URL(host);
36
+ requestUrl.hash = '';
23
37
  let resp: Dispatcher.ResponseData;
24
38
  try {
39
+ const headers = new Headers();
40
+ for (const [name, value] of Object.entries(extraHeaders)) {
41
+ headers.append(name, value);
42
+ }
43
+ const cookie = await cookieJar?.getCookieString(requestUrl.href);
44
+ if (cookie) {
45
+ headers.append('cookie', cookie);
46
+ }
25
47
  const jsonBody = Buffer.from(jsonStringify(body));
26
48
  const shouldCompress = jsonBody.length >= COMPRESSION_THRESHOLD;
49
+ headers.set('content-type', 'application/json');
50
+ if (shouldCompress) {
51
+ headers.set('content-encoding', 'gzip');
52
+ }
53
+ headers.set('accept-encoding', 'gzip');
54
+ const requestHeaders: string[] = [];
55
+ headers.forEach((value, name) => requestHeaders.push(name, value));
27
56
  resp = await client.request({
28
57
  method: 'POST',
29
- origin: new URL(host),
30
- path: '/',
58
+ origin: requestUrl.origin,
59
+ path: `${requestUrl.pathname}${requestUrl.search}`,
31
60
  body: shouldCompress ? await gzip(jsonBody) : jsonBody,
32
- headers: {
33
- ...extraHeaders,
34
- 'content-type': 'application/json',
35
- ...(shouldCompress && { 'content-encoding': 'gzip' }),
36
- 'accept-encoding': 'gzip',
37
- },
61
+ headers: requestHeaders,
38
62
  });
39
63
  } catch (err) {
40
64
  const errorMessage = `Error fetching from host ${host}: ${String(err)}`;
@@ -44,18 +68,36 @@ export function makeUndiciFetch(client = new Agent()): JsonRpcFetch {
44
68
  let responseJson: any;
45
69
  const responseOk = resp.statusCode >= 200 && resp.statusCode <= 299;
46
70
  const contentEncoding = resp.headers['content-encoding'];
71
+ let responseText: string;
47
72
  try {
48
73
  if (contentEncoding === 'gzip') {
49
74
  const jsonBuffer = await gunzip(await resp.body.arrayBuffer());
50
- responseJson = JSON.parse(jsonBuffer.toString('utf-8'));
75
+ responseText = jsonBuffer.toString('utf-8');
51
76
  } else {
52
- responseJson = await resp.body.json();
77
+ responseText = await resp.body.text();
53
78
  }
79
+ } catch (err) {
80
+ if (!responseOk) {
81
+ throw new Error('HTTP ' + resp.statusCode);
82
+ }
83
+ throw new Error(`Failed to read response body. encoding: ${contentEncoding}, error: ${String(err)}`);
84
+ }
85
+
86
+ if (cookieJar) {
87
+ const setCookieHeaders = resp.headers['set-cookie'];
88
+ const cookies = typeof setCookieHeaders === 'string' ? [setCookieHeaders] : (setCookieHeaders ?? []);
89
+ for (const cookie of cookies) {
90
+ await cookieJar.setCookie(cookie, requestUrl.href);
91
+ }
92
+ }
93
+
94
+ try {
95
+ responseJson = JSON.parse(responseText);
54
96
  } catch {
55
97
  if (!responseOk) {
56
98
  throw new Error('HTTP ' + resp.statusCode);
57
99
  }
58
- throw new Error(`Failed to parse body as JSON. encoding: ${contentEncoding}, body: ${await resp.body.text()}`);
100
+ throw new Error(`Failed to parse body as JSON. encoding: ${contentEncoding}, body: ${responseText}`);
59
101
  }
60
102
 
61
103
  if (!responseOk) {
@@ -130,14 +130,14 @@ export class TestState implements TestStateApi {
130
130
  }
131
131
 
132
132
  export const TestStateSchema: ApiSchemaFor<TestStateApi> = {
133
- getNote: z.function().args(z.number()).returns(TestNote.schema.optional()),
134
- getNotes: z.function().args(optional(schemas.Integer)).returns(z.array(TestNote.schema)),
135
- getNotes2: z.function().args(optional(schemas.BigInt)).returns(z.array(TestNote.schema)),
136
- getNotes3: z.function().args(optional(schemas.Integer)).returns(z.array(TestNote.schema)),
137
- clear: z.function().returns(z.void()),
138
- addNotes: z.function().args(z.array(TestNote.schema)).returns(z.array(TestNote.schema)),
139
- fail: z.function().returns(z.void()),
140
- count: z.function().returns(z.number()),
141
- getStatus: z.function().returns(z.object({ status: z.string(), count: schemas.BigInt })),
142
- getTuple: z.function().returns(z.tuple([z.string(), optional(z.string()), z.number()])),
133
+ getNote: z.function({ input: z.tuple([z.number()]), output: TestNote.schema.optional() }),
134
+ getNotes: z.function({ input: z.tuple([optional(schemas.Integer)]), output: z.array(TestNote.schema) }),
135
+ getNotes2: z.function({ input: z.tuple([optional(schemas.BigInt)]), output: z.array(TestNote.schema) }),
136
+ getNotes3: z.function({ input: z.tuple([optional(schemas.Integer)]), output: z.array(TestNote.schema) }),
137
+ clear: z.function({ input: z.tuple([]), output: z.void() }),
138
+ addNotes: z.function({ input: z.tuple([z.array(TestNote.schema)]), output: z.array(TestNote.schema) }),
139
+ fail: z.function({ input: z.tuple([]), output: z.void() }),
140
+ count: z.function({ input: z.tuple([]), output: z.number() }),
141
+ getStatus: z.function({ input: z.tuple([]), output: z.object({ status: z.string(), count: schemas.BigInt }) }),
142
+ getTuple: z.function({ input: z.tuple([]), output: z.tuple([z.string(), optional(z.string()), z.number()]) }),
143
143
  };