@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.cjs
CHANGED
|
@@ -517,9 +517,9 @@ function createHttpClient(transport) {
|
|
|
517
517
|
}
|
|
518
518
|
function createBrowserHttpClient(options) {
|
|
519
519
|
const transport = {
|
|
520
|
-
//
|
|
521
|
-
//
|
|
522
|
-
fetch: (url, init) => globalThis.fetch(url, init),
|
|
520
|
+
// globalThis.fetch must be called as a method on globalThis, not through a
|
|
521
|
+
// variable, or browsers throw "Illegal invocation".
|
|
522
|
+
fetch: (url, init) => options.fetch ? options.fetch(url, init) : globalThis.fetch(url, init),
|
|
523
523
|
baseUrl: options.baseUrl,
|
|
524
524
|
getAuthToken: options.getAuthToken,
|
|
525
525
|
getProof: options.getProof,
|
|
@@ -2010,6 +2010,196 @@ function buildAuthLoginUrl(nodeUrl, opts) {
|
|
|
2010
2010
|
return `${base}/auth/login?${params.toString()}`;
|
|
2011
2011
|
}
|
|
2012
2012
|
|
|
2013
|
+
// src/crypto/internal.ts
|
|
2014
|
+
var PKCS8_ED25519_PREFIX = new Uint8Array([
|
|
2015
|
+
48,
|
|
2016
|
+
46,
|
|
2017
|
+
2,
|
|
2018
|
+
1,
|
|
2019
|
+
0,
|
|
2020
|
+
48,
|
|
2021
|
+
5,
|
|
2022
|
+
6,
|
|
2023
|
+
3,
|
|
2024
|
+
43,
|
|
2025
|
+
101,
|
|
2026
|
+
112,
|
|
2027
|
+
4,
|
|
2028
|
+
34,
|
|
2029
|
+
4,
|
|
2030
|
+
32
|
|
2031
|
+
]);
|
|
2032
|
+
function u32le(value) {
|
|
2033
|
+
const out = new Uint8Array(4);
|
|
2034
|
+
new DataView(out.buffer).setUint32(0, value, true);
|
|
2035
|
+
return out;
|
|
2036
|
+
}
|
|
2037
|
+
function hex(bytes) {
|
|
2038
|
+
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
2039
|
+
}
|
|
2040
|
+
function fromHex(value, label, expectedBytes) {
|
|
2041
|
+
const clean = value.trim();
|
|
2042
|
+
if (!/^[0-9a-fA-F]*$/.test(clean) || clean.length !== expectedBytes * 2) {
|
|
2043
|
+
throw new Error(
|
|
2044
|
+
`${label} must be ${expectedBytes * 2} hex characters, got ${clean.length}`
|
|
2045
|
+
);
|
|
2046
|
+
}
|
|
2047
|
+
const bytes = new Uint8Array(expectedBytes);
|
|
2048
|
+
for (let i = 0; i < expectedBytes; i += 1) {
|
|
2049
|
+
bytes[i] = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);
|
|
2050
|
+
}
|
|
2051
|
+
return bytes;
|
|
2052
|
+
}
|
|
2053
|
+
function fromHexUnsized(value, label) {
|
|
2054
|
+
const clean = value.trim();
|
|
2055
|
+
if (!/^[0-9a-fA-F]*$/.test(clean) || clean.length % 2 !== 0) {
|
|
2056
|
+
throw new Error(`${label} must be an even number of hex characters`);
|
|
2057
|
+
}
|
|
2058
|
+
const bytes = new Uint8Array(clean.length / 2);
|
|
2059
|
+
for (let i = 0; i < bytes.length; i += 1) {
|
|
2060
|
+
bytes[i] = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);
|
|
2061
|
+
}
|
|
2062
|
+
return bytes;
|
|
2063
|
+
}
|
|
2064
|
+
function u64le(value) {
|
|
2065
|
+
const out = new Uint8Array(8);
|
|
2066
|
+
new DataView(out.buffer).setBigUint64(0, BigInt(value), true);
|
|
2067
|
+
return out;
|
|
2068
|
+
}
|
|
2069
|
+
function concat(...parts) {
|
|
2070
|
+
const out = new Uint8Array(parts.reduce((total, p) => total + p.length, 0));
|
|
2071
|
+
let offset = 0;
|
|
2072
|
+
for (const part of parts) {
|
|
2073
|
+
out.set(part, offset);
|
|
2074
|
+
offset += part.length;
|
|
2075
|
+
}
|
|
2076
|
+
return out;
|
|
2077
|
+
}
|
|
2078
|
+
async function domainHash(domain, parts) {
|
|
2079
|
+
const chunks = [u64le(domain.length), domain];
|
|
2080
|
+
for (const part of parts) {
|
|
2081
|
+
chunks.push(u64le(part.length), part);
|
|
2082
|
+
}
|
|
2083
|
+
return new Uint8Array(
|
|
2084
|
+
await crypto.subtle.digest("SHA-256", concat(...chunks))
|
|
2085
|
+
);
|
|
2086
|
+
}
|
|
2087
|
+
async function importSigningKey(secretHex) {
|
|
2088
|
+
const seed = fromHex(secretHex, "deviceSecret", 32);
|
|
2089
|
+
const pkcs8 = concat(PKCS8_ED25519_PREFIX, seed);
|
|
2090
|
+
try {
|
|
2091
|
+
return await crypto.subtle.importKey(
|
|
2092
|
+
"pkcs8",
|
|
2093
|
+
pkcs8,
|
|
2094
|
+
{ name: "Ed25519" },
|
|
2095
|
+
false,
|
|
2096
|
+
["sign"]
|
|
2097
|
+
);
|
|
2098
|
+
} catch (cause) {
|
|
2099
|
+
const detail = cause instanceof Error ? `: ${cause.message}` : "";
|
|
2100
|
+
throw new Error(
|
|
2101
|
+
"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
|
|
2102
|
+
);
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
async function derivePublicKey(secretHex) {
|
|
2106
|
+
const seed = fromHex(secretHex, "deviceSecret", 32);
|
|
2107
|
+
const pkcs8 = concat(PKCS8_ED25519_PREFIX, seed);
|
|
2108
|
+
const key = await crypto.subtle.importKey(
|
|
2109
|
+
"pkcs8",
|
|
2110
|
+
pkcs8,
|
|
2111
|
+
{ name: "Ed25519" },
|
|
2112
|
+
true,
|
|
2113
|
+
["sign"]
|
|
2114
|
+
);
|
|
2115
|
+
const jwk = await crypto.subtle.exportKey("jwk", key);
|
|
2116
|
+
const raw = jwk.x;
|
|
2117
|
+
return Uint8Array.from(
|
|
2118
|
+
atob(raw.replace(/-/g, "+").replace(/_/g, "/")),
|
|
2119
|
+
(c) => c.charCodeAt(0)
|
|
2120
|
+
);
|
|
2121
|
+
}
|
|
2122
|
+
|
|
2123
|
+
// src/request/request-sig.ts
|
|
2124
|
+
var SIGN_DOMAIN = new TextEncoder().encode("calimero.auth.request.v1");
|
|
2125
|
+
var BODY_DOMAIN = new TextEncoder().encode("calimero.auth.request.body.v1");
|
|
2126
|
+
function borshString(value) {
|
|
2127
|
+
const bytes = new TextEncoder().encode(value);
|
|
2128
|
+
return concat(u32le(bytes.length), bytes);
|
|
2129
|
+
}
|
|
2130
|
+
async function requestBodyHash(body = new Uint8Array(0)) {
|
|
2131
|
+
const bytes = typeof body === "string" ? new TextEncoder().encode(body) : body;
|
|
2132
|
+
return domainHash(BODY_DOMAIN, [bytes]);
|
|
2133
|
+
}
|
|
2134
|
+
async function signRequest(input) {
|
|
2135
|
+
const key = await importSigningKey(input.signerSecret);
|
|
2136
|
+
const bodyHash = await requestBodyHash(input.body);
|
|
2137
|
+
const issuedAt = u64le(input.issuedAt);
|
|
2138
|
+
const expiresAt = u64le(input.expiresAt);
|
|
2139
|
+
const encoder = new TextEncoder();
|
|
2140
|
+
const preimage = await domainHash(SIGN_DOMAIN, [
|
|
2141
|
+
encoder.encode(input.method),
|
|
2142
|
+
encoder.encode(input.path),
|
|
2143
|
+
bodyHash,
|
|
2144
|
+
issuedAt,
|
|
2145
|
+
expiresAt
|
|
2146
|
+
]);
|
|
2147
|
+
const signature = new Uint8Array(
|
|
2148
|
+
await crypto.subtle.sign({ name: "Ed25519" }, key, preimage)
|
|
2149
|
+
);
|
|
2150
|
+
return hex(
|
|
2151
|
+
concat(
|
|
2152
|
+
borshString(input.method),
|
|
2153
|
+
borshString(input.path),
|
|
2154
|
+
bodyHash,
|
|
2155
|
+
issuedAt,
|
|
2156
|
+
expiresAt,
|
|
2157
|
+
signature
|
|
2158
|
+
)
|
|
2159
|
+
);
|
|
2160
|
+
}
|
|
2161
|
+
|
|
2162
|
+
// src/request/caller-proof.ts
|
|
2163
|
+
function callerProof(input) {
|
|
2164
|
+
const credential = fromHexUnsized(input.credential, "credential");
|
|
2165
|
+
const request = fromHexUnsized(input.request, "request signature");
|
|
2166
|
+
const session = input.session === void 0 ? new Uint8Array([0]) : concat(new Uint8Array([1]), fromHexUnsized(input.session, "session statement"));
|
|
2167
|
+
return hex(concat(credential, session, request));
|
|
2168
|
+
}
|
|
2169
|
+
|
|
2170
|
+
// src/request/proof-signer.ts
|
|
2171
|
+
function bodyBytes(body) {
|
|
2172
|
+
if (body === void 0 || body === null) return new Uint8Array(0);
|
|
2173
|
+
if (typeof body === "string") return body;
|
|
2174
|
+
if (body instanceof Uint8Array) return body;
|
|
2175
|
+
if (body instanceof ArrayBuffer) return new Uint8Array(body);
|
|
2176
|
+
if (ArrayBuffer.isView(body)) {
|
|
2177
|
+
return new Uint8Array(body.buffer, body.byteOffset, body.byteLength);
|
|
2178
|
+
}
|
|
2179
|
+
throw new Error(
|
|
2180
|
+
`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`
|
|
2181
|
+
);
|
|
2182
|
+
}
|
|
2183
|
+
function createProofSigner(options) {
|
|
2184
|
+
const ttl = options.ttlSeconds ?? 120;
|
|
2185
|
+
const clock = options.now ?? (() => Math.floor(Date.now() / 1e3));
|
|
2186
|
+
return async (request) => {
|
|
2187
|
+
const issuedAt = clock();
|
|
2188
|
+
return callerProof({
|
|
2189
|
+
credential: options.credential,
|
|
2190
|
+
session: options.session,
|
|
2191
|
+
request: await signRequest({
|
|
2192
|
+
method: request.method,
|
|
2193
|
+
path: request.path,
|
|
2194
|
+
body: bodyBytes(request.body),
|
|
2195
|
+
issuedAt,
|
|
2196
|
+
expiresAt: issuedAt + ttl,
|
|
2197
|
+
signerSecret: options.signerSecret
|
|
2198
|
+
})
|
|
2199
|
+
});
|
|
2200
|
+
};
|
|
2201
|
+
}
|
|
2202
|
+
|
|
2013
2203
|
// src/rpc/index.ts
|
|
2014
2204
|
var RpcError = class extends Error {
|
|
2015
2205
|
constructor(code, message, data, type) {
|
|
@@ -2095,6 +2285,7 @@ var SseClient = class {
|
|
|
2095
2285
|
this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
|
|
2096
2286
|
this.getAuthToken = opts.getAuthToken;
|
|
2097
2287
|
this.reconnectDelayMs = opts.reconnectDelayMs ?? 3e3;
|
|
2288
|
+
this.fetchImpl = (url, init) => opts.fetch ? opts.fetch(url, init) : globalThis.fetch(url, init);
|
|
2098
2289
|
}
|
|
2099
2290
|
on(event, handler) {
|
|
2100
2291
|
const key = event;
|
|
@@ -2161,7 +2352,7 @@ var SseClient = class {
|
|
|
2161
2352
|
try {
|
|
2162
2353
|
const token = await this.getAuthToken();
|
|
2163
2354
|
const url = `${this.baseUrl}/sse`;
|
|
2164
|
-
const response = await
|
|
2355
|
+
const response = await this.fetchImpl(url, {
|
|
2165
2356
|
headers: {
|
|
2166
2357
|
"Authorization": `Bearer ${token}`,
|
|
2167
2358
|
"Accept": "text/event-stream"
|
|
@@ -2320,7 +2511,7 @@ var SseClient = class {
|
|
|
2320
2511
|
const params = {};
|
|
2321
2512
|
if (ids.contextIds && ids.contextIds.length > 0) params.contextIds = ids.contextIds;
|
|
2322
2513
|
if (ids.groupIds && ids.groupIds.length > 0) params.groupIds = ids.groupIds;
|
|
2323
|
-
const response = await
|
|
2514
|
+
const response = await this.fetchImpl(`${this.baseUrl}/sse/subscription`, {
|
|
2324
2515
|
method: "POST",
|
|
2325
2516
|
headers: {
|
|
2326
2517
|
"Authorization": `Bearer ${token}`,
|
|
@@ -2649,116 +2840,6 @@ var EphemeralClient = class {
|
|
|
2649
2840
|
}
|
|
2650
2841
|
};
|
|
2651
2842
|
|
|
2652
|
-
// src/crypto/internal.ts
|
|
2653
|
-
var PKCS8_ED25519_PREFIX = new Uint8Array([
|
|
2654
|
-
48,
|
|
2655
|
-
46,
|
|
2656
|
-
2,
|
|
2657
|
-
1,
|
|
2658
|
-
0,
|
|
2659
|
-
48,
|
|
2660
|
-
5,
|
|
2661
|
-
6,
|
|
2662
|
-
3,
|
|
2663
|
-
43,
|
|
2664
|
-
101,
|
|
2665
|
-
112,
|
|
2666
|
-
4,
|
|
2667
|
-
34,
|
|
2668
|
-
4,
|
|
2669
|
-
32
|
|
2670
|
-
]);
|
|
2671
|
-
function u32le(value) {
|
|
2672
|
-
const out = new Uint8Array(4);
|
|
2673
|
-
new DataView(out.buffer).setUint32(0, value, true);
|
|
2674
|
-
return out;
|
|
2675
|
-
}
|
|
2676
|
-
function hex(bytes) {
|
|
2677
|
-
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
2678
|
-
}
|
|
2679
|
-
function fromHex(value, label, expectedBytes) {
|
|
2680
|
-
const clean = value.trim();
|
|
2681
|
-
if (!/^[0-9a-fA-F]*$/.test(clean) || clean.length !== expectedBytes * 2) {
|
|
2682
|
-
throw new Error(
|
|
2683
|
-
`${label} must be ${expectedBytes * 2} hex characters, got ${clean.length}`
|
|
2684
|
-
);
|
|
2685
|
-
}
|
|
2686
|
-
const bytes = new Uint8Array(expectedBytes);
|
|
2687
|
-
for (let i = 0; i < expectedBytes; i += 1) {
|
|
2688
|
-
bytes[i] = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);
|
|
2689
|
-
}
|
|
2690
|
-
return bytes;
|
|
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
|
-
}
|
|
2703
|
-
function u64le(value) {
|
|
2704
|
-
const out = new Uint8Array(8);
|
|
2705
|
-
new DataView(out.buffer).setBigUint64(0, BigInt(value), true);
|
|
2706
|
-
return out;
|
|
2707
|
-
}
|
|
2708
|
-
function concat(...parts) {
|
|
2709
|
-
const out = new Uint8Array(parts.reduce((total, p) => total + p.length, 0));
|
|
2710
|
-
let offset = 0;
|
|
2711
|
-
for (const part of parts) {
|
|
2712
|
-
out.set(part, offset);
|
|
2713
|
-
offset += part.length;
|
|
2714
|
-
}
|
|
2715
|
-
return out;
|
|
2716
|
-
}
|
|
2717
|
-
async function domainHash(domain, parts) {
|
|
2718
|
-
const chunks = [u64le(domain.length), domain];
|
|
2719
|
-
for (const part of parts) {
|
|
2720
|
-
chunks.push(u64le(part.length), part);
|
|
2721
|
-
}
|
|
2722
|
-
return new Uint8Array(
|
|
2723
|
-
await crypto.subtle.digest("SHA-256", concat(...chunks))
|
|
2724
|
-
);
|
|
2725
|
-
}
|
|
2726
|
-
async function importSigningKey(secretHex) {
|
|
2727
|
-
const seed = fromHex(secretHex, "deviceSecret", 32);
|
|
2728
|
-
const pkcs8 = concat(PKCS8_ED25519_PREFIX, seed);
|
|
2729
|
-
try {
|
|
2730
|
-
return await crypto.subtle.importKey(
|
|
2731
|
-
"pkcs8",
|
|
2732
|
-
pkcs8,
|
|
2733
|
-
{ name: "Ed25519" },
|
|
2734
|
-
false,
|
|
2735
|
-
["sign"]
|
|
2736
|
-
);
|
|
2737
|
-
} catch (cause) {
|
|
2738
|
-
const detail = cause instanceof Error ? `: ${cause.message}` : "";
|
|
2739
|
-
throw new Error(
|
|
2740
|
-
"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
|
|
2741
|
-
);
|
|
2742
|
-
}
|
|
2743
|
-
}
|
|
2744
|
-
async function derivePublicKey(secretHex) {
|
|
2745
|
-
const seed = fromHex(secretHex, "deviceSecret", 32);
|
|
2746
|
-
const pkcs8 = concat(PKCS8_ED25519_PREFIX, seed);
|
|
2747
|
-
const key = await crypto.subtle.importKey(
|
|
2748
|
-
"pkcs8",
|
|
2749
|
-
pkcs8,
|
|
2750
|
-
{ name: "Ed25519" },
|
|
2751
|
-
true,
|
|
2752
|
-
["sign"]
|
|
2753
|
-
);
|
|
2754
|
-
const jwk = await crypto.subtle.exportKey("jwk", key);
|
|
2755
|
-
const raw = jwk.x;
|
|
2756
|
-
return Uint8Array.from(
|
|
2757
|
-
atob(raw.replace(/-/g, "+").replace(/_/g, "/")),
|
|
2758
|
-
(c) => c.charCodeAt(0)
|
|
2759
|
-
);
|
|
2760
|
-
}
|
|
2761
|
-
|
|
2762
2843
|
// src/device-cert/device-cert.ts
|
|
2763
2844
|
var CERT_DOMAIN = new TextEncoder().encode("calimero.device.cert.v1");
|
|
2764
2845
|
var ACCOUNT_ID_DOMAIN = new TextEncoder().encode("calimero.account.genesis.v1");
|
|
@@ -5756,6 +5837,10 @@ var CloudClient = class {
|
|
|
5756
5837
|
};
|
|
5757
5838
|
|
|
5758
5839
|
// src/mero-js.ts
|
|
5840
|
+
function resolveProofSigner(config) {
|
|
5841
|
+
if (!config) return void 0;
|
|
5842
|
+
return typeof config === "function" ? config : createProofSigner(config);
|
|
5843
|
+
}
|
|
5759
5844
|
var REFRESH_LOCK_NAME = "mero-js:token-refresh";
|
|
5760
5845
|
function getLockManager() {
|
|
5761
5846
|
const nav = globalThis.navigator;
|
|
@@ -5794,8 +5879,11 @@ var MeroJs = class {
|
|
|
5794
5879
|
this.tokenData = this.tokenStore.getTokens();
|
|
5795
5880
|
}
|
|
5796
5881
|
const isTauri = typeof window !== "undefined" && "__TAURI_INTERNALS__" in window;
|
|
5882
|
+
const getProof = resolveProofSigner(this.config.requestProof);
|
|
5797
5883
|
this.httpClient = createBrowserHttpClient({
|
|
5798
5884
|
baseUrl: this.config.baseUrl,
|
|
5885
|
+
fetch: this.config.fetch,
|
|
5886
|
+
getProof,
|
|
5799
5887
|
getAuthToken: async () => {
|
|
5800
5888
|
const token = await this.getValidToken();
|
|
5801
5889
|
return token?.access_token || "";
|
|
@@ -5865,6 +5953,7 @@ var MeroJs = class {
|
|
|
5865
5953
|
if (!this.sseClient) {
|
|
5866
5954
|
this.sseClient = new SseClient({
|
|
5867
5955
|
baseUrl: this.config.baseUrl,
|
|
5956
|
+
fetch: this.config.fetch,
|
|
5868
5957
|
getAuthToken: async () => {
|
|
5869
5958
|
const token = await this.getValidToken();
|
|
5870
5959
|
return token?.access_token || "";
|
|
@@ -6149,7 +6238,7 @@ var LocalStorageTokenStore = class {
|
|
|
6149
6238
|
};
|
|
6150
6239
|
|
|
6151
6240
|
// src/warrant/warrant.ts
|
|
6152
|
-
var
|
|
6241
|
+
var SIGN_DOMAIN2 = new TextEncoder().encode("calimero.warrant.v2");
|
|
6153
6242
|
var INTENT_DOMAIN = new TextEncoder().encode("calimero.warrant.intent.v1");
|
|
6154
6243
|
var MAX_CITED_HEADS = 64;
|
|
6155
6244
|
var UNPINNED_APP = "00".repeat(32);
|
|
@@ -6174,7 +6263,7 @@ async function signWarrant(input) {
|
|
|
6174
6263
|
const commitment = await intentHash(input.method, input.argsJson);
|
|
6175
6264
|
const nonce = u64le(input.nonce);
|
|
6176
6265
|
const notAfter = u64le(input.notAfter);
|
|
6177
|
-
const preimage = await domainHash(
|
|
6266
|
+
const preimage = await domainHash(SIGN_DOMAIN2, [
|
|
6178
6267
|
context,
|
|
6179
6268
|
authorAccount,
|
|
6180
6269
|
publicKey,
|
|
@@ -6493,7 +6582,7 @@ function optionalBytes32(value, label) {
|
|
|
6493
6582
|
}
|
|
6494
6583
|
return concat(new Uint8Array([1]), new Uint8Array(value));
|
|
6495
6584
|
}
|
|
6496
|
-
function
|
|
6585
|
+
function borshString2(value) {
|
|
6497
6586
|
const bytes = new TextEncoder().encode(value);
|
|
6498
6587
|
return concat(u32le(bytes.length), bytes);
|
|
6499
6588
|
}
|
|
@@ -6517,7 +6606,7 @@ function encodeSignedInvitation(signed) {
|
|
|
6517
6606
|
// ...then the enclosing SignedGroupOpenInvitation, in declaration order.
|
|
6518
6607
|
// `inviter_account` sits between the signature and the addresses; putting it
|
|
6519
6608
|
// anywhere else still encodes 32 bytes and still verifies as nothing.
|
|
6520
|
-
|
|
6609
|
+
borshString2(signed.inviter_signature),
|
|
6521
6610
|
signed.inviter_account ? concat(new Uint8Array([1]), fromHex(signed.inviter_account, "inviter_account", 32)) : new Uint8Array([0]),
|
|
6522
6611
|
// A `Vec<String>`, so each entry is a bare borsh string. This carried an
|
|
6523
6612
|
// enum until core dropped the URL variant, and an enum writes a
|
|
@@ -6525,7 +6614,7 @@ function encodeSignedInvitation(signed) {
|
|
|
6525
6614
|
// every following byte and fail as `invalid invitation signature`, pointing
|
|
6526
6615
|
// nowhere near this line.
|
|
6527
6616
|
u32le(admitterAddrs.length),
|
|
6528
|
-
...admitterAddrs.map(
|
|
6617
|
+
...admitterAddrs.map(borshString2),
|
|
6529
6618
|
optionalBytes32(signed.application_id, "application_id"),
|
|
6530
6619
|
// Borsh order follows core's field order, where this is `bytecode_id`; the
|
|
6531
6620
|
// JSON key is `app_key`, a rename covering both directions that core pins in
|
|
@@ -6570,86 +6659,6 @@ async function signMemberJoinOp(input) {
|
|
|
6570
6659
|
return hex(concat(signable, signature, unendorsed));
|
|
6571
6660
|
}
|
|
6572
6661
|
|
|
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
|
-
|
|
6653
6662
|
// src/login/login.ts
|
|
6654
6663
|
var SIGN_DOMAIN3 = new TextEncoder().encode("calimero.auth.login.v1");
|
|
6655
6664
|
var AUDIENCE_TAG = {
|