@calimero-network/mero-js 19.7.2 → 19.8.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/cloud/cloud-client.d.ts +38 -0
- package/dist/cloud/cloud-client.js +46 -1
- package/dist/cloud/index.d.ts +2 -0
- package/dist/cloud/index.js +1 -0
- package/dist/cloud/routing-proof.d.ts +92 -0
- package/dist/cloud/routing-proof.js +92 -0
- package/dist/index.browser.mjs +2 -2
- package/dist/index.browser.mjs.map +4 -4
- package/dist/index.cjs +76 -2
- package/dist/index.cjs.map +4 -4
- package/dist/index.mjs +76 -2
- package/dist/index.mjs.map +4 -4
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -76,10 +76,12 @@ __export(index_exports, {
|
|
|
76
76
|
nodeEndpoint: () => nodeEndpoint,
|
|
77
77
|
parseAuthCallback: () => parseAuthCallback,
|
|
78
78
|
probeNodeHealth: () => probeNodeHealth,
|
|
79
|
+
routingProofHeaders: () => routingProofHeaders,
|
|
79
80
|
signAccountLink: () => signAccountLink,
|
|
80
81
|
signDeviceCert: () => signDeviceCert,
|
|
81
82
|
signLoginStatement: () => signLoginStatement,
|
|
82
83
|
signMemberJoinOp: () => signMemberJoinOp,
|
|
84
|
+
signRoutingChallenge: () => signRoutingChallenge,
|
|
83
85
|
signWarrant: () => signWarrant,
|
|
84
86
|
withCap: () => withCap,
|
|
85
87
|
withRetry: () => withRetry,
|
|
@@ -4838,6 +4840,38 @@ function base64(bytes) {
|
|
|
4838
4840
|
return btoa(binary);
|
|
4839
4841
|
}
|
|
4840
4842
|
|
|
4843
|
+
// src/cloud/routing-proof.ts
|
|
4844
|
+
var ROUTING_PROOF_DOMAIN = new TextEncoder().encode(
|
|
4845
|
+
"calimero.mdma.routing-read.v1\0"
|
|
4846
|
+
);
|
|
4847
|
+
async function signRoutingChallenge(nonce, deviceSecret) {
|
|
4848
|
+
fromHex(deviceSecret, "deviceSecret", 32);
|
|
4849
|
+
const key = await importSigningKey(deviceSecret);
|
|
4850
|
+
const message = concat(
|
|
4851
|
+
ROUTING_PROOF_DOMAIN,
|
|
4852
|
+
new TextEncoder().encode(nonce)
|
|
4853
|
+
);
|
|
4854
|
+
const signature = new Uint8Array(
|
|
4855
|
+
await crypto.subtle.sign({ name: "Ed25519" }, key, message)
|
|
4856
|
+
);
|
|
4857
|
+
return base642(signature);
|
|
4858
|
+
}
|
|
4859
|
+
async function routingProofHeaders(challenge, credential) {
|
|
4860
|
+
return {
|
|
4861
|
+
"X-Calimero-Credential": credential.credential,
|
|
4862
|
+
"X-Calimero-Nonce": challenge.nonce,
|
|
4863
|
+
"X-Calimero-Signature": await signRoutingChallenge(
|
|
4864
|
+
challenge.nonce,
|
|
4865
|
+
credential.deviceSecret
|
|
4866
|
+
)
|
|
4867
|
+
};
|
|
4868
|
+
}
|
|
4869
|
+
function base642(bytes) {
|
|
4870
|
+
let binary = "";
|
|
4871
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
4872
|
+
return btoa(binary);
|
|
4873
|
+
}
|
|
4874
|
+
|
|
4841
4875
|
// src/cloud/cloud-client.ts
|
|
4842
4876
|
var DEFAULT_CLOUD_BASE_URL = "https://cloud.calimero.network";
|
|
4843
4877
|
var REFRESH_HEADER = "x-mdma-session-refresh";
|
|
@@ -4850,6 +4884,7 @@ var CloudClient = class {
|
|
|
4850
4884
|
const injected = config.fetch;
|
|
4851
4885
|
this.fetchImpl = injected ? (input, init) => injected(input, init) : (input, init) => globalThis.fetch(input, init);
|
|
4852
4886
|
this.timeoutMs = config.timeoutMs ?? 1e4;
|
|
4887
|
+
this.routingCredential = config.routingCredential;
|
|
4853
4888
|
if (config.sessionToken) {
|
|
4854
4889
|
this.session = {
|
|
4855
4890
|
sessionToken: config.sessionToken,
|
|
@@ -4976,7 +5011,8 @@ var CloudClient = class {
|
|
|
4976
5011
|
*/
|
|
4977
5012
|
async getNamespaceRouting(namespaceId) {
|
|
4978
5013
|
const body = await this.request("GET", `/api/cloud/namespaces/${encodeURIComponent(namespaceId)}/admitters`, {
|
|
4979
|
-
anonymous: true
|
|
5014
|
+
anonymous: true,
|
|
5015
|
+
headers: await this.routingProof(namespaceId)
|
|
4980
5016
|
});
|
|
4981
5017
|
return {
|
|
4982
5018
|
namespaceId: String(body.namespace_id ?? namespaceId),
|
|
@@ -4995,6 +5031,41 @@ var CloudClient = class {
|
|
|
4995
5031
|
writable: body.writable === true
|
|
4996
5032
|
};
|
|
4997
5033
|
}
|
|
5034
|
+
/**
|
|
5035
|
+
* Ask the cloud for a challenge to prove an account against.
|
|
5036
|
+
*
|
|
5037
|
+
* Public and unauthenticated on purpose, and safe to be: the nonce is sealed
|
|
5038
|
+
* and bound to this one namespace, so it is not a capability — it is the
|
|
5039
|
+
* thing a capability gets demonstrated against. A caller with no credential
|
|
5040
|
+
* gains nothing by holding one.
|
|
5041
|
+
*
|
|
5042
|
+
* {@link getNamespaceRouting} calls this for you when the client was
|
|
5043
|
+
* constructed with a `routingCredential`. Call it directly only to sign a
|
|
5044
|
+
* challenge somewhere this client cannot reach the key.
|
|
5045
|
+
*/
|
|
5046
|
+
async getRoutingChallenge(namespaceId) {
|
|
5047
|
+
const body = await this.request("GET", `/api/cloud/namespaces/${encodeURIComponent(namespaceId)}/challenge`, {
|
|
5048
|
+
anonymous: true
|
|
5049
|
+
});
|
|
5050
|
+
return {
|
|
5051
|
+
namespaceId: String(body.namespace_id ?? namespaceId),
|
|
5052
|
+
nonce: String(body.nonce ?? ""),
|
|
5053
|
+
expiresAtMs: Number(body.expires_at_ms ?? 0)
|
|
5054
|
+
};
|
|
5055
|
+
}
|
|
5056
|
+
/**
|
|
5057
|
+
* The proof headers for one routing read, or nothing when no credential was
|
|
5058
|
+
* configured.
|
|
5059
|
+
*
|
|
5060
|
+
* A challenge per read rather than a cached one: they expire in about two
|
|
5061
|
+
* minutes and are single-namespace, so caching would trade one cheap request
|
|
5062
|
+
* for a class of expiry bug that only shows up on a slow client.
|
|
5063
|
+
*/
|
|
5064
|
+
async routingProof(namespaceId) {
|
|
5065
|
+
if (!this.routingCredential) return void 0;
|
|
5066
|
+
const challenge = await this.getRoutingChallenge(namespaceId);
|
|
5067
|
+
return routingProofHeaders(challenge, this.routingCredential);
|
|
5068
|
+
}
|
|
4998
5069
|
/**
|
|
4999
5070
|
* The node to send a signed join to, chosen from those an invitation names.
|
|
5000
5071
|
*
|
|
@@ -5248,7 +5319,10 @@ var CloudClient = class {
|
|
|
5248
5319
|
"Not signed in to Calimero Cloud: call signInWithGoogle() or construct the client with a sessionToken"
|
|
5249
5320
|
);
|
|
5250
5321
|
}
|
|
5251
|
-
const headers = {
|
|
5322
|
+
const headers = {
|
|
5323
|
+
...options.headers,
|
|
5324
|
+
Accept: "application/json"
|
|
5325
|
+
};
|
|
5252
5326
|
if (options.body !== void 0) headers["Content-Type"] = "application/json";
|
|
5253
5327
|
if (!options.anonymous && this.session) {
|
|
5254
5328
|
headers.Authorization = `Bearer ${this.session.sessionToken}`;
|