@calimero-network/mero-js 22.2.0 → 22.4.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.d.ts CHANGED
@@ -18,14 +18,14 @@ export type { Codec, EphemeralEntry } from "./ephemeral/index.js";
18
18
  export * from "./cloud/index.js";
19
19
  export * from "./sealed/index.js";
20
20
  export * from "./relay/index.js";
21
- export { signWarrant, intentHash } from "./warrant/index.js";
21
+ export { signWarrant, intentHash, signCreationWarrant, parseCreationWarrant, creationInitHash, } from "./warrant/index.js";
22
22
  export { generateAccountRoot, accountRootFromPhrase, accountRootFromSecret, signAccountLink, signAccountLogin, } from "./account/index.js";
23
23
  export type { AccountRoot, RecoverableAccountRoot, AccountLinkInput, AccountLoginInput, } from "./account/index.js";
24
24
  export { signDeviceCert, mintDeviceId, deviceCertPayload, accountForRoot, } from "./device-cert/index.js";
25
25
  export type { DeviceCertInput } from "./device-cert/index.js";
26
26
  export { signMemberJoinOp, encodeSignedInvitation, SIGNED_NAMESPACE_OP_SCHEMA_VERSION, } from "./namespace-op/index.js";
27
27
  export type { SignMemberJoinInput } from "./namespace-op/index.js";
28
- export type { WarrantInput } from "./warrant/index.js";
28
+ export type { WarrantInput, CreationWarrantInput, CreationWarrantFields, SignedCreationWarrant, } from "./warrant/index.js";
29
29
  export { requestBodyHash, signRequest, callerProof, createProofSigner, } from "./request/index.js";
30
30
  export type { CallerProofInput, ProofRequest, ProofSignerOptions, } from "./request/index.js";
31
31
  export type { RequestSigInput } from "./request/index.js";
package/dist/index.js CHANGED
@@ -27,7 +27,7 @@ export * from "./sealed/index.js";
27
27
  // Relay client — write through delegated execution, holding only a signing key
28
28
  export * from "./relay/index.js";
29
29
  // Warrant signing — mint the author's consent for a relay to run one intent
30
- export { signWarrant, intentHash } from "./warrant/index.js";
30
+ export { signWarrant, intentHash, signCreationWarrant, parseCreationWarrant, creationInitHash, } from "./warrant/index.js";
31
31
  // Account roots — mint one with a recovery phrase, or prove you hold one
32
32
  export { generateAccountRoot, accountRootFromPhrase, accountRootFromSecret, signAccountLink, signAccountLogin, } from "./account/index.js";
33
33
  export { signDeviceCert, mintDeviceId, deviceCertPayload, accountForRoot, } from "./device-cert/index.js";
package/dist/index.mjs CHANGED
@@ -2183,11 +2183,11 @@ function u32le(value) {
2183
2183
  function hex(bytes) {
2184
2184
  return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
2185
2185
  }
2186
- function fromHex(value, label, expectedBytes) {
2186
+ function fromHex(value, label2, expectedBytes) {
2187
2187
  const clean = value.trim();
2188
2188
  if (!/^[0-9a-fA-F]*$/.test(clean) || clean.length !== expectedBytes * 2) {
2189
2189
  throw new Error(
2190
- `${label} must be ${expectedBytes * 2} hex characters, got ${clean.length}`
2190
+ `${label2} must be ${expectedBytes * 2} hex characters, got ${clean.length}`
2191
2191
  );
2192
2192
  }
2193
2193
  const bytes = new Uint8Array(expectedBytes);
@@ -2196,10 +2196,10 @@ function fromHex(value, label, expectedBytes) {
2196
2196
  }
2197
2197
  return bytes;
2198
2198
  }
2199
- function fromHexUnsized(value, label) {
2199
+ function fromHexUnsized(value, label2) {
2200
2200
  const clean = value.trim();
2201
2201
  if (!/^[0-9a-fA-F]*$/.test(clean) || clean.length % 2 !== 0) {
2202
- throw new Error(`${label} must be an even number of hex characters`);
2202
+ throw new Error(`${label2} must be an even number of hex characters`);
2203
2203
  }
2204
2204
  const bytes = new Uint8Array(clean.length / 2);
2205
2205
  for (let i = 0; i < bytes.length; i += 1) {
@@ -6513,14 +6513,172 @@ async function signWarrant(input) {
6513
6513
  )
6514
6514
  );
6515
6515
  }
6516
- function citedHeads(heads, label) {
6516
+ function citedHeads(heads, label2) {
6517
6517
  const list = heads ?? [];
6518
6518
  if (list.length > MAX_CITED_HEADS) {
6519
6519
  throw new Error(
6520
- `${label} cites ${list.length} heads, over the ${MAX_CITED_HEADS} a node accepts`
6520
+ `${label2} cites ${list.length} heads, over the ${MAX_CITED_HEADS} a node accepts`
6521
6521
  );
6522
6522
  }
6523
- return list.map((head, i) => fromHex(head, `${label}[${i}]`, 32));
6523
+ return list.map((head, i) => fromHex(head, `${label2}[${i}]`, 32));
6524
+ }
6525
+
6526
+ // src/warrant/creation-warrant.ts
6527
+ var SIGN_DOMAIN3 = new TextEncoder().encode("calimero.context-creation-warrant.v1");
6528
+ var INIT_DOMAIN = new TextEncoder().encode("calimero.context-creation.init.v1");
6529
+ var MAX_LABEL_BYTES = 256;
6530
+ async function creationInitHash(initArgs) {
6531
+ const bytes = new TextEncoder().encode(JSON.stringify(initArgs));
6532
+ return domainHash(INIT_DOMAIN, [bytes]);
6533
+ }
6534
+ async function creationWarrantPreimage(p) {
6535
+ return domainHash(SIGN_DOMAIN3, [
6536
+ p.group,
6537
+ p.seed,
6538
+ p.authorAccount,
6539
+ p.deviceKey,
6540
+ p.executor,
6541
+ p.applicationId,
6542
+ new Uint8Array([p.serviceName === null ? 0 : 1]),
6543
+ p.serviceName ?? new Uint8Array(0),
6544
+ new Uint8Array([p.name === null ? 0 : 1]),
6545
+ p.name ?? new Uint8Array(0),
6546
+ p.initHash,
6547
+ u64le(p.accountHeads.length),
6548
+ ...p.accountHeads,
6549
+ u64le(p.governanceFloor.length),
6550
+ ...p.governanceFloor,
6551
+ u64le(p.nonce),
6552
+ u64le(p.notAfter)
6553
+ ]);
6554
+ }
6555
+ async function signCreationWarrant(input) {
6556
+ const group = fromHex(input.group, "group", 32);
6557
+ const seed = input.seed === void 0 ? crypto.getRandomValues(new Uint8Array(32)) : fromHex(input.seed, "seed", 32);
6558
+ const authorAccount = fromHex(input.authorAccount, "authorAccount", 32);
6559
+ const executor = fromHex(input.executor, "executor", 32);
6560
+ const applicationId = fromHex(input.applicationId, "applicationId", 32);
6561
+ const serviceName = label(input.serviceName, "serviceName");
6562
+ const name = label(input.name, "name");
6563
+ const accountHeads = citedHeads(input.accountHeads, "accountHeads");
6564
+ const governanceFloor = citedHeads(input.governanceFloor, "governanceFloor");
6565
+ const key = await importSigningKey(input.deviceSecret);
6566
+ const deviceKey = await derivePublicKey(input.deviceSecret);
6567
+ const initHash = await creationInitHash(input.initArgs);
6568
+ const preimage = await creationWarrantPreimage({
6569
+ group,
6570
+ seed,
6571
+ authorAccount,
6572
+ deviceKey,
6573
+ executor,
6574
+ applicationId,
6575
+ serviceName,
6576
+ name,
6577
+ initHash,
6578
+ accountHeads,
6579
+ governanceFloor,
6580
+ nonce: input.nonce,
6581
+ notAfter: input.notAfter
6582
+ });
6583
+ const signature = new Uint8Array(
6584
+ await crypto.subtle.sign({ name: "Ed25519" }, key, preimage)
6585
+ );
6586
+ const warrant = hex(
6587
+ concat(
6588
+ group,
6589
+ seed,
6590
+ authorAccount,
6591
+ deviceKey,
6592
+ executor,
6593
+ applicationId,
6594
+ borshOption(serviceName),
6595
+ borshOption(name),
6596
+ initHash,
6597
+ u32le(accountHeads.length),
6598
+ ...accountHeads,
6599
+ u32le(governanceFloor.length),
6600
+ ...governanceFloor,
6601
+ u64le(input.nonce),
6602
+ u64le(input.notAfter),
6603
+ signature
6604
+ )
6605
+ );
6606
+ return { warrant, seed: hex(seed) };
6607
+ }
6608
+ function parseCreationWarrant(warrant) {
6609
+ const clean = warrant.trim();
6610
+ if (!/^[0-9a-fA-F]*$/.test(clean) || clean.length % 2 !== 0) {
6611
+ throw new Error("creation warrant must be an even number of hex characters");
6612
+ }
6613
+ const bytes = new Uint8Array(clean.length / 2);
6614
+ for (let i = 0; i < bytes.length; i += 1) {
6615
+ bytes[i] = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);
6616
+ }
6617
+ const view = new DataView(bytes.buffer);
6618
+ let o = 0;
6619
+ const take = (n, what) => {
6620
+ if (o + n > bytes.length) {
6621
+ throw new Error(`creation warrant ends inside ${what} (${bytes.length} bytes)`);
6622
+ }
6623
+ const out = bytes.subarray(o, o + n);
6624
+ o += n;
6625
+ return out;
6626
+ };
6627
+ const u32 = (what) => view.getUint32(take(4, what).byteOffset, true);
6628
+ const u64 = (what) => view.getBigUint64(take(8, what).byteOffset, true);
6629
+ const option = (what) => {
6630
+ const tag = take(1, what)[0];
6631
+ if (tag === 0) return null;
6632
+ if (tag !== 1) throw new Error(`${what} has option tag ${tag}, expected 0 or 1`);
6633
+ const len = u32(what);
6634
+ if (len > MAX_LABEL_BYTES) {
6635
+ throw new Error(`${what} is ${len} bytes, over the ${MAX_LABEL_BYTES} a node accepts`);
6636
+ }
6637
+ return new TextDecoder("utf-8", { fatal: true }).decode(take(len, what));
6638
+ };
6639
+ const heads = (what) => {
6640
+ const count = u32(what);
6641
+ if (count > 64) {
6642
+ throw new Error(`${what} cites ${count} heads, over the 64 a node accepts`);
6643
+ }
6644
+ return Array.from({ length: count }, () => hex(take(32, what)));
6645
+ };
6646
+ const fields = {
6647
+ group: hex(take(32, "group")),
6648
+ seed: hex(take(32, "seed")),
6649
+ authorAccount: hex(take(32, "authorAccount")),
6650
+ deviceKey: hex(take(32, "deviceKey")),
6651
+ executor: hex(take(32, "executor")),
6652
+ applicationId: hex(take(32, "applicationId")),
6653
+ serviceName: option("serviceName"),
6654
+ name: option("name"),
6655
+ initHash: hex(take(32, "initHash")),
6656
+ accountHeads: heads("accountHeads"),
6657
+ governanceFloor: heads("governanceFloor"),
6658
+ nonce: u64("nonce"),
6659
+ notAfter: u64("notAfter"),
6660
+ signature: hex(take(64, "signature"))
6661
+ };
6662
+ if (o !== bytes.length) {
6663
+ throw new Error(
6664
+ `creation warrant is ${bytes.length} bytes but its fields account for ${o}`
6665
+ );
6666
+ }
6667
+ return fields;
6668
+ }
6669
+ function label(value, what) {
6670
+ if (value === void 0) return null;
6671
+ const bytes = new TextEncoder().encode(value);
6672
+ if (bytes.length > MAX_LABEL_BYTES) {
6673
+ throw new Error(
6674
+ `${what} is ${bytes.length} UTF-8 bytes, over the ${MAX_LABEL_BYTES} a node accepts`
6675
+ );
6676
+ }
6677
+ return bytes;
6678
+ }
6679
+ function borshOption(bytes) {
6680
+ if (bytes === null) return new Uint8Array([0]);
6681
+ return concat(new Uint8Array([1]), u32le(bytes.length), bytes);
6524
6682
  }
6525
6683
 
6526
6684
  // src/relay/relay-client.ts
@@ -6583,6 +6741,94 @@ var RelayClient = class {
6583
6741
  );
6584
6742
  return { rootHash: body.data.rootHash, returns: body.data.returns ?? null };
6585
6743
  }
6744
+ /**
6745
+ * Ask the relay what it can do about creating contexts in `groupId`.
6746
+ *
6747
+ * Pass `author` (an account, hex) to also learn whether that account may
6748
+ * create here — `authorMayCreate` is present only then.
6749
+ */
6750
+ async describeCreation(groupId, opts = {}) {
6751
+ const query = opts.author ? `?author=${encodeURIComponent(opts.author)}` : "";
6752
+ const body = await this.json(
6753
+ "GET",
6754
+ `/admin-api/groups/${encodeURIComponent(groupId)}/context-intents${query}`
6755
+ );
6756
+ return body.data;
6757
+ }
6758
+ /**
6759
+ * Create a context in a group through the relay, as the author.
6760
+ *
6761
+ * Always asks {@link describeCreation} first — with the author, so both
6762
+ * standing checks happen before anything is signed. A relay without standing
6763
+ * in the group, or an author without `CAN_CREATE_CONTEXT`, is refused here as
6764
+ * an {@link IntentRefusedError} *before* a nonce is taken: the nonce source
6765
+ * is monotonic, and a warrant nobody will spend burns one for nothing.
6766
+ *
6767
+ * The creation warrant's nonce is spent in the new context's per-device
6768
+ * ledger — the same one later `execute` calls in that context draw from — so
6769
+ * it comes from the configured {@link NonceSource} like any other warrant.
6770
+ *
6771
+ * Sealing: nothing here is plaintext-specific. The request goes through the
6772
+ * injected `fetch`, so a `createAttestedSealedFetch` seals it exactly as it
6773
+ * seals `execute`. Whether the relay *accepts* it sealed is the node's call:
6774
+ * a proxy-auth relay only admits sealed requests for routes `merod` serves
6775
+ * without a credential, so `/admin-api/groups/:id/context-intents` must be on
6776
+ * that list on the core side or the request comes back
6777
+ * `403 sealed_route_unguarded`.
6778
+ */
6779
+ async createContext(input) {
6780
+ const described = await this.describeCreation(input.groupId, {
6781
+ author: this.config.authorAccount
6782
+ });
6783
+ if (!described.canCreateOnBehalf) {
6784
+ throw new IntentRefusedError(
6785
+ `the relay (${described.executorAccount}) has no standing to act for members of group ${described.groupId}; an admin must admit it as a relay or grant it CAN_AUTHOR_ON_BEHALF (checked before signing \u2014 no nonce was spent)`,
6786
+ false,
6787
+ 403
6788
+ );
6789
+ }
6790
+ if (described.authorMayCreate === false) {
6791
+ throw new IntentRefusedError(
6792
+ `the author (${this.config.authorAccount}) may not create contexts in group ${described.groupId}; it needs CAN_CREATE_CONTEXT or admin (checked before signing \u2014 no nonce was spent)`,
6793
+ false,
6794
+ 403
6795
+ );
6796
+ }
6797
+ const configured = this.config.executorAccount;
6798
+ if (configured && configured.toLowerCase() !== described.executorAccount.toLowerCase()) {
6799
+ throw new Error(
6800
+ `configured executorAccount ${configured} is not the relay's account ${described.executorAccount}; a warrant naming it would be unspendable`
6801
+ );
6802
+ }
6803
+ const executor = described.executorAccount;
6804
+ this.executorAccount = executor;
6805
+ const initArgs = input.initArgs ?? {};
6806
+ const nonce2 = await this.config.nonces.next();
6807
+ const ttl = this.config.ttlSeconds ?? DEFAULT_TTL_SECONDS;
6808
+ const { warrant } = await signCreationWarrant({
6809
+ group: input.groupId,
6810
+ seed: input.seed,
6811
+ authorAccount: this.config.authorAccount,
6812
+ executor,
6813
+ applicationId: input.applicationId,
6814
+ serviceName: input.serviceName,
6815
+ name: input.name,
6816
+ initArgs,
6817
+ nonce: nonce2,
6818
+ notAfter: BigInt(Math.floor(Date.now() / 1e3)) + BigInt(ttl),
6819
+ deviceSecret: this.config.deviceSecret
6820
+ });
6821
+ const body = await this.json(
6822
+ "POST",
6823
+ `/admin-api/groups/${encodeURIComponent(input.groupId)}/context-intents`,
6824
+ { warrant, authorProof: this.config.authorProof, initArgs }
6825
+ );
6826
+ return {
6827
+ contextId: body.data.contextId,
6828
+ groupId: body.data.groupId,
6829
+ memberPublicKey: body.data.memberPublicKey
6830
+ };
6831
+ }
6586
6832
  async json(method, path, body) {
6587
6833
  const headers = { Accept: "application/json" };
6588
6834
  if (body !== void 0) headers["Content-Type"] = "application/json";
@@ -7282,8 +7528,8 @@ var REGISTERS = ["mrtd", "rtmr0", "rtmr1", "rtmr2", "rtmr3"];
7282
7528
  function createQuoteVerifier(options) {
7283
7529
  const allowedMrtd = measurements(options.allowedMrtd ?? [], "allowedMrtd");
7284
7530
  const allowedImages = (options.allowedMeasurements ?? []).map((image, index) => {
7285
- const label = `allowedMeasurements[${index}]`;
7286
- return REGISTERS.map((register) => measurements([image?.[register] ?? ""], `${label}.${register}`)[0]).join();
7531
+ const label2 = `allowedMeasurements[${index}]`;
7532
+ return REGISTERS.map((register) => measurements([image?.[register] ?? ""], `${label2}.${register}`)[0]).join();
7287
7533
  });
7288
7534
  const allowedRtmr = [
7289
7535
  measurements(options.allowedRtmr0 ?? [], "allowedRtmr0"),
@@ -7352,11 +7598,11 @@ function createQuoteVerifier(options) {
7352
7598
  };
7353
7599
  return Object.assign(verifier, { includeCollateral: true });
7354
7600
  }
7355
- function measurements(values, label) {
7601
+ function measurements(values, label2) {
7356
7602
  return values.map((value) => {
7357
7603
  const normalized = value.trim().toLowerCase();
7358
7604
  if (!MEASUREMENT_HEX.test(normalized)) {
7359
- throw new Error(`${label} holds ${JSON.stringify(value)}, which is not a 48-byte hex measurement`);
7605
+ throw new Error(`${label2} holds ${JSON.stringify(value)}, which is not a 48-byte hex measurement`);
7360
7606
  }
7361
7607
  return normalized;
7362
7608
  });
@@ -7842,8 +8088,24 @@ function nodeReleaseVersionFromImage(osImage) {
7842
8088
  return `${Number(match[1])}.${Number(match[2])}.${Number(match[3])}`;
7843
8089
  }
7844
8090
  async function fetchNodeReleaseVersion(baseUrl, options = {}) {
7845
- const url = `${baseUrl.replace(/\/+$/, "")}/admin-api/tee/info`;
7846
- const response = await (options.fetch ?? fetch)(url, { headers: { accept: "application/json" } });
8091
+ const version = await readNodeReleaseVersion(baseUrl, options.fetch ?? fetch);
8092
+ if (version === void 0) {
8093
+ throw new Error(
8094
+ `${infoUrl(baseUrl)} was refused unsealed: the node requires sealing and is too old to name its release before a session exists. Name the release it runs yourself (createSignedReleaseSealedFetch's \`releaseVersion\`), or upgrade the node`
8095
+ );
8096
+ }
8097
+ return version;
8098
+ }
8099
+ function infoUrl(baseUrl) {
8100
+ return `${baseUrl.replace(/\/+$/, "")}/admin-api/tee/info`;
8101
+ }
8102
+ async function readNodeReleaseVersion(baseUrl, givenFetch) {
8103
+ const url = infoUrl(baseUrl);
8104
+ const response = await givenFetch(url, { headers: { accept: "application/json" } });
8105
+ if (response.status === 403) {
8106
+ const code = await response.json().then((body) => body?.error?.code).catch(() => void 0);
8107
+ if (code === "sealed_required") return void 0;
8108
+ }
7847
8109
  if (!response.ok) throw new Error(`Fetching ${url} failed: HTTP ${response.status}`);
7848
8110
  let osImage;
7849
8111
  try {
@@ -7890,10 +8152,19 @@ function createSignedReleaseVerifier(options) {
7890
8152
  return Object.assign(verifier, { includeCollateral: true });
7891
8153
  }
7892
8154
  function createSignedReleaseSealedFetch(options) {
7893
- const { baseUrl, releaseSource, applicationId, applicationHash, fetch: givenFetch, ...verifierOptions } = options;
8155
+ const {
8156
+ baseUrl,
8157
+ releaseSource,
8158
+ releaseVersion: fallbackVersion,
8159
+ applicationId,
8160
+ applicationHash,
8161
+ fetch: givenFetch,
8162
+ ...verifierOptions
8163
+ } = options;
8164
+ if (fallbackVersion !== void 0) releaseVersion(fallbackVersion, "releaseVersion");
7894
8165
  const baseFetch = givenFetch ?? ((input, init) => fetch(input, init));
7895
8166
  const release = async () => {
7896
- const version = await fetchNodeReleaseVersion(baseUrl, { fetch: baseFetch });
8167
+ const version = fallbackVersion === void 0 ? await fetchNodeReleaseVersion(baseUrl, { fetch: baseFetch }) : await readNodeReleaseVersion(baseUrl, baseFetch) ?? fallbackVersion;
7897
8168
  return typeof releaseSource === "function" ? releaseSource({ baseUrl, version, fetch: baseFetch }) : fetchNodeRelease(cloudNodeReleaseUrl(releaseSource ?? DEFAULT_RELEASE_MIRROR, version), { fetch: baseFetch });
7898
8169
  };
7899
8170
  return createAttestedSealedFetch({
@@ -7953,18 +8224,18 @@ var ROOT_OP = {
7953
8224
  NamespaceCreatedV2: 9,
7954
8225
  MemberJoinedViaTeeAttestation: 10
7955
8226
  };
7956
- function bytes32(value, label) {
8227
+ function bytes32(value, label2) {
7957
8228
  if (value.length !== 32) {
7958
- throw new Error(`${label} must be 32 bytes, got ${value.length}`);
8229
+ throw new Error(`${label2} must be 32 bytes, got ${value.length}`);
7959
8230
  }
7960
8231
  return new Uint8Array(value);
7961
8232
  }
7962
- function optionalBytes32(value, label) {
8233
+ function optionalBytes32(value, label2) {
7963
8234
  if (value === null || value === void 0) {
7964
8235
  return new Uint8Array([0]);
7965
8236
  }
7966
8237
  if (value.length !== 32) {
7967
- throw new Error(`${label} must be 32 bytes, got ${value.length}`);
8238
+ throw new Error(`${label2} must be 32 bytes, got ${value.length}`);
7968
8239
  }
7969
8240
  return concat(new Uint8Array([1]), new Uint8Array(value));
7970
8241
  }
@@ -8046,7 +8317,7 @@ async function signMemberJoinOp(input) {
8046
8317
  }
8047
8318
 
8048
8319
  // src/login/login.ts
8049
- var SIGN_DOMAIN3 = new TextEncoder().encode("calimero.auth.login.v1");
8320
+ var SIGN_DOMAIN4 = new TextEncoder().encode("calimero.auth.login.v1");
8050
8321
  var AUDIENCE_TAG = {
8051
8322
  webOrigin: 0,
8052
8323
  codeSigningId: 1,
@@ -8085,7 +8356,7 @@ async function signLoginStatement(input) {
8085
8356
  const deviceKey = await derivePublicKey(input.deviceSecret);
8086
8357
  const issuedAt = u64le(input.issuedAt);
8087
8358
  const expiresAt = u64le(input.expiresAt);
8088
- const preimage = await domainHash(SIGN_DOMAIN3, [
8359
+ const preimage = await domainHash(SIGN_DOMAIN4, [
8089
8360
  node,
8090
8361
  audienceSigningBytes(input.audience),
8091
8362
  challenge,
@@ -8320,6 +8591,7 @@ export {
8320
8591
  createSignedReleaseVerifier,
8321
8592
  createTimeoutSignal,
8322
8593
  createUniversalHttpClient,
8594
+ creationInitHash,
8323
8595
  deviceCertPayload,
8324
8596
  discoverLocalNodes,
8325
8597
  encodeSignedInvitation,
@@ -8339,6 +8611,7 @@ export {
8339
8611
  nodeEndpoint,
8340
8612
  nodeReleaseVersionFromImage,
8341
8613
  parseAuthCallback,
8614
+ parseCreationWarrant,
8342
8615
  probeNodeHealth,
8343
8616
  redeemInvitation,
8344
8617
  requestBodyHash,
@@ -8346,6 +8619,7 @@ export {
8346
8619
  shouldRetain,
8347
8620
  signAccountLink,
8348
8621
  signAccountLogin,
8622
+ signCreationWarrant,
8349
8623
  signDeviceCert,
8350
8624
  signLoginStatement,
8351
8625
  signMemberJoinOp,