@calimero-network/mero-js 19.25.0 → 19.27.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/admin-api/admin-client.d.ts +4 -0
- package/dist/admin-api/admin-client.js +4 -0
- package/dist/admin-api/admin-types.d.ts +18 -0
- package/dist/admin-api/admin-types.js +0 -2
- package/dist/cloud/connect.d.ts +19 -0
- package/dist/cloud/connect.js +17 -1
- package/dist/index.browser.mjs +2 -2
- package/dist/index.browser.mjs.map +4 -4
- package/dist/index.cjs +222 -91
- package/dist/index.cjs.map +4 -4
- package/dist/index.mjs +222 -91
- package/dist/index.mjs.map +4 -4
- package/dist/sealed/index.d.ts +4 -2
- package/dist/sealed/index.js +2 -1
- package/dist/sealed/noise.js +11 -3
- package/dist/sealed/sealed.d.ts +46 -6
- package/dist/sealed/sealed.js +57 -1
- package/dist/sealed/verify.d.ts +109 -0
- package/dist/sealed/verify.js +116 -0
- package/package.json +2 -1
package/dist/index.mjs
CHANGED
|
@@ -1848,6 +1848,10 @@ var AdminApiClient = class {
|
|
|
1848
1848
|
async teeAttest(request) {
|
|
1849
1849
|
return unwrap(await this.httpClient.post("/admin-api/tee/attest", request));
|
|
1850
1850
|
}
|
|
1851
|
+
/**
|
|
1852
|
+
* @deprecated Nodes no longer serve `/admin-api/tee/verify-quote` (removed in
|
|
1853
|
+
* core#3262), so this fails. Verify quotes with `createQuoteVerifier`.
|
|
1854
|
+
*/
|
|
1851
1855
|
async teeVerifyQuote(request) {
|
|
1852
1856
|
return unwrap(
|
|
1853
1857
|
await this.httpClient.post("/admin-api/tee/verify-quote", request)
|
|
@@ -6463,92 +6467,6 @@ function createLocalStorageNonceSource(key, storage) {
|
|
|
6463
6467
|
};
|
|
6464
6468
|
}
|
|
6465
6469
|
|
|
6466
|
-
// src/cloud/connect.ts
|
|
6467
|
-
async function connectCloud(options) {
|
|
6468
|
-
if (!options.sessionToken && !options.googleIdToken) {
|
|
6469
|
-
throw new Error("connectCloud needs either a sessionToken or a googleIdToken");
|
|
6470
|
-
}
|
|
6471
|
-
const cloud = new CloudClient({
|
|
6472
|
-
cloudBaseUrl: options.cloudBaseUrl,
|
|
6473
|
-
sessionToken: options.sessionToken,
|
|
6474
|
-
onSession: options.onSession,
|
|
6475
|
-
fetch: options.fetch,
|
|
6476
|
-
timeoutMs: options.timeoutMs
|
|
6477
|
-
});
|
|
6478
|
-
if (!options.sessionToken && options.googleIdToken) {
|
|
6479
|
-
await cloud.signInWithGoogle(options.googleIdToken);
|
|
6480
|
-
}
|
|
6481
|
-
const namespaces = await cloud.getMyNamespaces();
|
|
6482
|
-
const namespace = pickNamespace(namespaces, options.namespaceId);
|
|
6483
|
-
const relays = await cloud.getNamespaceRelays(namespace.namespaceId);
|
|
6484
|
-
const relayInfo = relays.find((r) => r.authorshipReady && r.relayUrl !== null && r.executorAccount !== null) ?? null;
|
|
6485
|
-
if (!relayInfo) {
|
|
6486
|
-
throw new Error(explainNoRelay(namespace, relays));
|
|
6487
|
-
}
|
|
6488
|
-
const relay = new RelayClient({
|
|
6489
|
-
// Checked by `findExecutingRelay`, which is the only thing that returns a
|
|
6490
|
-
// relay — narrowed here rather than re-validated, so the invariant lives in
|
|
6491
|
-
// one place.
|
|
6492
|
-
relayUrl: relayInfo.relayUrl,
|
|
6493
|
-
executorAccount: relayInfo.executorAccount,
|
|
6494
|
-
authorAccount: options.authorAccount,
|
|
6495
|
-
authorProof: options.authorProof,
|
|
6496
|
-
deviceSecret: options.deviceSecret,
|
|
6497
|
-
nonces: options.nonces ?? await defaultNonceSource(options.deviceSecret),
|
|
6498
|
-
ttlSeconds: options.ttlSeconds,
|
|
6499
|
-
fetch: options.fetch,
|
|
6500
|
-
timeoutMs: options.timeoutMs
|
|
6501
|
-
});
|
|
6502
|
-
return {
|
|
6503
|
-
cloud,
|
|
6504
|
-
relay,
|
|
6505
|
-
namespaceId: namespace.namespaceId,
|
|
6506
|
-
namespace,
|
|
6507
|
-
relayInfo,
|
|
6508
|
-
execute: (contextId, method, argsJson) => relay.execute(contextId, method, argsJson)
|
|
6509
|
-
};
|
|
6510
|
-
}
|
|
6511
|
-
function pickNamespace(namespaces, requested) {
|
|
6512
|
-
if (requested) {
|
|
6513
|
-
const found = namespaces.find((n) => n.namespaceId === requested);
|
|
6514
|
-
if (!found) {
|
|
6515
|
-
throw new Error(
|
|
6516
|
-
`this account owns no namespace ${requested}; it owns: ${namespaces.map((n) => n.namespaceId).join(", ") || "(none)"}`
|
|
6517
|
-
);
|
|
6518
|
-
}
|
|
6519
|
-
return found;
|
|
6520
|
-
}
|
|
6521
|
-
if (namespaces.length === 0) {
|
|
6522
|
-
throw new Error(
|
|
6523
|
-
"this account owns no namespaces in the cloud: claim one first, then enable HA on it so a relay is assigned"
|
|
6524
|
-
);
|
|
6525
|
-
}
|
|
6526
|
-
if (namespaces.length > 1) {
|
|
6527
|
-
throw new Error(
|
|
6528
|
-
`this account owns ${namespaces.length} namespaces \u2014 pass namespaceId to say which: ${namespaces.map((n) => n.namespaceId).join(", ")}`
|
|
6529
|
-
);
|
|
6530
|
-
}
|
|
6531
|
-
return namespaces[0];
|
|
6532
|
-
}
|
|
6533
|
-
function explainNoRelay(namespace, relays) {
|
|
6534
|
-
if (relays.length === 0) {
|
|
6535
|
-
return namespace.haStatus === "enabled" ? `namespace ${namespace.namespaceId} has HA enabled but no relay has been assigned to it yet \u2014 retry shortly` : `namespace ${namespace.namespaceId} has no relays: enable HA on it in the cloud to have an attested node assigned`;
|
|
6536
|
-
}
|
|
6537
|
-
const waitingOnGrant = relays.filter((r) => !r.authorshipReady);
|
|
6538
|
-
if (waitingOnGrant.length === relays.length) {
|
|
6539
|
-
return `every relay on namespace ${namespace.namespaceId} is waiting for the authorship grant: an admin of the namespace must grant CAN_AUTHOR_ON_BEHALF to ${waitingOnGrant.map((r) => r.executorAccount ?? r.peerId).join(", ") || "the relay account"} \u2014 with AdminClient.grantAuthorship(namespaceId, account) for these relays, and AdminClient.openToDelegatedExecution(namespaceId) so relays assigned later need no further op`;
|
|
6540
|
-
}
|
|
6541
|
-
return `namespace ${namespace.namespaceId} has ${relays.length} relay(s), but none reported both a URL and an executor account yet \u2014 retry shortly`;
|
|
6542
|
-
}
|
|
6543
|
-
async function defaultNonceSource(deviceSecret) {
|
|
6544
|
-
const key = `mero-js:warrant-nonce:${hex(await derivePublicKey(deviceSecret))}`;
|
|
6545
|
-
try {
|
|
6546
|
-
return createLocalStorageNonceSource(key);
|
|
6547
|
-
} catch {
|
|
6548
|
-
return createMemoryNonceSource(1);
|
|
6549
|
-
}
|
|
6550
|
-
}
|
|
6551
|
-
|
|
6552
6470
|
// src/sealed/noise.ts
|
|
6553
6471
|
var PROTOCOL_NAME = "Noise_NK_25519_AESGCM_SHA256";
|
|
6554
6472
|
var DH_LEN = 32;
|
|
@@ -6646,9 +6564,16 @@ async function initiate(remoteStatic, prologue, fixedEphemeral) {
|
|
|
6646
6564
|
}
|
|
6647
6565
|
async function x25519KeyPair(secret) {
|
|
6648
6566
|
if (!secret) {
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6567
|
+
let pair;
|
|
6568
|
+
try {
|
|
6569
|
+
pair = await crypto.subtle.generateKey({ name: "X25519" }, true, [
|
|
6570
|
+
"deriveBits"
|
|
6571
|
+
]);
|
|
6572
|
+
} catch (error) {
|
|
6573
|
+
throw new Error(
|
|
6574
|
+
`Sealed transport needs WebCrypto with X25519, which this runtime lacks (${error?.name ?? "no crypto.subtle"}). Current browsers and Node have it; in React Native, install react-native-quick-crypto as the global crypto.`
|
|
6575
|
+
);
|
|
6576
|
+
}
|
|
6652
6577
|
const publicKey = new Uint8Array(await crypto.subtle.exportKey("raw", pair.publicKey));
|
|
6653
6578
|
return { privateKey: pair.privateKey, publicKey };
|
|
6654
6579
|
}
|
|
@@ -6741,7 +6666,8 @@ async function fetchAttestedTransportKey(admin, verify, options = {}) {
|
|
|
6741
6666
|
const attested = await admin.teeAttest({
|
|
6742
6667
|
nonce: nonce2,
|
|
6743
6668
|
applicationId: options.applicationId,
|
|
6744
|
-
bindTransportKey: true
|
|
6669
|
+
bindTransportKey: true,
|
|
6670
|
+
...verify.includeCollateral ? { includeCollateral: true } : {}
|
|
6745
6671
|
});
|
|
6746
6672
|
if (!attested.transportPublicKey) {
|
|
6747
6673
|
throw new Error("The node did not report a transport key; it predates sealed transport");
|
|
@@ -6749,11 +6675,44 @@ async function fetchAttestedTransportKey(admin, verify, options = {}) {
|
|
|
6749
6675
|
const transportKey = fromHex(attested.transportPublicKey, "transportPublicKey", 32);
|
|
6750
6676
|
const inner = options.applicationHash ? fromHex(options.applicationHash, "applicationHash", 32) : new Uint8Array(32);
|
|
6751
6677
|
const reportDataSuffix = hex(await transportKeyBinding(inner, transportKey));
|
|
6752
|
-
|
|
6678
|
+
const verified = await verify({
|
|
6679
|
+
quoteB64: attested.quoteB64,
|
|
6680
|
+
nonce: nonce2,
|
|
6681
|
+
reportDataSuffix,
|
|
6682
|
+
collateral: attested.collateral
|
|
6683
|
+
});
|
|
6684
|
+
if (!verified) {
|
|
6753
6685
|
throw new Error("The attestation did not verify, so its transport key is not trusted");
|
|
6754
6686
|
}
|
|
6755
6687
|
return transportKey;
|
|
6756
6688
|
}
|
|
6689
|
+
function createAttestedSealedFetch(options) {
|
|
6690
|
+
const baseFetch = options.fetch ?? ((input, init) => fetch(input, init));
|
|
6691
|
+
const attestUrl = `${options.baseUrl.replace(/\/+$/, "")}/admin-api/tee/attest`;
|
|
6692
|
+
const admin = {
|
|
6693
|
+
async teeAttest(request) {
|
|
6694
|
+
const response = await baseFetch(attestUrl, {
|
|
6695
|
+
method: "POST",
|
|
6696
|
+
headers: { "content-type": "application/json" },
|
|
6697
|
+
body: JSON.stringify(request)
|
|
6698
|
+
});
|
|
6699
|
+
if (!response.ok) {
|
|
6700
|
+
throw new Error(`The node refused to attest: HTTP ${response.status}`);
|
|
6701
|
+
}
|
|
6702
|
+
const body = await response.json();
|
|
6703
|
+
if (!body.data) throw new Error("The attestation response is malformed");
|
|
6704
|
+
return body.data;
|
|
6705
|
+
}
|
|
6706
|
+
};
|
|
6707
|
+
return createSealedFetch({
|
|
6708
|
+
baseUrl: options.baseUrl,
|
|
6709
|
+
transportPublicKey: () => fetchAttestedTransportKey(admin, options.verify, {
|
|
6710
|
+
applicationId: options.applicationId,
|
|
6711
|
+
applicationHash: options.applicationHash
|
|
6712
|
+
}),
|
|
6713
|
+
fetch: baseFetch
|
|
6714
|
+
});
|
|
6715
|
+
}
|
|
6757
6716
|
function createSealedFetch(options) {
|
|
6758
6717
|
const base = new URL(options.baseUrl);
|
|
6759
6718
|
const basePath = base.pathname.replace(/\/+$/, "");
|
|
@@ -6761,6 +6720,7 @@ function createSealedFetch(options) {
|
|
|
6761
6720
|
const baseFetch = options.fetch ?? ((input, init) => fetch(input, init));
|
|
6762
6721
|
const attest = typeof options.transportPublicKey === "function" ? options.transportPublicKey : void 0;
|
|
6763
6722
|
let transportKey = attest ? Promise.resolve().then(attest) : Promise.resolve(options.transportPublicKey);
|
|
6723
|
+
transportKey.catch(() => void 0);
|
|
6764
6724
|
let session;
|
|
6765
6725
|
const openSession = async () => {
|
|
6766
6726
|
try {
|
|
@@ -7011,6 +6971,175 @@ async function envelopeRefusal(response) {
|
|
|
7011
6971
|
return new SealedTransportError(response.status, code, message, retryAfterMs);
|
|
7012
6972
|
}
|
|
7013
6973
|
|
|
6974
|
+
// src/cloud/connect.ts
|
|
6975
|
+
async function connectCloud(options) {
|
|
6976
|
+
if (!options.sessionToken && !options.googleIdToken) {
|
|
6977
|
+
throw new Error("connectCloud needs either a sessionToken or a googleIdToken");
|
|
6978
|
+
}
|
|
6979
|
+
const cloud = new CloudClient({
|
|
6980
|
+
cloudBaseUrl: options.cloudBaseUrl,
|
|
6981
|
+
sessionToken: options.sessionToken,
|
|
6982
|
+
onSession: options.onSession,
|
|
6983
|
+
fetch: options.fetch,
|
|
6984
|
+
timeoutMs: options.timeoutMs
|
|
6985
|
+
});
|
|
6986
|
+
if (!options.sessionToken && options.googleIdToken) {
|
|
6987
|
+
await cloud.signInWithGoogle(options.googleIdToken);
|
|
6988
|
+
}
|
|
6989
|
+
const namespaces = await cloud.getMyNamespaces();
|
|
6990
|
+
const namespace = pickNamespace(namespaces, options.namespaceId);
|
|
6991
|
+
const relays = await cloud.getNamespaceRelays(namespace.namespaceId);
|
|
6992
|
+
const relayInfo = relays.find((r) => r.authorshipReady && r.relayUrl !== null && r.executorAccount !== null) ?? null;
|
|
6993
|
+
if (!relayInfo) {
|
|
6994
|
+
throw new Error(explainNoRelay(namespace, relays));
|
|
6995
|
+
}
|
|
6996
|
+
const relay = new RelayClient({
|
|
6997
|
+
// Checked by `findExecutingRelay`, which is the only thing that returns a
|
|
6998
|
+
// relay — narrowed here rather than re-validated, so the invariant lives in
|
|
6999
|
+
// one place.
|
|
7000
|
+
relayUrl: relayInfo.relayUrl,
|
|
7001
|
+
executorAccount: relayInfo.executorAccount,
|
|
7002
|
+
authorAccount: options.authorAccount,
|
|
7003
|
+
authorProof: options.authorProof,
|
|
7004
|
+
deviceSecret: options.deviceSecret,
|
|
7005
|
+
nonces: options.nonces ?? await defaultNonceSource(options.deviceSecret),
|
|
7006
|
+
ttlSeconds: options.ttlSeconds,
|
|
7007
|
+
// Only the relay is sealed: a sealed fetch is bound to one node and refuses
|
|
7008
|
+
// any other URL, and the cloud calls above carry no intent.
|
|
7009
|
+
fetch: options.seal ? createAttestedSealedFetch({
|
|
7010
|
+
baseUrl: relayInfo.relayUrl,
|
|
7011
|
+
verify: options.seal,
|
|
7012
|
+
fetch: options.fetch
|
|
7013
|
+
}) : options.fetch,
|
|
7014
|
+
timeoutMs: options.timeoutMs
|
|
7015
|
+
});
|
|
7016
|
+
return {
|
|
7017
|
+
cloud,
|
|
7018
|
+
relay,
|
|
7019
|
+
namespaceId: namespace.namespaceId,
|
|
7020
|
+
namespace,
|
|
7021
|
+
relayInfo,
|
|
7022
|
+
execute: (contextId, method, argsJson) => relay.execute(contextId, method, argsJson)
|
|
7023
|
+
};
|
|
7024
|
+
}
|
|
7025
|
+
function pickNamespace(namespaces, requested) {
|
|
7026
|
+
if (requested) {
|
|
7027
|
+
const found = namespaces.find((n) => n.namespaceId === requested);
|
|
7028
|
+
if (!found) {
|
|
7029
|
+
throw new Error(
|
|
7030
|
+
`this account owns no namespace ${requested}; it owns: ${namespaces.map((n) => n.namespaceId).join(", ") || "(none)"}`
|
|
7031
|
+
);
|
|
7032
|
+
}
|
|
7033
|
+
return found;
|
|
7034
|
+
}
|
|
7035
|
+
if (namespaces.length === 0) {
|
|
7036
|
+
throw new Error(
|
|
7037
|
+
"this account owns no namespaces in the cloud: claim one first, then enable HA on it so a relay is assigned"
|
|
7038
|
+
);
|
|
7039
|
+
}
|
|
7040
|
+
if (namespaces.length > 1) {
|
|
7041
|
+
throw new Error(
|
|
7042
|
+
`this account owns ${namespaces.length} namespaces \u2014 pass namespaceId to say which: ${namespaces.map((n) => n.namespaceId).join(", ")}`
|
|
7043
|
+
);
|
|
7044
|
+
}
|
|
7045
|
+
return namespaces[0];
|
|
7046
|
+
}
|
|
7047
|
+
function explainNoRelay(namespace, relays) {
|
|
7048
|
+
if (relays.length === 0) {
|
|
7049
|
+
return namespace.haStatus === "enabled" ? `namespace ${namespace.namespaceId} has HA enabled but no relay has been assigned to it yet \u2014 retry shortly` : `namespace ${namespace.namespaceId} has no relays: enable HA on it in the cloud to have an attested node assigned`;
|
|
7050
|
+
}
|
|
7051
|
+
const waitingOnGrant = relays.filter((r) => !r.authorshipReady);
|
|
7052
|
+
if (waitingOnGrant.length === relays.length) {
|
|
7053
|
+
return `every relay on namespace ${namespace.namespaceId} is waiting for the authorship grant: an admin of the namespace must grant CAN_AUTHOR_ON_BEHALF to ${waitingOnGrant.map((r) => r.executorAccount ?? r.peerId).join(", ") || "the relay account"} \u2014 with AdminClient.grantAuthorship(namespaceId, account) for these relays, and AdminClient.openToDelegatedExecution(namespaceId) so relays assigned later need no further op`;
|
|
7054
|
+
}
|
|
7055
|
+
return `namespace ${namespace.namespaceId} has ${relays.length} relay(s), but none reported both a URL and an executor account yet \u2014 retry shortly`;
|
|
7056
|
+
}
|
|
7057
|
+
async function defaultNonceSource(deviceSecret) {
|
|
7058
|
+
const key = `mero-js:warrant-nonce:${hex(await derivePublicKey(deviceSecret))}`;
|
|
7059
|
+
try {
|
|
7060
|
+
return createLocalStorageNonceSource(key);
|
|
7061
|
+
} catch {
|
|
7062
|
+
return createMemoryNonceSource(1);
|
|
7063
|
+
}
|
|
7064
|
+
}
|
|
7065
|
+
|
|
7066
|
+
// src/sealed/verify.ts
|
|
7067
|
+
var MEASUREMENT_HEX = /^[0-9a-f]{96}$/;
|
|
7068
|
+
function createQuoteVerifier(options) {
|
|
7069
|
+
const allowedMrtd = measurements(options.allowedMrtd, "allowedMrtd");
|
|
7070
|
+
if (allowedMrtd.length === 0) {
|
|
7071
|
+
throw new Error("allowedMrtd is empty, so no quote would ever be accepted");
|
|
7072
|
+
}
|
|
7073
|
+
const allowedRtmr = [
|
|
7074
|
+
measurements(options.allowedRtmr0 ?? [], "allowedRtmr0"),
|
|
7075
|
+
measurements(options.allowedRtmr1 ?? [], "allowedRtmr1"),
|
|
7076
|
+
measurements(options.allowedRtmr2 ?? [], "allowedRtmr2"),
|
|
7077
|
+
measurements(options.allowedRtmr3 ?? [], "allowedRtmr3")
|
|
7078
|
+
];
|
|
7079
|
+
const allowedStatuses = options.allowedTcbStatuses ?? ["UpToDate"];
|
|
7080
|
+
const now = options.now ?? Date.now;
|
|
7081
|
+
const verifier = async ({
|
|
7082
|
+
quoteB64,
|
|
7083
|
+
nonce: nonce2,
|
|
7084
|
+
reportDataSuffix,
|
|
7085
|
+
collateral
|
|
7086
|
+
}) => {
|
|
7087
|
+
const quote = fromBase64(quoteB64);
|
|
7088
|
+
const against = collateral ?? await options.fetchCollateral?.(quote);
|
|
7089
|
+
if (!against) {
|
|
7090
|
+
throw new Error(
|
|
7091
|
+
"The node sent no collateral for its quote, and no fetchCollateral was given to get it"
|
|
7092
|
+
);
|
|
7093
|
+
}
|
|
7094
|
+
let verified;
|
|
7095
|
+
try {
|
|
7096
|
+
verified = options.dcapVerify(quote, against, Math.floor(now() / 1e3));
|
|
7097
|
+
} catch (error) {
|
|
7098
|
+
throw new Error(`The quote did not verify: ${error?.message ?? String(error)}`);
|
|
7099
|
+
}
|
|
7100
|
+
if (verified.status === "Revoked" || !allowedStatuses.includes(verified.status)) {
|
|
7101
|
+
throw new Error(`The platform's TCB status is ${verified.status}, which is not accepted`);
|
|
7102
|
+
}
|
|
7103
|
+
const td = tdReport(verified.report);
|
|
7104
|
+
if (!allowedMrtd.includes(hex(td.mrTd))) {
|
|
7105
|
+
throw new Error(`MRTD ${hex(td.mrTd)} is not an image this verifier trusts`);
|
|
7106
|
+
}
|
|
7107
|
+
const registers = [td.rtMr0, td.rtMr1, td.rtMr2, td.rtMr3];
|
|
7108
|
+
registers.forEach((register, index) => {
|
|
7109
|
+
const allowed = allowedRtmr[index];
|
|
7110
|
+
if (allowed.length > 0 && !allowed.includes(hex(register))) {
|
|
7111
|
+
throw new Error(`RTMR${index} ${hex(register)} is not one this verifier trusts`);
|
|
7112
|
+
}
|
|
7113
|
+
});
|
|
7114
|
+
if (hex(td.reportData) !== `${nonce2}${reportDataSuffix}`.toLowerCase()) {
|
|
7115
|
+
throw new Error("The quote does not commit to this nonce and binding");
|
|
7116
|
+
}
|
|
7117
|
+
return true;
|
|
7118
|
+
};
|
|
7119
|
+
return Object.assign(verifier, { includeCollateral: true });
|
|
7120
|
+
}
|
|
7121
|
+
function measurements(values, label) {
|
|
7122
|
+
return values.map((value) => {
|
|
7123
|
+
const normalized = value.trim().toLowerCase();
|
|
7124
|
+
if (!MEASUREMENT_HEX.test(normalized)) {
|
|
7125
|
+
throw new Error(`${label} holds ${JSON.stringify(value)}, which is not a 48-byte hex measurement`);
|
|
7126
|
+
}
|
|
7127
|
+
return normalized;
|
|
7128
|
+
});
|
|
7129
|
+
}
|
|
7130
|
+
function tdReport(report) {
|
|
7131
|
+
const data = report.data;
|
|
7132
|
+
if (report.type === "td10" && data) return data;
|
|
7133
|
+
if (report.type === "td15" && data?.base) return data.base;
|
|
7134
|
+
throw new Error(`The quote is a ${report.type} quote, not a TDX one`);
|
|
7135
|
+
}
|
|
7136
|
+
function fromBase64(value) {
|
|
7137
|
+
const binary = atob(value);
|
|
7138
|
+
const bytes = new Uint8Array(binary.length);
|
|
7139
|
+
for (let i = 0; i < binary.length; i += 1) bytes[i] = binary.charCodeAt(i);
|
|
7140
|
+
return bytes;
|
|
7141
|
+
}
|
|
7142
|
+
|
|
7014
7143
|
// src/namespace-op/namespace-op.ts
|
|
7015
7144
|
var SIGNED_NAMESPACE_OP_SCHEMA_VERSION = 8;
|
|
7016
7145
|
var NAMESPACE_SIGN_DOMAIN = new TextEncoder().encode("calimero.namespace.v1");
|
|
@@ -7373,6 +7502,7 @@ export {
|
|
|
7373
7502
|
connectCloud,
|
|
7374
7503
|
createAdminApiClient,
|
|
7375
7504
|
createAdminApiClientFromHttpClient,
|
|
7505
|
+
createAttestedSealedFetch,
|
|
7376
7506
|
createAuthApiClient,
|
|
7377
7507
|
createAuthApiClientFromHttpClient,
|
|
7378
7508
|
createBrowserAdminApiClient,
|
|
@@ -7386,6 +7516,7 @@ export {
|
|
|
7386
7516
|
createNodeAuthApiClient,
|
|
7387
7517
|
createNodeHttpClient,
|
|
7388
7518
|
createProofSigner,
|
|
7519
|
+
createQuoteVerifier,
|
|
7389
7520
|
createRetryableMethod,
|
|
7390
7521
|
createSealedFetch,
|
|
7391
7522
|
createTimeoutSignal,
|