@calimero-network/mero-js 19.16.0 → 19.18.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/events/sse.d.ts +2 -0
- package/dist/events/sse.js +5 -2
- package/dist/http-client/http-factory.d.ts +1 -0
- package/dist/http-client/http-factory.js +3 -3
- package/dist/index.browser.mjs +2 -2
- package/dist/index.browser.mjs.map +4 -4
- package/dist/index.cjs +209 -200
- package/dist/index.cjs.map +3 -3
- package/dist/index.mjs +209 -200
- package/dist/index.mjs.map +3 -3
- package/dist/mero-js.d.ts +37 -0
- package/dist/mero-js.js +20 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -420,9 +420,9 @@ function createHttpClient(transport) {
|
|
|
420
420
|
}
|
|
421
421
|
function createBrowserHttpClient(options) {
|
|
422
422
|
const transport = {
|
|
423
|
-
//
|
|
424
|
-
//
|
|
425
|
-
fetch: (url, init) => globalThis.fetch(url, init),
|
|
423
|
+
// globalThis.fetch must be called as a method on globalThis, not through a
|
|
424
|
+
// variable, or browsers throw "Illegal invocation".
|
|
425
|
+
fetch: (url, init) => options.fetch ? options.fetch(url, init) : globalThis.fetch(url, init),
|
|
426
426
|
baseUrl: options.baseUrl,
|
|
427
427
|
getAuthToken: options.getAuthToken,
|
|
428
428
|
getProof: options.getProof,
|
|
@@ -1913,6 +1913,196 @@ function buildAuthLoginUrl(nodeUrl, opts) {
|
|
|
1913
1913
|
return `${base}/auth/login?${params.toString()}`;
|
|
1914
1914
|
}
|
|
1915
1915
|
|
|
1916
|
+
// src/crypto/internal.ts
|
|
1917
|
+
var PKCS8_ED25519_PREFIX = new Uint8Array([
|
|
1918
|
+
48,
|
|
1919
|
+
46,
|
|
1920
|
+
2,
|
|
1921
|
+
1,
|
|
1922
|
+
0,
|
|
1923
|
+
48,
|
|
1924
|
+
5,
|
|
1925
|
+
6,
|
|
1926
|
+
3,
|
|
1927
|
+
43,
|
|
1928
|
+
101,
|
|
1929
|
+
112,
|
|
1930
|
+
4,
|
|
1931
|
+
34,
|
|
1932
|
+
4,
|
|
1933
|
+
32
|
|
1934
|
+
]);
|
|
1935
|
+
function u32le(value) {
|
|
1936
|
+
const out = new Uint8Array(4);
|
|
1937
|
+
new DataView(out.buffer).setUint32(0, value, true);
|
|
1938
|
+
return out;
|
|
1939
|
+
}
|
|
1940
|
+
function hex(bytes) {
|
|
1941
|
+
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
1942
|
+
}
|
|
1943
|
+
function fromHex(value, label, expectedBytes) {
|
|
1944
|
+
const clean = value.trim();
|
|
1945
|
+
if (!/^[0-9a-fA-F]*$/.test(clean) || clean.length !== expectedBytes * 2) {
|
|
1946
|
+
throw new Error(
|
|
1947
|
+
`${label} must be ${expectedBytes * 2} hex characters, got ${clean.length}`
|
|
1948
|
+
);
|
|
1949
|
+
}
|
|
1950
|
+
const bytes = new Uint8Array(expectedBytes);
|
|
1951
|
+
for (let i = 0; i < expectedBytes; i += 1) {
|
|
1952
|
+
bytes[i] = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);
|
|
1953
|
+
}
|
|
1954
|
+
return bytes;
|
|
1955
|
+
}
|
|
1956
|
+
function fromHexUnsized(value, label) {
|
|
1957
|
+
const clean = value.trim();
|
|
1958
|
+
if (!/^[0-9a-fA-F]*$/.test(clean) || clean.length % 2 !== 0) {
|
|
1959
|
+
throw new Error(`${label} must be an even number of hex characters`);
|
|
1960
|
+
}
|
|
1961
|
+
const bytes = new Uint8Array(clean.length / 2);
|
|
1962
|
+
for (let i = 0; i < bytes.length; i += 1) {
|
|
1963
|
+
bytes[i] = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);
|
|
1964
|
+
}
|
|
1965
|
+
return bytes;
|
|
1966
|
+
}
|
|
1967
|
+
function u64le(value) {
|
|
1968
|
+
const out = new Uint8Array(8);
|
|
1969
|
+
new DataView(out.buffer).setBigUint64(0, BigInt(value), true);
|
|
1970
|
+
return out;
|
|
1971
|
+
}
|
|
1972
|
+
function concat(...parts) {
|
|
1973
|
+
const out = new Uint8Array(parts.reduce((total, p) => total + p.length, 0));
|
|
1974
|
+
let offset = 0;
|
|
1975
|
+
for (const part of parts) {
|
|
1976
|
+
out.set(part, offset);
|
|
1977
|
+
offset += part.length;
|
|
1978
|
+
}
|
|
1979
|
+
return out;
|
|
1980
|
+
}
|
|
1981
|
+
async function domainHash(domain, parts) {
|
|
1982
|
+
const chunks = [u64le(domain.length), domain];
|
|
1983
|
+
for (const part of parts) {
|
|
1984
|
+
chunks.push(u64le(part.length), part);
|
|
1985
|
+
}
|
|
1986
|
+
return new Uint8Array(
|
|
1987
|
+
await crypto.subtle.digest("SHA-256", concat(...chunks))
|
|
1988
|
+
);
|
|
1989
|
+
}
|
|
1990
|
+
async function importSigningKey(secretHex) {
|
|
1991
|
+
const seed = fromHex(secretHex, "deviceSecret", 32);
|
|
1992
|
+
const pkcs8 = concat(PKCS8_ED25519_PREFIX, seed);
|
|
1993
|
+
try {
|
|
1994
|
+
return await crypto.subtle.importKey(
|
|
1995
|
+
"pkcs8",
|
|
1996
|
+
pkcs8,
|
|
1997
|
+
{ name: "Ed25519" },
|
|
1998
|
+
false,
|
|
1999
|
+
["sign"]
|
|
2000
|
+
);
|
|
2001
|
+
} catch (cause) {
|
|
2002
|
+
const detail = cause instanceof Error ? `: ${cause.message}` : "";
|
|
2003
|
+
throw new Error(
|
|
2004
|
+
"this runtime has no WebCrypto Ed25519, so a warrant cannot be signed here. Node 18.4+, Safari 17+, Firefox 129+ and Chrome 137+ have it; otherwise mint the warrant with `merod account warrant`" + detail
|
|
2005
|
+
);
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
async function derivePublicKey(secretHex) {
|
|
2009
|
+
const seed = fromHex(secretHex, "deviceSecret", 32);
|
|
2010
|
+
const pkcs8 = concat(PKCS8_ED25519_PREFIX, seed);
|
|
2011
|
+
const key = await crypto.subtle.importKey(
|
|
2012
|
+
"pkcs8",
|
|
2013
|
+
pkcs8,
|
|
2014
|
+
{ name: "Ed25519" },
|
|
2015
|
+
true,
|
|
2016
|
+
["sign"]
|
|
2017
|
+
);
|
|
2018
|
+
const jwk = await crypto.subtle.exportKey("jwk", key);
|
|
2019
|
+
const raw = jwk.x;
|
|
2020
|
+
return Uint8Array.from(
|
|
2021
|
+
atob(raw.replace(/-/g, "+").replace(/_/g, "/")),
|
|
2022
|
+
(c) => c.charCodeAt(0)
|
|
2023
|
+
);
|
|
2024
|
+
}
|
|
2025
|
+
|
|
2026
|
+
// src/request/request-sig.ts
|
|
2027
|
+
var SIGN_DOMAIN = new TextEncoder().encode("calimero.auth.request.v1");
|
|
2028
|
+
var BODY_DOMAIN = new TextEncoder().encode("calimero.auth.request.body.v1");
|
|
2029
|
+
function borshString(value) {
|
|
2030
|
+
const bytes = new TextEncoder().encode(value);
|
|
2031
|
+
return concat(u32le(bytes.length), bytes);
|
|
2032
|
+
}
|
|
2033
|
+
async function requestBodyHash(body = new Uint8Array(0)) {
|
|
2034
|
+
const bytes = typeof body === "string" ? new TextEncoder().encode(body) : body;
|
|
2035
|
+
return domainHash(BODY_DOMAIN, [bytes]);
|
|
2036
|
+
}
|
|
2037
|
+
async function signRequest(input) {
|
|
2038
|
+
const key = await importSigningKey(input.signerSecret);
|
|
2039
|
+
const bodyHash = await requestBodyHash(input.body);
|
|
2040
|
+
const issuedAt = u64le(input.issuedAt);
|
|
2041
|
+
const expiresAt = u64le(input.expiresAt);
|
|
2042
|
+
const encoder = new TextEncoder();
|
|
2043
|
+
const preimage = await domainHash(SIGN_DOMAIN, [
|
|
2044
|
+
encoder.encode(input.method),
|
|
2045
|
+
encoder.encode(input.path),
|
|
2046
|
+
bodyHash,
|
|
2047
|
+
issuedAt,
|
|
2048
|
+
expiresAt
|
|
2049
|
+
]);
|
|
2050
|
+
const signature = new Uint8Array(
|
|
2051
|
+
await crypto.subtle.sign({ name: "Ed25519" }, key, preimage)
|
|
2052
|
+
);
|
|
2053
|
+
return hex(
|
|
2054
|
+
concat(
|
|
2055
|
+
borshString(input.method),
|
|
2056
|
+
borshString(input.path),
|
|
2057
|
+
bodyHash,
|
|
2058
|
+
issuedAt,
|
|
2059
|
+
expiresAt,
|
|
2060
|
+
signature
|
|
2061
|
+
)
|
|
2062
|
+
);
|
|
2063
|
+
}
|
|
2064
|
+
|
|
2065
|
+
// src/request/caller-proof.ts
|
|
2066
|
+
function callerProof(input) {
|
|
2067
|
+
const credential = fromHexUnsized(input.credential, "credential");
|
|
2068
|
+
const request = fromHexUnsized(input.request, "request signature");
|
|
2069
|
+
const session = input.session === void 0 ? new Uint8Array([0]) : concat(new Uint8Array([1]), fromHexUnsized(input.session, "session statement"));
|
|
2070
|
+
return hex(concat(credential, session, request));
|
|
2071
|
+
}
|
|
2072
|
+
|
|
2073
|
+
// src/request/proof-signer.ts
|
|
2074
|
+
function bodyBytes(body) {
|
|
2075
|
+
if (body === void 0 || body === null) return new Uint8Array(0);
|
|
2076
|
+
if (typeof body === "string") return body;
|
|
2077
|
+
if (body instanceof Uint8Array) return body;
|
|
2078
|
+
if (body instanceof ArrayBuffer) return new Uint8Array(body);
|
|
2079
|
+
if (ArrayBuffer.isView(body)) {
|
|
2080
|
+
return new Uint8Array(body.buffer, body.byteOffset, body.byteLength);
|
|
2081
|
+
}
|
|
2082
|
+
throw new Error(
|
|
2083
|
+
`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`
|
|
2084
|
+
);
|
|
2085
|
+
}
|
|
2086
|
+
function createProofSigner(options) {
|
|
2087
|
+
const ttl = options.ttlSeconds ?? 120;
|
|
2088
|
+
const clock = options.now ?? (() => Math.floor(Date.now() / 1e3));
|
|
2089
|
+
return async (request) => {
|
|
2090
|
+
const issuedAt = clock();
|
|
2091
|
+
return callerProof({
|
|
2092
|
+
credential: options.credential,
|
|
2093
|
+
session: options.session,
|
|
2094
|
+
request: await signRequest({
|
|
2095
|
+
method: request.method,
|
|
2096
|
+
path: request.path,
|
|
2097
|
+
body: bodyBytes(request.body),
|
|
2098
|
+
issuedAt,
|
|
2099
|
+
expiresAt: issuedAt + ttl,
|
|
2100
|
+
signerSecret: options.signerSecret
|
|
2101
|
+
})
|
|
2102
|
+
});
|
|
2103
|
+
};
|
|
2104
|
+
}
|
|
2105
|
+
|
|
1916
2106
|
// src/rpc/index.ts
|
|
1917
2107
|
var RpcError = class extends Error {
|
|
1918
2108
|
constructor(code, message, data, type) {
|
|
@@ -1998,6 +2188,7 @@ var SseClient = class {
|
|
|
1998
2188
|
this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
|
|
1999
2189
|
this.getAuthToken = opts.getAuthToken;
|
|
2000
2190
|
this.reconnectDelayMs = opts.reconnectDelayMs ?? 3e3;
|
|
2191
|
+
this.fetchImpl = (url, init) => opts.fetch ? opts.fetch(url, init) : globalThis.fetch(url, init);
|
|
2001
2192
|
}
|
|
2002
2193
|
on(event, handler) {
|
|
2003
2194
|
const key = event;
|
|
@@ -2064,7 +2255,7 @@ var SseClient = class {
|
|
|
2064
2255
|
try {
|
|
2065
2256
|
const token = await this.getAuthToken();
|
|
2066
2257
|
const url = `${this.baseUrl}/sse`;
|
|
2067
|
-
const response = await
|
|
2258
|
+
const response = await this.fetchImpl(url, {
|
|
2068
2259
|
headers: {
|
|
2069
2260
|
"Authorization": `Bearer ${token}`,
|
|
2070
2261
|
"Accept": "text/event-stream"
|
|
@@ -2223,7 +2414,7 @@ var SseClient = class {
|
|
|
2223
2414
|
const params = {};
|
|
2224
2415
|
if (ids.contextIds && ids.contextIds.length > 0) params.contextIds = ids.contextIds;
|
|
2225
2416
|
if (ids.groupIds && ids.groupIds.length > 0) params.groupIds = ids.groupIds;
|
|
2226
|
-
const response = await
|
|
2417
|
+
const response = await this.fetchImpl(`${this.baseUrl}/sse/subscription`, {
|
|
2227
2418
|
method: "POST",
|
|
2228
2419
|
headers: {
|
|
2229
2420
|
"Authorization": `Bearer ${token}`,
|
|
@@ -2552,116 +2743,6 @@ var EphemeralClient = class {
|
|
|
2552
2743
|
}
|
|
2553
2744
|
};
|
|
2554
2745
|
|
|
2555
|
-
// src/crypto/internal.ts
|
|
2556
|
-
var PKCS8_ED25519_PREFIX = new Uint8Array([
|
|
2557
|
-
48,
|
|
2558
|
-
46,
|
|
2559
|
-
2,
|
|
2560
|
-
1,
|
|
2561
|
-
0,
|
|
2562
|
-
48,
|
|
2563
|
-
5,
|
|
2564
|
-
6,
|
|
2565
|
-
3,
|
|
2566
|
-
43,
|
|
2567
|
-
101,
|
|
2568
|
-
112,
|
|
2569
|
-
4,
|
|
2570
|
-
34,
|
|
2571
|
-
4,
|
|
2572
|
-
32
|
|
2573
|
-
]);
|
|
2574
|
-
function u32le(value) {
|
|
2575
|
-
const out = new Uint8Array(4);
|
|
2576
|
-
new DataView(out.buffer).setUint32(0, value, true);
|
|
2577
|
-
return out;
|
|
2578
|
-
}
|
|
2579
|
-
function hex(bytes) {
|
|
2580
|
-
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
2581
|
-
}
|
|
2582
|
-
function fromHex(value, label, expectedBytes) {
|
|
2583
|
-
const clean = value.trim();
|
|
2584
|
-
if (!/^[0-9a-fA-F]*$/.test(clean) || clean.length !== expectedBytes * 2) {
|
|
2585
|
-
throw new Error(
|
|
2586
|
-
`${label} must be ${expectedBytes * 2} hex characters, got ${clean.length}`
|
|
2587
|
-
);
|
|
2588
|
-
}
|
|
2589
|
-
const bytes = new Uint8Array(expectedBytes);
|
|
2590
|
-
for (let i = 0; i < expectedBytes; i += 1) {
|
|
2591
|
-
bytes[i] = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);
|
|
2592
|
-
}
|
|
2593
|
-
return bytes;
|
|
2594
|
-
}
|
|
2595
|
-
function fromHexUnsized(value, label) {
|
|
2596
|
-
const clean = value.trim();
|
|
2597
|
-
if (!/^[0-9a-fA-F]*$/.test(clean) || clean.length % 2 !== 0) {
|
|
2598
|
-
throw new Error(`${label} must be an even number of hex characters`);
|
|
2599
|
-
}
|
|
2600
|
-
const bytes = new Uint8Array(clean.length / 2);
|
|
2601
|
-
for (let i = 0; i < bytes.length; i += 1) {
|
|
2602
|
-
bytes[i] = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);
|
|
2603
|
-
}
|
|
2604
|
-
return bytes;
|
|
2605
|
-
}
|
|
2606
|
-
function u64le(value) {
|
|
2607
|
-
const out = new Uint8Array(8);
|
|
2608
|
-
new DataView(out.buffer).setBigUint64(0, BigInt(value), true);
|
|
2609
|
-
return out;
|
|
2610
|
-
}
|
|
2611
|
-
function concat(...parts) {
|
|
2612
|
-
const out = new Uint8Array(parts.reduce((total, p) => total + p.length, 0));
|
|
2613
|
-
let offset = 0;
|
|
2614
|
-
for (const part of parts) {
|
|
2615
|
-
out.set(part, offset);
|
|
2616
|
-
offset += part.length;
|
|
2617
|
-
}
|
|
2618
|
-
return out;
|
|
2619
|
-
}
|
|
2620
|
-
async function domainHash(domain, parts) {
|
|
2621
|
-
const chunks = [u64le(domain.length), domain];
|
|
2622
|
-
for (const part of parts) {
|
|
2623
|
-
chunks.push(u64le(part.length), part);
|
|
2624
|
-
}
|
|
2625
|
-
return new Uint8Array(
|
|
2626
|
-
await crypto.subtle.digest("SHA-256", concat(...chunks))
|
|
2627
|
-
);
|
|
2628
|
-
}
|
|
2629
|
-
async function importSigningKey(secretHex) {
|
|
2630
|
-
const seed = fromHex(secretHex, "deviceSecret", 32);
|
|
2631
|
-
const pkcs8 = concat(PKCS8_ED25519_PREFIX, seed);
|
|
2632
|
-
try {
|
|
2633
|
-
return await crypto.subtle.importKey(
|
|
2634
|
-
"pkcs8",
|
|
2635
|
-
pkcs8,
|
|
2636
|
-
{ name: "Ed25519" },
|
|
2637
|
-
false,
|
|
2638
|
-
["sign"]
|
|
2639
|
-
);
|
|
2640
|
-
} catch (cause) {
|
|
2641
|
-
const detail = cause instanceof Error ? `: ${cause.message}` : "";
|
|
2642
|
-
throw new Error(
|
|
2643
|
-
"this runtime has no WebCrypto Ed25519, so a warrant cannot be signed here. Node 18.4+, Safari 17+, Firefox 129+ and Chrome 137+ have it; otherwise mint the warrant with `merod account warrant`" + detail
|
|
2644
|
-
);
|
|
2645
|
-
}
|
|
2646
|
-
}
|
|
2647
|
-
async function derivePublicKey(secretHex) {
|
|
2648
|
-
const seed = fromHex(secretHex, "deviceSecret", 32);
|
|
2649
|
-
const pkcs8 = concat(PKCS8_ED25519_PREFIX, seed);
|
|
2650
|
-
const key = await crypto.subtle.importKey(
|
|
2651
|
-
"pkcs8",
|
|
2652
|
-
pkcs8,
|
|
2653
|
-
{ name: "Ed25519" },
|
|
2654
|
-
true,
|
|
2655
|
-
["sign"]
|
|
2656
|
-
);
|
|
2657
|
-
const jwk = await crypto.subtle.exportKey("jwk", key);
|
|
2658
|
-
const raw = jwk.x;
|
|
2659
|
-
return Uint8Array.from(
|
|
2660
|
-
atob(raw.replace(/-/g, "+").replace(/_/g, "/")),
|
|
2661
|
-
(c) => c.charCodeAt(0)
|
|
2662
|
-
);
|
|
2663
|
-
}
|
|
2664
|
-
|
|
2665
2746
|
// src/device-cert/device-cert.ts
|
|
2666
2747
|
var CERT_DOMAIN = new TextEncoder().encode("calimero.device.cert.v1");
|
|
2667
2748
|
var ACCOUNT_ID_DOMAIN = new TextEncoder().encode("calimero.account.genesis.v1");
|
|
@@ -5659,6 +5740,10 @@ var CloudClient = class {
|
|
|
5659
5740
|
};
|
|
5660
5741
|
|
|
5661
5742
|
// src/mero-js.ts
|
|
5743
|
+
function resolveProofSigner(config) {
|
|
5744
|
+
if (!config) return void 0;
|
|
5745
|
+
return typeof config === "function" ? config : createProofSigner(config);
|
|
5746
|
+
}
|
|
5662
5747
|
var REFRESH_LOCK_NAME = "mero-js:token-refresh";
|
|
5663
5748
|
function getLockManager() {
|
|
5664
5749
|
const nav = globalThis.navigator;
|
|
@@ -5697,8 +5782,11 @@ var MeroJs = class {
|
|
|
5697
5782
|
this.tokenData = this.tokenStore.getTokens();
|
|
5698
5783
|
}
|
|
5699
5784
|
const isTauri = typeof window !== "undefined" && "__TAURI_INTERNALS__" in window;
|
|
5785
|
+
const getProof = resolveProofSigner(this.config.requestProof);
|
|
5700
5786
|
this.httpClient = createBrowserHttpClient({
|
|
5701
5787
|
baseUrl: this.config.baseUrl,
|
|
5788
|
+
fetch: this.config.fetch,
|
|
5789
|
+
getProof,
|
|
5702
5790
|
getAuthToken: async () => {
|
|
5703
5791
|
const token = await this.getValidToken();
|
|
5704
5792
|
return token?.access_token || "";
|
|
@@ -5768,6 +5856,7 @@ var MeroJs = class {
|
|
|
5768
5856
|
if (!this.sseClient) {
|
|
5769
5857
|
this.sseClient = new SseClient({
|
|
5770
5858
|
baseUrl: this.config.baseUrl,
|
|
5859
|
+
fetch: this.config.fetch,
|
|
5771
5860
|
getAuthToken: async () => {
|
|
5772
5861
|
const token = await this.getValidToken();
|
|
5773
5862
|
return token?.access_token || "";
|
|
@@ -6052,7 +6141,7 @@ var LocalStorageTokenStore = class {
|
|
|
6052
6141
|
};
|
|
6053
6142
|
|
|
6054
6143
|
// src/warrant/warrant.ts
|
|
6055
|
-
var
|
|
6144
|
+
var SIGN_DOMAIN2 = new TextEncoder().encode("calimero.warrant.v2");
|
|
6056
6145
|
var INTENT_DOMAIN = new TextEncoder().encode("calimero.warrant.intent.v1");
|
|
6057
6146
|
var MAX_CITED_HEADS = 64;
|
|
6058
6147
|
var UNPINNED_APP = "00".repeat(32);
|
|
@@ -6077,7 +6166,7 @@ async function signWarrant(input) {
|
|
|
6077
6166
|
const commitment = await intentHash(input.method, input.argsJson);
|
|
6078
6167
|
const nonce = u64le(input.nonce);
|
|
6079
6168
|
const notAfter = u64le(input.notAfter);
|
|
6080
|
-
const preimage = await domainHash(
|
|
6169
|
+
const preimage = await domainHash(SIGN_DOMAIN2, [
|
|
6081
6170
|
context,
|
|
6082
6171
|
authorAccount,
|
|
6083
6172
|
publicKey,
|
|
@@ -6396,7 +6485,7 @@ function optionalBytes32(value, label) {
|
|
|
6396
6485
|
}
|
|
6397
6486
|
return concat(new Uint8Array([1]), new Uint8Array(value));
|
|
6398
6487
|
}
|
|
6399
|
-
function
|
|
6488
|
+
function borshString2(value) {
|
|
6400
6489
|
const bytes = new TextEncoder().encode(value);
|
|
6401
6490
|
return concat(u32le(bytes.length), bytes);
|
|
6402
6491
|
}
|
|
@@ -6420,7 +6509,7 @@ function encodeSignedInvitation(signed) {
|
|
|
6420
6509
|
// ...then the enclosing SignedGroupOpenInvitation, in declaration order.
|
|
6421
6510
|
// `inviter_account` sits between the signature and the addresses; putting it
|
|
6422
6511
|
// anywhere else still encodes 32 bytes and still verifies as nothing.
|
|
6423
|
-
|
|
6512
|
+
borshString2(signed.inviter_signature),
|
|
6424
6513
|
signed.inviter_account ? concat(new Uint8Array([1]), fromHex(signed.inviter_account, "inviter_account", 32)) : new Uint8Array([0]),
|
|
6425
6514
|
// A `Vec<String>`, so each entry is a bare borsh string. This carried an
|
|
6426
6515
|
// enum until core dropped the URL variant, and an enum writes a
|
|
@@ -6428,7 +6517,7 @@ function encodeSignedInvitation(signed) {
|
|
|
6428
6517
|
// every following byte and fail as `invalid invitation signature`, pointing
|
|
6429
6518
|
// nowhere near this line.
|
|
6430
6519
|
u32le(admitterAddrs.length),
|
|
6431
|
-
...admitterAddrs.map(
|
|
6520
|
+
...admitterAddrs.map(borshString2),
|
|
6432
6521
|
optionalBytes32(signed.application_id, "application_id"),
|
|
6433
6522
|
// Borsh order follows core's field order, where this is `bytecode_id`; the
|
|
6434
6523
|
// JSON key is `app_key`, a rename covering both directions that core pins in
|
|
@@ -6473,86 +6562,6 @@ async function signMemberJoinOp(input) {
|
|
|
6473
6562
|
return hex(concat(signable, signature, unendorsed));
|
|
6474
6563
|
}
|
|
6475
6564
|
|
|
6476
|
-
// src/request/request-sig.ts
|
|
6477
|
-
var SIGN_DOMAIN2 = new TextEncoder().encode("calimero.auth.request.v1");
|
|
6478
|
-
var BODY_DOMAIN = new TextEncoder().encode("calimero.auth.request.body.v1");
|
|
6479
|
-
function borshString2(value) {
|
|
6480
|
-
const bytes = new TextEncoder().encode(value);
|
|
6481
|
-
return concat(u32le(bytes.length), bytes);
|
|
6482
|
-
}
|
|
6483
|
-
async function requestBodyHash(body = new Uint8Array(0)) {
|
|
6484
|
-
const bytes = typeof body === "string" ? new TextEncoder().encode(body) : body;
|
|
6485
|
-
return domainHash(BODY_DOMAIN, [bytes]);
|
|
6486
|
-
}
|
|
6487
|
-
async function signRequest(input) {
|
|
6488
|
-
const key = await importSigningKey(input.signerSecret);
|
|
6489
|
-
const bodyHash = await requestBodyHash(input.body);
|
|
6490
|
-
const issuedAt = u64le(input.issuedAt);
|
|
6491
|
-
const expiresAt = u64le(input.expiresAt);
|
|
6492
|
-
const encoder = new TextEncoder();
|
|
6493
|
-
const preimage = await domainHash(SIGN_DOMAIN2, [
|
|
6494
|
-
encoder.encode(input.method),
|
|
6495
|
-
encoder.encode(input.path),
|
|
6496
|
-
bodyHash,
|
|
6497
|
-
issuedAt,
|
|
6498
|
-
expiresAt
|
|
6499
|
-
]);
|
|
6500
|
-
const signature = new Uint8Array(
|
|
6501
|
-
await crypto.subtle.sign({ name: "Ed25519" }, key, preimage)
|
|
6502
|
-
);
|
|
6503
|
-
return hex(
|
|
6504
|
-
concat(
|
|
6505
|
-
borshString2(input.method),
|
|
6506
|
-
borshString2(input.path),
|
|
6507
|
-
bodyHash,
|
|
6508
|
-
issuedAt,
|
|
6509
|
-
expiresAt,
|
|
6510
|
-
signature
|
|
6511
|
-
)
|
|
6512
|
-
);
|
|
6513
|
-
}
|
|
6514
|
-
|
|
6515
|
-
// src/request/caller-proof.ts
|
|
6516
|
-
function callerProof(input) {
|
|
6517
|
-
const credential = fromHexUnsized(input.credential, "credential");
|
|
6518
|
-
const request = fromHexUnsized(input.request, "request signature");
|
|
6519
|
-
const session = input.session === void 0 ? new Uint8Array([0]) : concat(new Uint8Array([1]), fromHexUnsized(input.session, "session statement"));
|
|
6520
|
-
return hex(concat(credential, session, request));
|
|
6521
|
-
}
|
|
6522
|
-
|
|
6523
|
-
// src/request/proof-signer.ts
|
|
6524
|
-
function bodyBytes(body) {
|
|
6525
|
-
if (body === void 0 || body === null) return new Uint8Array(0);
|
|
6526
|
-
if (typeof body === "string") return body;
|
|
6527
|
-
if (body instanceof Uint8Array) return body;
|
|
6528
|
-
if (body instanceof ArrayBuffer) return new Uint8Array(body);
|
|
6529
|
-
if (ArrayBuffer.isView(body)) {
|
|
6530
|
-
return new Uint8Array(body.buffer, body.byteOffset, body.byteLength);
|
|
6531
|
-
}
|
|
6532
|
-
throw new Error(
|
|
6533
|
-
`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`
|
|
6534
|
-
);
|
|
6535
|
-
}
|
|
6536
|
-
function createProofSigner(options) {
|
|
6537
|
-
const ttl = options.ttlSeconds ?? 120;
|
|
6538
|
-
const clock = options.now ?? (() => Math.floor(Date.now() / 1e3));
|
|
6539
|
-
return async (request) => {
|
|
6540
|
-
const issuedAt = clock();
|
|
6541
|
-
return callerProof({
|
|
6542
|
-
credential: options.credential,
|
|
6543
|
-
session: options.session,
|
|
6544
|
-
request: await signRequest({
|
|
6545
|
-
method: request.method,
|
|
6546
|
-
path: request.path,
|
|
6547
|
-
body: bodyBytes(request.body),
|
|
6548
|
-
issuedAt,
|
|
6549
|
-
expiresAt: issuedAt + ttl,
|
|
6550
|
-
signerSecret: options.signerSecret
|
|
6551
|
-
})
|
|
6552
|
-
});
|
|
6553
|
-
};
|
|
6554
|
-
}
|
|
6555
|
-
|
|
6556
6565
|
// src/login/login.ts
|
|
6557
6566
|
var SIGN_DOMAIN3 = new TextEncoder().encode("calimero.auth.login.v1");
|
|
6558
6567
|
var AUDIENCE_TAG = {
|