@calimero-network/mero-js 13.3.0 → 14.0.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/account/index.d.ts +15 -15
- package/dist/account/index.js +15 -15
- package/dist/admin-api/admin-client.d.ts +12 -6
- package/dist/admin-api/admin-client.js +12 -6
- package/dist/admin-api/admin-types.d.ts +17 -11
- package/dist/events/group.d.ts +1 -1
- package/dist/index.browser.mjs +2 -2
- package/dist/index.browser.mjs.map +4 -4
- package/dist/index.cjs +151 -9
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -1
- package/dist/index.mjs +151 -9
- package/dist/index.mjs.map +4 -4
- package/dist/warrant/index.d.ts +2 -0
- package/dist/warrant/index.js +2 -0
- package/dist/warrant/warrant.d.ts +76 -0
- package/dist/warrant/warrant.js +143 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -55,12 +55,14 @@ __export(index_exports, {
|
|
|
55
55
|
createUniversalHttpClient: () => createUniversalHttpClient,
|
|
56
56
|
discoverLocalNodes: () => discoverLocalNodes,
|
|
57
57
|
hasCap: () => hasCap,
|
|
58
|
+
intentHash: () => intentHash,
|
|
58
59
|
jsonCodec: () => jsonCodec,
|
|
59
60
|
localNodeUrl: () => localNodeUrl,
|
|
60
61
|
nodeEndpoint: () => nodeEndpoint,
|
|
61
62
|
parseAuthCallback: () => parseAuthCallback,
|
|
62
63
|
probeNodeHealth: () => probeNodeHealth,
|
|
63
64
|
sameAccount: () => sameAccount,
|
|
65
|
+
signWarrant: () => signWarrant,
|
|
64
66
|
toAccountBase58: () => toAccountBase58,
|
|
65
67
|
toAccountHex: () => toAccountHex,
|
|
66
68
|
withCap: () => withCap,
|
|
@@ -1190,7 +1192,8 @@ var AdminApiClient = class {
|
|
|
1190
1192
|
* CAN_AUTHOR_ON_BEHALF to …", or that the nonce is already spent — so a caller
|
|
1191
1193
|
* can tell which precondition failed rather than only that one did.
|
|
1192
1194
|
*
|
|
1193
|
-
*
|
|
1195
|
+
* Mint the warrant with {@link signWarrant}; see
|
|
1196
|
+
* {@link PerformIntentRequest.warrant}.
|
|
1194
1197
|
*/
|
|
1195
1198
|
async performIntent(contextId, request) {
|
|
1196
1199
|
return unwrap(
|
|
@@ -1296,14 +1299,16 @@ var AdminApiClient = class {
|
|
|
1296
1299
|
}
|
|
1297
1300
|
/**
|
|
1298
1301
|
* `identity` is the member's ACCOUNT (64 hex), as returned by
|
|
1299
|
-
* {@link listGroupMembers} — not the
|
|
1302
|
+
* {@link listGroupMembers} — not the signing key that added them. Both are
|
|
1303
|
+
* 64 hex, so nothing but the source tells them apart.
|
|
1300
1304
|
*/
|
|
1301
1305
|
async updateMemberRole(groupId, identity, request) {
|
|
1302
1306
|
await this.httpClient.put(`/admin-api/groups/${groupId}/members/${identity}/role`, request);
|
|
1303
1307
|
}
|
|
1304
1308
|
/**
|
|
1305
1309
|
* `identity` is the member's ACCOUNT (64 hex), as returned by
|
|
1306
|
-
* {@link listGroupMembers} — not the
|
|
1310
|
+
* {@link listGroupMembers} — not the signing key that added them. Both are
|
|
1311
|
+
* 64 hex, so nothing but the source tells them apart.
|
|
1307
1312
|
*/
|
|
1308
1313
|
async getMemberCapabilities(groupId, identity) {
|
|
1309
1314
|
return unwrap(
|
|
@@ -1314,7 +1319,8 @@ var AdminApiClient = class {
|
|
|
1314
1319
|
}
|
|
1315
1320
|
/**
|
|
1316
1321
|
* `identity` is the member's ACCOUNT (64 hex), as returned by
|
|
1317
|
-
* {@link listGroupMembers} — not the
|
|
1322
|
+
* {@link listGroupMembers} — not the signing key that added them. Both are
|
|
1323
|
+
* 64 hex, so nothing but the source tells them apart.
|
|
1318
1324
|
*/
|
|
1319
1325
|
async setMemberCapabilities(groupId, identity, request) {
|
|
1320
1326
|
await this.httpClient.put(`/admin-api/groups/${groupId}/members/${identity}/capabilities`, request);
|
|
@@ -1347,7 +1353,8 @@ var AdminApiClient = class {
|
|
|
1347
1353
|
}
|
|
1348
1354
|
/**
|
|
1349
1355
|
* `identity` is the member's ACCOUNT (64 hex), as returned by
|
|
1350
|
-
* {@link listGroupMembers} — not the
|
|
1356
|
+
* {@link listGroupMembers} — not the signing key that added them. Both are
|
|
1357
|
+
* 64 hex, so nothing but the source tells them apart.
|
|
1351
1358
|
*/
|
|
1352
1359
|
async getMemberMetadata(groupId, identity) {
|
|
1353
1360
|
const response = await this.httpClient.get(
|
|
@@ -1501,7 +1508,8 @@ var AdminApiClient = class {
|
|
|
1501
1508
|
* /admin-api/groups/:group_id/members/:identity/auto-follow).
|
|
1502
1509
|
*
|
|
1503
1510
|
* `identity` is the member's ACCOUNT (64 hex), as returned by
|
|
1504
|
-
* {@link listGroupMembers} — not the
|
|
1511
|
+
* {@link listGroupMembers} — not the signing key that added them. Both are
|
|
1512
|
+
* 64 hex, so nothing but the source tells them apart.
|
|
1505
1513
|
*/
|
|
1506
1514
|
async setMemberAutoFollow(groupId, identity, request) {
|
|
1507
1515
|
await this.httpClient.put(`/admin-api/groups/${groupId}/members/${identity}/auto-follow`, request);
|
|
@@ -2566,10 +2574,10 @@ function toHex(bytes) {
|
|
|
2566
2574
|
for (const byte of bytes) out += byte.toString(16).padStart(2, "0");
|
|
2567
2575
|
return out;
|
|
2568
2576
|
}
|
|
2569
|
-
function fromHex(
|
|
2570
|
-
const bytes = new Uint8Array(
|
|
2577
|
+
function fromHex(hex2) {
|
|
2578
|
+
const bytes = new Uint8Array(hex2.length / 2);
|
|
2571
2579
|
for (let i = 0; i < bytes.length; i++) {
|
|
2572
|
-
bytes[i] = parseInt(
|
|
2580
|
+
bytes[i] = parseInt(hex2.slice(i * 2, i * 2 + 2), 16);
|
|
2573
2581
|
}
|
|
2574
2582
|
return bytes;
|
|
2575
2583
|
}
|
|
@@ -2674,6 +2682,140 @@ var CloudClient = class {
|
|
|
2674
2682
|
}
|
|
2675
2683
|
};
|
|
2676
2684
|
|
|
2685
|
+
// src/warrant/warrant.ts
|
|
2686
|
+
var SIGN_DOMAIN = new TextEncoder().encode("calimero.warrant.v1");
|
|
2687
|
+
var INTENT_DOMAIN = new TextEncoder().encode("calimero.warrant.intent.v1");
|
|
2688
|
+
var PKCS8_ED25519_PREFIX = new Uint8Array([
|
|
2689
|
+
48,
|
|
2690
|
+
46,
|
|
2691
|
+
2,
|
|
2692
|
+
1,
|
|
2693
|
+
0,
|
|
2694
|
+
48,
|
|
2695
|
+
5,
|
|
2696
|
+
6,
|
|
2697
|
+
3,
|
|
2698
|
+
43,
|
|
2699
|
+
101,
|
|
2700
|
+
112,
|
|
2701
|
+
4,
|
|
2702
|
+
34,
|
|
2703
|
+
4,
|
|
2704
|
+
32
|
|
2705
|
+
]);
|
|
2706
|
+
function hex(bytes) {
|
|
2707
|
+
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
2708
|
+
}
|
|
2709
|
+
function fromHex2(value, label, expectedBytes) {
|
|
2710
|
+
const clean = value.trim();
|
|
2711
|
+
if (!/^[0-9a-fA-F]*$/.test(clean) || clean.length !== expectedBytes * 2) {
|
|
2712
|
+
throw new Error(
|
|
2713
|
+
`${label} must be ${expectedBytes * 2} hex characters, got ${clean.length}`
|
|
2714
|
+
);
|
|
2715
|
+
}
|
|
2716
|
+
const bytes = new Uint8Array(expectedBytes);
|
|
2717
|
+
for (let i = 0; i < expectedBytes; i += 1) {
|
|
2718
|
+
bytes[i] = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);
|
|
2719
|
+
}
|
|
2720
|
+
return bytes;
|
|
2721
|
+
}
|
|
2722
|
+
function u64le(value) {
|
|
2723
|
+
const out = new Uint8Array(8);
|
|
2724
|
+
new DataView(out.buffer).setBigUint64(0, BigInt(value), true);
|
|
2725
|
+
return out;
|
|
2726
|
+
}
|
|
2727
|
+
function concat(...parts) {
|
|
2728
|
+
const out = new Uint8Array(parts.reduce((total, p) => total + p.length, 0));
|
|
2729
|
+
let offset = 0;
|
|
2730
|
+
for (const part of parts) {
|
|
2731
|
+
out.set(part, offset);
|
|
2732
|
+
offset += part.length;
|
|
2733
|
+
}
|
|
2734
|
+
return out;
|
|
2735
|
+
}
|
|
2736
|
+
async function domainHash(domain, parts) {
|
|
2737
|
+
const chunks = [u64le(domain.length), domain];
|
|
2738
|
+
for (const part of parts) {
|
|
2739
|
+
chunks.push(u64le(part.length), part);
|
|
2740
|
+
}
|
|
2741
|
+
return new Uint8Array(
|
|
2742
|
+
await crypto.subtle.digest("SHA-256", concat(...chunks))
|
|
2743
|
+
);
|
|
2744
|
+
}
|
|
2745
|
+
async function intentHash(method, argsJson) {
|
|
2746
|
+
const args = new TextEncoder().encode(JSON.stringify(argsJson));
|
|
2747
|
+
return domainHash(INTENT_DOMAIN, [new TextEncoder().encode(method), args]);
|
|
2748
|
+
}
|
|
2749
|
+
async function importSigningKey(secretHex) {
|
|
2750
|
+
const seed = fromHex2(secretHex, "deviceSecret", 32);
|
|
2751
|
+
const pkcs8 = concat(PKCS8_ED25519_PREFIX, seed);
|
|
2752
|
+
try {
|
|
2753
|
+
return await crypto.subtle.importKey(
|
|
2754
|
+
"pkcs8",
|
|
2755
|
+
pkcs8,
|
|
2756
|
+
{ name: "Ed25519" },
|
|
2757
|
+
false,
|
|
2758
|
+
["sign"]
|
|
2759
|
+
);
|
|
2760
|
+
} catch (cause) {
|
|
2761
|
+
const detail = cause instanceof Error ? `: ${cause.message}` : "";
|
|
2762
|
+
throw new Error(
|
|
2763
|
+
"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
|
|
2764
|
+
);
|
|
2765
|
+
}
|
|
2766
|
+
}
|
|
2767
|
+
async function signWarrant(input) {
|
|
2768
|
+
const context = fromHex2(input.context, "context", 32);
|
|
2769
|
+
const authorAccount = fromHex2(input.authorAccount, "authorAccount", 32);
|
|
2770
|
+
const executor = fromHex2(input.executor, "executor", 32);
|
|
2771
|
+
const key = await importSigningKey(input.deviceSecret);
|
|
2772
|
+
const publicKey = await derivePublicKey(input.deviceSecret);
|
|
2773
|
+
const commitment = await intentHash(input.method, input.argsJson);
|
|
2774
|
+
const nonce = u64le(input.nonce);
|
|
2775
|
+
const notAfter = u64le(input.notAfter);
|
|
2776
|
+
const preimage = await domainHash(SIGN_DOMAIN, [
|
|
2777
|
+
context,
|
|
2778
|
+
authorAccount,
|
|
2779
|
+
publicKey,
|
|
2780
|
+
executor,
|
|
2781
|
+
commitment,
|
|
2782
|
+
nonce,
|
|
2783
|
+
notAfter
|
|
2784
|
+
]);
|
|
2785
|
+
const signature = new Uint8Array(
|
|
2786
|
+
await crypto.subtle.sign({ name: "Ed25519" }, key, preimage)
|
|
2787
|
+
);
|
|
2788
|
+
return hex(
|
|
2789
|
+
concat(
|
|
2790
|
+
context,
|
|
2791
|
+
authorAccount,
|
|
2792
|
+
publicKey,
|
|
2793
|
+
executor,
|
|
2794
|
+
commitment,
|
|
2795
|
+
nonce,
|
|
2796
|
+
notAfter,
|
|
2797
|
+
signature
|
|
2798
|
+
)
|
|
2799
|
+
);
|
|
2800
|
+
}
|
|
2801
|
+
async function derivePublicKey(secretHex) {
|
|
2802
|
+
const seed = fromHex2(secretHex, "deviceSecret", 32);
|
|
2803
|
+
const pkcs8 = concat(PKCS8_ED25519_PREFIX, seed);
|
|
2804
|
+
const key = await crypto.subtle.importKey(
|
|
2805
|
+
"pkcs8",
|
|
2806
|
+
pkcs8,
|
|
2807
|
+
{ name: "Ed25519" },
|
|
2808
|
+
true,
|
|
2809
|
+
["sign"]
|
|
2810
|
+
);
|
|
2811
|
+
const jwk = await crypto.subtle.exportKey("jwk", key);
|
|
2812
|
+
const raw = jwk.x;
|
|
2813
|
+
return Uint8Array.from(
|
|
2814
|
+
atob(raw.replace(/-/g, "+").replace(/_/g, "/")),
|
|
2815
|
+
(c) => c.charCodeAt(0)
|
|
2816
|
+
);
|
|
2817
|
+
}
|
|
2818
|
+
|
|
2677
2819
|
// src/capabilities.ts
|
|
2678
2820
|
var CAPABILITIES = {
|
|
2679
2821
|
CAN_CREATE_CONTEXT: 1 << 0,
|