@corpus-core/colibri-stateless 2.0.4 → 2.0.5

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,132 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 corpus.core
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ * this software and associated documentation files (the "Software"), to deal in
7
+ * the Software without restriction, including without limitation the rights to
8
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ * the Software, and to permit persons to whom the Software is furnished to do so,
10
+ * subject to the following conditions:
11
+ *
12
+ * The above copyright notice and this permission notice shall be included in all
13
+ * copies or substantial portions of the Software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+ *
22
+ * SPDX-License-Identifier: MIT
23
+ */
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.getWasmRuntime = getWasmRuntime;
26
+ const wasm_js_1 = require("./wasm.js");
27
+ const wasm_shared_js_1 = require("./wasm_shared.js");
28
+ // The WASM runtime wraps the pointer-level Emscripten API (`C4W`) behind the
29
+ // value-level `C4Runtime` interface. The module is loaded once via `getC4w()`.
30
+ // Note: the historical c4w_* exports say "proof_ctx" where the core C API
31
+ // (and this interface) say "prover" (c4_prover_create etc.).
32
+ function createRuntime(c4w) {
33
+ return {
34
+ kind: 'wasm',
35
+ getMethodType(chainId, method, paramsJson, flags) {
36
+ const free_buffers = [];
37
+ const type = c4w._c4w_get_method_type(chainId, (0, wasm_shared_js_1.as_char_ptr)(method, c4w, free_buffers), paramsJson ? (0, wasm_shared_js_1.as_char_ptr)(paramsJson, c4w, free_buffers) : 0, flags);
38
+ free_buffers.forEach(ptr => c4w._free(ptr));
39
+ return type;
40
+ },
41
+ createProverCtx(method, argsJson, chainId, flags) {
42
+ const free_buffers = [];
43
+ const ctx = c4w._c4w_create_proof_ctx((0, wasm_shared_js_1.as_char_ptr)(method, c4w, free_buffers), (0, wasm_shared_js_1.as_char_ptr)(argsJson, c4w, free_buffers), chainId, flags);
44
+ free_buffers.forEach(ptr => c4w._free(ptr));
45
+ return ctx;
46
+ },
47
+ executeProverCtx(ctx) {
48
+ const state = (0, wasm_shared_js_1.as_json)(c4w._c4w_execute_proof_ctx(ctx), c4w, true);
49
+ // On success the JSON carries the proof as heap pointer + length
50
+ // (owned by the prover ctx); materialize it as bytes.
51
+ if (state.status === 'success')
52
+ state.result = (0, wasm_shared_js_1.as_bytes)(state.result, state.result_len, c4w);
53
+ return state;
54
+ },
55
+ freeProverCtx(ctx) {
56
+ c4w._c4w_free_proof_ctx(ctx);
57
+ },
58
+ createVerifyCtx(proof, method, argsJson, chainId, trustedCheckpoint, witnessKeys, flags, minLatestBlockTs) {
59
+ const free_buffers = [];
60
+ const ctx = c4w._c4w_create_verify_ctx((0, wasm_shared_js_1.copy_to_c)(proof, c4w, free_buffers), proof.length, (0, wasm_shared_js_1.as_char_ptr)(method, c4w, free_buffers), (0, wasm_shared_js_1.as_char_ptr)(argsJson, c4w, free_buffers), chainId, trustedCheckpoint ? (0, wasm_shared_js_1.as_char_ptr)(trustedCheckpoint, c4w, free_buffers) : 0, witnessKeys ? (0, wasm_shared_js_1.as_char_ptr)(witnessKeys, c4w, free_buffers) : 0, flags, minLatestBlockTs);
61
+ free_buffers.forEach(ptr => c4w._free(ptr));
62
+ return ctx;
63
+ },
64
+ verifyProof(ctx) {
65
+ return (0, wasm_shared_js_1.as_json)(c4w._c4w_verify_proof(ctx), c4w, true);
66
+ },
67
+ freeVerifyCtx(ctx) {
68
+ c4w._c4w_free_verify_ctx(ctx);
69
+ },
70
+ createRpcCtx(method, paramsJson, chainId, proverFlags, verifyFlags, proverMode) {
71
+ const free_buffers = [];
72
+ const ctx = c4w._c4w_create_rpc_ctx((0, wasm_shared_js_1.as_char_ptr)(method, c4w, free_buffers), (0, wasm_shared_js_1.as_char_ptr)(paramsJson, c4w, free_buffers), chainId, proverFlags, verifyFlags, proverMode);
73
+ free_buffers.forEach(ptr => c4w._free(ptr));
74
+ return ctx;
75
+ },
76
+ executeRpcCtx(ctx) {
77
+ return (0, wasm_shared_js_1.as_json)(c4w._c4w_execute_rpc_ctx(ctx), c4w, true);
78
+ },
79
+ freeRpcCtx(ctx) {
80
+ c4w._c4w_free_rpc_ctx(ctx);
81
+ },
82
+ rpcCtxSetProxyUrls(ctx, rpcUrls, beaconUrls) {
83
+ const free_buffers = [];
84
+ c4w._c4w_rpc_ctx_set_proxy_urls(ctx, (0, wasm_shared_js_1.as_char_ptr)(rpcUrls, c4w, free_buffers), (0, wasm_shared_js_1.as_char_ptr)(beaconUrls, c4w, free_buffers));
85
+ free_buffers.forEach(ptr => c4w._free(ptr));
86
+ },
87
+ rpcCtxSetWitnessKeys(ctx, keys) {
88
+ const free_buffers = [];
89
+ c4w._c4w_rpc_ctx_set_witness_keys(ctx, (0, wasm_shared_js_1.as_char_ptr)(keys, c4w, free_buffers));
90
+ free_buffers.forEach(ptr => c4w._free(ptr));
91
+ },
92
+ rpcCtxSetMinLatestBlockTs(ctx, ts) {
93
+ c4w._c4w_rpc_ctx_set_min_latest_block_ts(ctx, ts);
94
+ },
95
+ setCheckpoint(chainId, checkpoint) {
96
+ const free_buffers = [];
97
+ c4w._c4w_set_checkpoint(chainId, (0, wasm_shared_js_1.as_char_ptr)(checkpoint, c4w, free_buffers));
98
+ free_buffers.forEach(ptr => c4w._free(ptr));
99
+ },
100
+ reqSetResponse(req, data, nodeIndex) {
101
+ // ownership of the copied bytes is transferred to the C context
102
+ c4w._c4w_req_set_response(req.req_ptr, (0, wasm_shared_js_1.copy_to_c)(data, c4w), data.length, nodeIndex);
103
+ },
104
+ reqSetError(req, error, nodeIndex) {
105
+ const free_buffers = [];
106
+ c4w._c4w_req_set_error(req.req_ptr, (0, wasm_shared_js_1.as_char_ptr)(error, c4w, free_buffers), nodeIndex);
107
+ free_buffers.forEach(ptr => c4w._free(ptr));
108
+ },
109
+ decodeProof(proof) {
110
+ const free_buffers = [];
111
+ const ptr = (0, wasm_shared_js_1.copy_to_c)(proof, c4w, free_buffers);
112
+ const resultPtr = c4w._c4w_decode_proof(ptr, proof.length);
113
+ free_buffers.forEach(p => c4w._free(p));
114
+ if (!resultPtr)
115
+ throw new Error('Unknown proof format');
116
+ return (0, wasm_shared_js_1.as_json)(resultPtr, c4w, true);
117
+ },
118
+ registerStorage(storage) {
119
+ c4w.storage = storage;
120
+ },
121
+ };
122
+ }
123
+ let runtime = null;
124
+ /**
125
+ * Returns the (cached) WASM-backed runtime.
126
+ * @return Initialized WASM runtime
127
+ */
128
+ function getWasmRuntime() {
129
+ if (!runtime)
130
+ runtime = (0, wasm_js_1.getC4w)().then(createRuntime);
131
+ return runtime;
132
+ }
package/cjs/wasm.js CHANGED
@@ -23,6 +23,7 @@
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.decode_proof = exports.set_trusted_checkpoint = exports.get_prover_config_hex = exports.getC4w = exports.loadC4WModule = exports.set_wasm_url = exports.get_default_storage = exports.copy_to_c = exports.as_json = exports.as_char_ptr = exports.as_bytes = void 0;
26
+ exports.module_dir = module_dir;
26
27
  // This file is used only for the CommonJS build output. It must not use
27
28
  // `import.meta` because that is a parse error in CommonJS environments (e.g. Jest).
28
29
  const node_path_1 = require("node:path");
@@ -64,3 +65,12 @@ exports.getC4w = api.getC4w;
64
65
  exports.get_prover_config_hex = api.get_prover_config_hex;
65
66
  exports.set_trusted_checkpoint = api.set_trusted_checkpoint;
66
67
  exports.decode_proof = api.decode_proof;
68
+ /**
69
+ * Returns the directory of the compiled module. Used in Node to locate
70
+ * packaged assets (e.g. native addon prebuilds) relative to the package root.
71
+ * This CJS variant replaces `wasm.ts` (ESM, `import.meta.url`) at build time.
72
+ * @return Absolute directory path of this module
73
+ */
74
+ async function module_dir() {
75
+ return __dirname;
76
+ }
package/cjs/wasm_cjs.js CHANGED
@@ -23,6 +23,7 @@
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.decode_proof = exports.set_trusted_checkpoint = exports.get_prover_config_hex = exports.getC4w = exports.loadC4WModule = exports.set_wasm_url = exports.get_default_storage = exports.copy_to_c = exports.as_json = exports.as_char_ptr = exports.as_bytes = void 0;
26
+ exports.module_dir = module_dir;
26
27
  // This file is used only for the CommonJS build output. It must not use
27
28
  // `import.meta` because that is a parse error in CommonJS environments (e.g. Jest).
28
29
  const node_path_1 = require("node:path");
@@ -64,3 +65,12 @@ exports.getC4w = api.getC4w;
64
65
  exports.get_prover_config_hex = api.get_prover_config_hex;
65
66
  exports.set_trusted_checkpoint = api.set_trusted_checkpoint;
66
67
  exports.decode_proof = api.decode_proof;
68
+ /**
69
+ * Returns the directory of the compiled module. Used in Node to locate
70
+ * packaged assets (e.g. native addon prebuilds) relative to the package root.
71
+ * This CJS variant replaces `wasm.ts` (ESM, `import.meta.url`) at build time.
72
+ * @return Absolute directory path of this module
73
+ */
74
+ async function module_dir() {
75
+ return __dirname;
76
+ }
package/http.d.ts CHANGED
@@ -1,3 +1,26 @@
1
+ /**
2
+ * Copyright (c) 2025 corpus.core
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
5
+ * this software and associated documentation files (the "Software"), to deal in
6
+ * the Software without restriction, including without limitation the rights to
7
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8
+ * the Software, and to permit persons to whom the Software is furnished to do so,
9
+ * subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in all
12
+ * copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ *
21
+ * SPDX-License-Identifier: MIT
22
+ */
23
+ import type { C4Runtime } from './runtime.js';
1
24
  import { Config as C4Config, DataRequest } from './types.js';
2
25
  export type AcceptKind = 'json' | 'octet';
3
26
  /**
@@ -17,7 +40,8 @@ export declare function fetch_rpc(urls: string[], payload: any, as_proof?: boole
17
40
  /**
18
41
  * Handles a C4 data request by fetching from configured servers, setting the
19
42
  * response or error back into the C context, and leveraging cache if present.
43
+ * @param runtime The active runtime the request originated from
20
44
  * @param req DataRequest descriptor from C
21
45
  * @param conf Colibri configuration
22
46
  */
23
- export declare function handle_request(req: DataRequest, conf: C4Config): Promise<void>;
47
+ export declare function handle_request(runtime: C4Runtime, req: DataRequest, conf: C4Config): Promise<void>;
package/http.js CHANGED
@@ -1,26 +1,3 @@
1
- /**
2
- * Copyright (c) 2025 corpus.core
3
- *
4
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
5
- * this software and associated documentation files (the "Software"), to deal in
6
- * the Software without restriction, including without limitation the rights to
7
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8
- * the Software, and to permit persons to whom the Software is furnished to do so,
9
- * subject to the following conditions:
10
- *
11
- * The above copyright notice and this permission notice shall be included in all
12
- * copies or substantial portions of the Software.
13
- *
14
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
- *
21
- * SPDX-License-Identifier: MIT
22
- */
23
- import { getC4w, as_char_ptr, copy_to_c } from './wasm.js';
24
1
  function joinPath(base, path) {
25
2
  if (!path)
26
3
  return base;
@@ -158,11 +135,11 @@ export async function fetch_rpc(urls, payload, as_proof = false, fetchFn = globa
158
135
  /**
159
136
  * Handles a C4 data request by fetching from configured servers, setting the
160
137
  * response or error back into the C context, and leveraging cache if present.
138
+ * @param runtime The active runtime the request originated from
161
139
  * @param req DataRequest descriptor from C
162
140
  * @param conf Colibri configuration
163
141
  */
164
- export async function handle_request(req, conf) {
165
- const free_buffers = [];
142
+ export async function handle_request(runtime, req, conf) {
166
143
  // Honor a requested delay before (re-)executing (e.g. oblivious-node retry backoff).
167
144
  if (req.delay && req.delay > 0)
168
145
  await new Promise(resolve => setTimeout(resolve, req.delay));
@@ -185,7 +162,6 @@ export async function handle_request(req, conf) {
185
162
  servers = conf.rpcs || [...((conf.prover || []).map(p => p + (p.endsWith('/') ? '' : '/') + 'unverified_rpc'))];
186
163
  break;
187
164
  }
188
- const c4w = await getC4w();
189
165
  let path = (req.type == 'eth_rpc' && req.payload)
190
166
  ? `rpc: ${req.payload?.method}(${req.payload?.params.join(',')})`
191
167
  : req.url;
@@ -195,7 +171,7 @@ export async function handle_request(req, conf) {
195
171
  if (data) {
196
172
  if (conf.debug)
197
173
  log(`::: ${path} (len=${data.length} bytes) CACHED`);
198
- c4w._c4w_req_set_response(req.req_ptr, copy_to_c(data, c4w), data.length, 0);
174
+ runtime.reqSetResponse(req, data, 0);
199
175
  if (conf.onTransfer)
200
176
  conf.onTransfer(data.length, req);
201
177
  return;
@@ -205,7 +181,7 @@ export async function handle_request(req, conf) {
205
181
  const accept = req.encoding == 'json' ? 'json' : 'octet';
206
182
  const fetchFn = conf.fetch || globalThis.fetch;
207
183
  const { data, nodeIndex } = await fetch_from_servers(servers, req.url || '', req.method, req.payload, accept, req.exclude_mask, fetchFn, req.ttl);
208
- c4w._c4w_req_set_response(req.req_ptr, copy_to_c(data, c4w), data.length, nodeIndex);
184
+ runtime.reqSetResponse(req, data, nodeIndex);
209
185
  if (conf.onTransfer)
210
186
  conf.onTransfer(data.length, req);
211
187
  if (conf.debug)
@@ -215,11 +191,8 @@ export async function handle_request(req, conf) {
215
191
  }
216
192
  catch (e) {
217
193
  const last_error = (e instanceof Error) ? e.message : String(e);
218
- c4w._c4w_req_set_error(req.req_ptr, as_char_ptr(last_error, c4w, free_buffers), 0);
194
+ runtime.reqSetError(req, last_error, 0);
219
195
  if (conf.debug)
220
196
  log(`::: ${path} (Error: ${last_error})`);
221
197
  }
222
- finally {
223
- free_buffers.forEach(ptr => c4w._free(ptr));
224
- }
225
198
  }
package/index.d.ts CHANGED
@@ -20,12 +20,19 @@
20
20
  *
21
21
  * SPDX-License-Identifier: MIT
22
22
  */
23
- import { Storage as C4Storage } from "./wasm.js";
23
+ import { type Storage as C4Storage } from './runtime.js';
24
24
  import { ProviderRpcError, RequestArguments, Cache, Config as C4Config, DataRequest, MethodType as C4MethodType, ProviderMessage, ProverMode } from './types.js';
25
25
  import { EthSubscribeSubscriptionType, EthNewFilterType } from './subscriptionManager.js';
26
26
  import Strategy from './strategy.js';
27
27
  export { Strategy };
28
- export { set_wasm_url, decode_proof } from "./wasm.js";
28
+ export { set_wasm_url } from "./wasm.js";
29
+ export { getRuntime, type C4Runtime, type RuntimeStatus } from './runtime.js';
30
+ /**
31
+ * Decodes a serialized proof into its JSON representation using the active runtime.
32
+ * @param proof The proof bytes
33
+ * @return The decoded proof as JSON
34
+ */
35
+ export declare function decode_proof(proof: Uint8Array): Promise<any>;
29
36
  export { ProviderRpcError, RequestArguments, Cache, C4Config, DataRequest, C4MethodType as MethodType, ProviderMessage, EthSubscribeSubscriptionType, EthNewFilterType, ProverMode };
30
37
  export { TransactionVerifier, PrototypeProtection } from './transactionVerifier.js';
31
38
  export default class C4Client {
package/index.js CHANGED
@@ -20,8 +20,8 @@
20
20
  *
21
21
  * SPDX-License-Identifier: MIT
22
22
  */
23
- // Import the Emscripten-generated module
24
- import { as_bytes, as_char_ptr, as_json, copy_to_c, getC4w } from "./wasm.js";
23
+ // Runtime abstraction: WASM (browser/default) or native addon (Node.js entry)
24
+ import { getRuntime } from './runtime.js';
25
25
  import { EventEmitter } from './eventEmitter.js';
26
26
  import { ConnectionState } from './connectionState.js';
27
27
  import { ProviderRpcError, MethodType as C4MethodType } from './types.js';
@@ -32,7 +32,17 @@ import { TransactionVerifier, PrototypeProtection } from './transactionVerifier.
32
32
  import { fetch_rpc, handle_request } from './http.js';
33
33
  export { Strategy };
34
34
  // Public helper for controlling WASM loading behavior in Node/bundlers.
35
- export { set_wasm_url, decode_proof } from "./wasm.js";
35
+ export { set_wasm_url } from "./wasm.js";
36
+ // Runtime introspection (e.g. to check whether the native addon is active in Node).
37
+ export { getRuntime } from './runtime.js';
38
+ /**
39
+ * Decodes a serialized proof into its JSON representation using the active runtime.
40
+ * @param proof The proof bytes
41
+ * @return The decoded proof as JSON
42
+ */
43
+ export async function decode_proof(proof) {
44
+ return (await getRuntime()).decodeProof(proof);
45
+ }
36
46
  // Re-export types needed by consumers of the C4Client module
37
47
  export { ProviderRpcError, C4MethodType as MethodType };
38
48
  // Re-export transaction verification utilities
@@ -126,12 +136,9 @@ class C4Client {
126
136
  * @returns The method type
127
137
  */
128
138
  async getMethodSupport(method, args) {
129
- const c4w = await getC4w();
130
- const free_buffers = [];
139
+ const runtime = await getRuntime();
131
140
  const paramsStr = args ? JSON.stringify(args) : null;
132
- const method_type = c4w._c4w_get_method_type(BigInt(this.config.chainId), as_char_ptr(method, c4w, free_buffers), paramsStr ? as_char_ptr(paramsStr, c4w, free_buffers) : 0, this.verify_flags);
133
- free_buffers.forEach(ptr => c4w._free(ptr));
134
- return method_type;
141
+ return runtime.getMethodType(BigInt(this.config.chainId), method, paramsStr, this.verify_flags);
135
142
  }
136
143
  /**
137
144
  * Creates a proof for the given method and arguments.
@@ -140,30 +147,27 @@ class C4Client {
140
147
  * @returns The proof
141
148
  */
142
149
  async createProof(method, args) {
143
- const c4w = await getC4w();
144
- const free_buffers = [];
145
- let ctx = 0;
150
+ const runtime = await getRuntime();
151
+ let ctx = null;
146
152
  try {
147
- // Call the C function
148
- ctx = c4w._c4w_create_proof_ctx(as_char_ptr(method, c4w, free_buffers), as_char_ptr(JSON.stringify(args), c4w, free_buffers), BigInt(this.config.chainId), this.flags);
153
+ ctx = runtime.createProverCtx(method, JSON.stringify(args), BigInt(this.config.chainId), this.flags);
149
154
  while (true) {
150
- const state = as_json(c4w._c4w_execute_proof_ctx(ctx), c4w, true);
155
+ const state = runtime.executeProverCtx(ctx);
151
156
  switch (state.status) {
152
157
  case "success":
153
- return as_bytes(state.result, state.result_len, c4w);
158
+ return state.result;
154
159
  case "error":
155
160
  throw new Error(state.error);
156
161
  case "pending": {
157
- await Promise.all(state.requests.map((req) => handle_request(req, this.config)));
162
+ await Promise.all(state.requests.map((req) => handle_request(runtime, req, this.config)));
158
163
  break;
159
164
  }
160
165
  }
161
166
  }
162
167
  }
163
168
  finally {
164
- free_buffers.forEach(ptr => c4w._free(ptr));
165
169
  if (ctx)
166
- c4w._c4w_free_proof_ctx(ctx);
170
+ runtime.freeProverCtx(ctx);
167
171
  }
168
172
  }
169
173
  /**
@@ -174,20 +178,12 @@ class C4Client {
174
178
  * @returns The result
175
179
  */
176
180
  async verifyProof(method, args, proof) {
177
- const c4w = await getC4w();
178
- const free_buffers = [];
179
- let ctx = 0;
181
+ const runtime = await getRuntime();
182
+ let ctx = null;
180
183
  try {
181
- // Call the C function
182
- const checkpoint_ptr = this.config.trusted_checkpoint
183
- ? as_char_ptr(this.config.trusted_checkpoint, c4w, free_buffers)
184
- : 0;
185
- const witness_keys_ptr = this.config.checkpoint_witness_keys
186
- ? as_char_ptr(this.config.checkpoint_witness_keys, c4w, free_buffers)
187
- : 0;
188
- ctx = c4w._c4w_create_verify_ctx(copy_to_c(proof, c4w, free_buffers), proof.length, as_char_ptr(method, c4w, free_buffers), as_char_ptr(JSON.stringify(args), c4w, free_buffers), BigInt(this.config.chainId), checkpoint_ptr, witness_keys_ptr, this.verify_flags, this.get_min_latest_block_ts());
184
+ ctx = runtime.createVerifyCtx(proof, method, JSON.stringify(args), BigInt(this.config.chainId), this.config.trusted_checkpoint || null, this.config.checkpoint_witness_keys || null, this.verify_flags, this.get_min_latest_block_ts());
189
185
  while (true) {
190
- const state = as_json(c4w._c4w_verify_proof(ctx), c4w, true);
186
+ const state = runtime.verifyProof(ctx);
191
187
  switch (state.status) {
192
188
  case "success":
193
189
  return state.result;
@@ -196,16 +192,15 @@ class C4Client {
196
192
  case "error":
197
193
  throw new Error(state.error);
198
194
  case "pending": {
199
- await Promise.all(state.requests.map((req) => handle_request(req, this.config)));
195
+ await Promise.all(state.requests.map((req) => handle_request(runtime, req, this.config)));
200
196
  break;
201
197
  }
202
198
  }
203
199
  }
204
200
  }
205
201
  finally {
206
- free_buffers.forEach(ptr => c4w._free(ptr));
207
202
  if (ctx)
208
- c4w._c4w_free_verify_ctx(ctx);
203
+ runtime.freeVerifyCtx(ctx);
209
204
  }
210
205
  }
211
206
  /**
@@ -227,9 +222,8 @@ class C4Client {
227
222
  method_type = await this.getMethodSupport(method, args);
228
223
  if (method_type === C4MethodType.PROOFABLE && this.config.verify && !this.config.verify(method, args))
229
224
  return await fetch_rpc(this.config.rpcs, { method, params: args }, false, this.config.fetch);
230
- const c4w = await getC4w();
231
- const free_buffers = [];
232
- let ctx = 0;
225
+ const runtime = await getRuntime();
226
+ let ctx = null;
233
227
  try {
234
228
  const prover_mode_map = { local: 0, remote: 1, hybrid: 2, proxy: 3, light_client: 4 };
235
229
  const resolved_mode = this.config.prover_mode ?? (this.config.prover?.length ? 'remote' : 'local');
@@ -237,19 +231,16 @@ class C4Client {
237
231
  let prover_flags = this.flags;
238
232
  if (this.config.zk_proof)
239
233
  prover_flags |= (1 << 7);
240
- ctx = c4w._c4w_create_rpc_ctx(as_char_ptr(method, c4w, free_buffers), as_char_ptr(JSON.stringify(args || []), c4w, free_buffers), BigInt(this.config.chainId), prover_flags, this.verify_flags, native_mode);
241
- if (resolved_mode === 'proxy') {
242
- const rpc_csv = this.config.rpcs.join(',');
243
- const beacon_csv = this.config.beacon_apis.join(',');
244
- c4w._c4w_rpc_ctx_set_proxy_urls(ctx, as_char_ptr(rpc_csv, c4w, free_buffers), as_char_ptr(beacon_csv, c4w, free_buffers));
245
- }
234
+ ctx = runtime.createRpcCtx(method, JSON.stringify(args || []), BigInt(this.config.chainId), prover_flags, this.verify_flags, native_mode);
235
+ if (resolved_mode === 'proxy')
236
+ runtime.rpcCtxSetProxyUrls(ctx, this.config.rpcs.join(','), this.config.beacon_apis.join(','));
246
237
  if (this.config.trusted_checkpoint)
247
- c4w._c4w_set_checkpoint(BigInt(this.config.chainId), as_char_ptr(this.config.trusted_checkpoint, c4w, free_buffers));
238
+ runtime.setCheckpoint(BigInt(this.config.chainId), this.config.trusted_checkpoint);
248
239
  if (this.config.checkpoint_witness_keys)
249
- c4w._c4w_rpc_ctx_set_witness_keys(ctx, as_char_ptr(this.config.checkpoint_witness_keys, c4w, free_buffers));
250
- c4w._c4w_rpc_ctx_set_min_latest_block_ts(ctx, this.get_min_latest_block_ts());
240
+ runtime.rpcCtxSetWitnessKeys(ctx, this.config.checkpoint_witness_keys);
241
+ runtime.rpcCtxSetMinLatestBlockTs(ctx, this.get_min_latest_block_ts());
251
242
  while (true) {
252
- const state = as_json(c4w._c4w_execute_rpc_ctx(ctx), c4w, true);
243
+ const state = runtime.executeRpcCtx(ctx);
253
244
  switch (state.status) {
254
245
  case "success":
255
246
  return state.result;
@@ -263,20 +254,18 @@ class C4Client {
263
254
  }
264
255
  throw new Error(state.error);
265
256
  case "pending":
266
- await Promise.all(state.requests.map((req) => handle_request(req, this.config)));
257
+ await Promise.all(state.requests.map((req) => handle_request(runtime, req, this.config)));
267
258
  break;
268
259
  }
269
260
  }
270
261
  }
271
262
  finally {
272
- free_buffers.forEach(ptr => c4w._free(ptr));
273
263
  if (ctx)
274
- c4w._c4w_free_rpc_ctx(ctx);
264
+ runtime.freeRpcCtx(ctx);
275
265
  }
276
266
  }
277
267
  static async register_storage(storage) {
278
- const c4w = await getC4w();
279
- c4w.storage = storage;
268
+ (await getRuntime()).registerStorage(storage);
280
269
  }
281
270
  async request(args) {
282
271
  if (!this.connectionState.initialConnectionAttempted) {
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Copyright (c) 2026 corpus.core
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
5
+ * this software and associated documentation files (the "Software"), to deal in
6
+ * the Software without restriction, including without limitation the rights to
7
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8
+ * the Software, and to permit persons to whom the Software is furnished to do so,
9
+ * subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in all
12
+ * copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ *
21
+ * SPDX-License-Identifier: MIT
22
+ */
23
+ export * from './index.js';
24
+ export { default } from './index.js';
package/index.node.js ADDED
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Copyright (c) 2026 corpus.core
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
5
+ * this software and associated documentation files (the "Software"), to deal in
6
+ * the Software without restriction, including without limitation the rights to
7
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8
+ * the Software, and to permit persons to whom the Software is furnished to do so,
9
+ * subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in all
12
+ * copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ *
21
+ * SPDX-License-Identifier: MIT
22
+ */
23
+ /**
24
+ * Node.js entry point (selected via `package.json` conditional exports).
25
+ *
26
+ * Uses the native N-API addon when a prebuild for the current platform is
27
+ * available (blst with platform-optimized assembly, ~10x faster BLS pairing)
28
+ * and transparently falls back to the WASM build otherwise. Browser bundlers
29
+ * never see this file.
30
+ */
31
+ import { setRuntimeProvider } from './runtime.js';
32
+ import { getNodeRuntime } from './runtime_node.js';
33
+ setRuntimeProvider(getNodeRuntime);
34
+ export * from './index.js';
35
+ export { default } from './index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@corpus-core/colibri-stateless",
3
- "version": "2.0.4",
3
+ "version": "2.0.5",
4
4
  "description": "Colibri is a stateless and trustless ethereum client, which is optimized for the mobile apps or embedded devices, because it does not hols the state, but verifies on demand.",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -8,13 +8,20 @@
8
8
  "exports": {
9
9
  ".": {
10
10
  "types": "./index.d.ts",
11
+ "browser": "./index.js",
12
+ "node": {
13
+ "import": "./index.node.js",
14
+ "require": "./cjs/index.node.js"
15
+ },
11
16
  "import": "./index.js",
12
17
  "require": "./cjs/index.js"
13
- }
18
+ },
19
+ "./package.json": "./package.json"
14
20
  },
15
21
  "scripts": {
16
22
  "test": "npm run test:node && npm run test:webpack",
17
- "test:node": "node --test test/rpc.test.mjs test/cjs_bridge.test.mjs",
23
+ "test:node": "node --test test/rpc.test.mjs test/cjs_bridge.test.mjs test/runtime_selection.test.mjs",
24
+ "test:node:native": "node --test test/native.test.mjs",
18
25
  "test:integration": "C4_RUN_INTEGRATION=1 node --test test/integration.test.mjs",
19
26
  "test:ccip": "C4_RUN_INTEGRATION=1 node --test test/ens_ccip.test.mjs",
20
27
  "test:webpack": "npm run webpack:install && npm run webpack:build",
@@ -57,6 +64,9 @@
57
64
  "devDependencies": {
58
65
  "ethers": "^6.16.0"
59
66
  },
67
+ "overrides": {
68
+ "ws": "^8.21.3"
69
+ },
60
70
  "publishConfig": {
61
71
  "access": "public"
62
72
  }