@calimero-network/mero-js 19.14.1 → 19.16.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/dist/index.cjs CHANGED
@@ -42,6 +42,7 @@ __export(index_exports, {
42
42
  accountRootFromPhrase: () => accountRootFromPhrase,
43
43
  accountRootFromSecret: () => accountRootFromSecret,
44
44
  buildAuthLoginUrl: () => buildAuthLoginUrl,
45
+ callerProof: () => callerProof,
45
46
  combineSignals: () => combineSignals,
46
47
  compareSemver: () => compareSemver,
47
48
  connectCloud: () => connectCloud,
@@ -59,6 +60,7 @@ __export(index_exports, {
59
60
  createNodeAdminApiClient: () => createNodeAdminApiClient,
60
61
  createNodeAuthApiClient: () => createNodeAuthApiClient,
61
62
  createNodeHttpClient: () => createNodeHttpClient,
63
+ createProofSigner: () => createProofSigner,
62
64
  createRetryableMethod: () => createRetryableMethod,
63
65
  createTimeoutSignal: () => createTimeoutSignal,
64
66
  createUniversalHttpClient: () => createUniversalHttpClient,
@@ -77,12 +79,14 @@ __export(index_exports, {
77
79
  nodeEndpoint: () => nodeEndpoint,
78
80
  parseAuthCallback: () => parseAuthCallback,
79
81
  probeNodeHealth: () => probeNodeHealth,
82
+ requestBodyHash: () => requestBodyHash,
80
83
  routingProofHeaders: () => routingProofHeaders,
81
84
  signAccountLink: () => signAccountLink,
82
85
  signAccountLogin: () => signAccountLogin,
83
86
  signDeviceCert: () => signDeviceCert,
84
87
  signLoginStatement: () => signLoginStatement,
85
88
  signMemberJoinOp: () => signMemberJoinOp,
89
+ signRequest: () => signRequest,
86
90
  signRoutingChallenge: () => signRoutingChallenge,
87
91
  signWarrant: () => signWarrant,
88
92
  withCap: () => withCap,
@@ -178,6 +182,14 @@ function headersToRecord(headers) {
178
182
  });
179
183
  return record;
180
184
  }
185
+ function pathForProof(url) {
186
+ try {
187
+ return new URL(url).pathname;
188
+ } catch {
189
+ const query = url.indexOf("?");
190
+ return query === -1 ? url : url.slice(0, query);
191
+ }
192
+ }
181
193
  var WebHttpClient = class {
182
194
  constructor(transport) {
183
195
  this.transport = transport;
@@ -304,6 +316,16 @@ var WebHttpClient = class {
304
316
  if (init?.keepalive !== void 0) {
305
317
  requestInit.keepalive = init.keepalive;
306
318
  }
319
+ if (this.transport.getProof) {
320
+ const proof = await this.transport.getProof({
321
+ method: requestInit.method ?? "GET",
322
+ path: pathForProof(url),
323
+ body: requestInit.body
324
+ });
325
+ if (proof) {
326
+ headersObj["X-Calimero-Proof"] = proof;
327
+ }
328
+ }
307
329
  try {
308
330
  const response = await this.transport.fetch(url, requestInit);
309
331
  if (!response.ok) {
@@ -500,6 +522,7 @@ function createBrowserHttpClient(options) {
500
522
  fetch: (url, init) => globalThis.fetch(url, init),
501
523
  baseUrl: options.baseUrl,
502
524
  getAuthToken: options.getAuthToken,
525
+ getProof: options.getProof,
503
526
  onTokenRefresh: options.onTokenRefresh,
504
527
  refreshToken: options.refreshToken,
505
528
  onAuthRevoked: options.onAuthRevoked,
@@ -526,6 +549,7 @@ function createNodeHttpClient(options) {
526
549
  fetch: isDefaultFetch ? (url, init) => globalThis.fetch(url, init) : (url, init) => fetchImpl(url, init),
527
550
  baseUrl: options.baseUrl,
528
551
  getAuthToken: options.getAuthToken,
552
+ getProof: options.getProof,
529
553
  onTokenRefresh: options.onTokenRefresh,
530
554
  refreshToken: options.refreshToken,
531
555
  onAuthRevoked: options.onAuthRevoked,
@@ -2665,6 +2689,17 @@ function fromHex(value, label, expectedBytes) {
2665
2689
  }
2666
2690
  return bytes;
2667
2691
  }
2692
+ function fromHexUnsized(value, label) {
2693
+ const clean = value.trim();
2694
+ if (!/^[0-9a-fA-F]*$/.test(clean) || clean.length % 2 !== 0) {
2695
+ throw new Error(`${label} must be an even number of hex characters`);
2696
+ }
2697
+ const bytes = new Uint8Array(clean.length / 2);
2698
+ for (let i = 0; i < bytes.length; i += 1) {
2699
+ bytes[i] = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);
2700
+ }
2701
+ return bytes;
2702
+ }
2668
2703
  function u64le(value) {
2669
2704
  const out = new Uint8Array(8);
2670
2705
  new DataView(out.buffer).setBigUint64(0, BigInt(value), true);
@@ -6535,8 +6570,88 @@ async function signMemberJoinOp(input) {
6535
6570
  return hex(concat(signable, signature, unendorsed));
6536
6571
  }
6537
6572
 
6573
+ // src/request/request-sig.ts
6574
+ var SIGN_DOMAIN2 = new TextEncoder().encode("calimero.auth.request.v1");
6575
+ var BODY_DOMAIN = new TextEncoder().encode("calimero.auth.request.body.v1");
6576
+ function borshString2(value) {
6577
+ const bytes = new TextEncoder().encode(value);
6578
+ return concat(u32le(bytes.length), bytes);
6579
+ }
6580
+ async function requestBodyHash(body = new Uint8Array(0)) {
6581
+ const bytes = typeof body === "string" ? new TextEncoder().encode(body) : body;
6582
+ return domainHash(BODY_DOMAIN, [bytes]);
6583
+ }
6584
+ async function signRequest(input) {
6585
+ const key = await importSigningKey(input.signerSecret);
6586
+ const bodyHash = await requestBodyHash(input.body);
6587
+ const issuedAt = u64le(input.issuedAt);
6588
+ const expiresAt = u64le(input.expiresAt);
6589
+ const encoder = new TextEncoder();
6590
+ const preimage = await domainHash(SIGN_DOMAIN2, [
6591
+ encoder.encode(input.method),
6592
+ encoder.encode(input.path),
6593
+ bodyHash,
6594
+ issuedAt,
6595
+ expiresAt
6596
+ ]);
6597
+ const signature = new Uint8Array(
6598
+ await crypto.subtle.sign({ name: "Ed25519" }, key, preimage)
6599
+ );
6600
+ return hex(
6601
+ concat(
6602
+ borshString2(input.method),
6603
+ borshString2(input.path),
6604
+ bodyHash,
6605
+ issuedAt,
6606
+ expiresAt,
6607
+ signature
6608
+ )
6609
+ );
6610
+ }
6611
+
6612
+ // src/request/caller-proof.ts
6613
+ function callerProof(input) {
6614
+ const credential = fromHexUnsized(input.credential, "credential");
6615
+ const request = fromHexUnsized(input.request, "request signature");
6616
+ const session = input.session === void 0 ? new Uint8Array([0]) : concat(new Uint8Array([1]), fromHexUnsized(input.session, "session statement"));
6617
+ return hex(concat(credential, session, request));
6618
+ }
6619
+
6620
+ // src/request/proof-signer.ts
6621
+ function bodyBytes(body) {
6622
+ if (body === void 0 || body === null) return new Uint8Array(0);
6623
+ if (typeof body === "string") return body;
6624
+ if (body instanceof Uint8Array) return body;
6625
+ if (body instanceof ArrayBuffer) return new Uint8Array(body);
6626
+ if (ArrayBuffer.isView(body)) {
6627
+ return new Uint8Array(body.buffer, body.byteOffset, body.byteLength);
6628
+ }
6629
+ throw new Error(
6630
+ `a request-carried proof cannot commit to a ${body?.constructor?.name ?? typeof body} body: pass a string or bytes, or use a session for this call`
6631
+ );
6632
+ }
6633
+ function createProofSigner(options) {
6634
+ const ttl = options.ttlSeconds ?? 120;
6635
+ const clock = options.now ?? (() => Math.floor(Date.now() / 1e3));
6636
+ return async (request) => {
6637
+ const issuedAt = clock();
6638
+ return callerProof({
6639
+ credential: options.credential,
6640
+ session: options.session,
6641
+ request: await signRequest({
6642
+ method: request.method,
6643
+ path: request.path,
6644
+ body: bodyBytes(request.body),
6645
+ issuedAt,
6646
+ expiresAt: issuedAt + ttl,
6647
+ signerSecret: options.signerSecret
6648
+ })
6649
+ });
6650
+ };
6651
+ }
6652
+
6538
6653
  // src/login/login.ts
6539
- var SIGN_DOMAIN2 = new TextEncoder().encode("calimero.auth.login.v1");
6654
+ var SIGN_DOMAIN3 = new TextEncoder().encode("calimero.auth.login.v1");
6540
6655
  var AUDIENCE_TAG = {
6541
6656
  webOrigin: 0,
6542
6657
  codeSigningId: 1,
@@ -6575,7 +6690,7 @@ async function signLoginStatement(input) {
6575
6690
  const deviceKey = await derivePublicKey(input.deviceSecret);
6576
6691
  const issuedAt = u64le(input.issuedAt);
6577
6692
  const expiresAt = u64le(input.expiresAt);
6578
- const preimage = await domainHash(SIGN_DOMAIN2, [
6693
+ const preimage = await domainHash(SIGN_DOMAIN3, [
6579
6694
  node,
6580
6695
  audienceSigningBytes(input.audience),
6581
6696
  challenge,