@calimero-network/mero-js 18.3.0 → 19.1.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 +23 -3
- package/dist/admin-api/admin-client.js +33 -4
- package/dist/admin-api/admin-types.d.ts +19 -0
- package/dist/index.browser.mjs +2 -2
- package/dist/index.browser.mjs.map +3 -3
- package/dist/index.cjs +66 -6
- package/dist/index.cjs.map +2 -2
- package/dist/index.mjs +66 -6
- package/dist/index.mjs.map +2 -2
- package/dist/warrant/warrant.d.ts +89 -10
- package/dist/warrant/warrant.js +109 -12
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -949,13 +949,30 @@ var AdminApiClient = class {
|
|
|
949
949
|
);
|
|
950
950
|
return { blobs: res.blobs.map((b) => ({ blobId: b.blob_id, size: b.size })) };
|
|
951
951
|
}
|
|
952
|
+
/**
|
|
953
|
+
* Blob-read query params. `context_id` is the same snake_case param
|
|
954
|
+
* {@link uploadBlob} announces with; building it in one place keeps the read
|
|
955
|
+
* side from drifting from the write side.
|
|
956
|
+
*/
|
|
957
|
+
blobPath(blobId, options) {
|
|
958
|
+
if (!options?.contextId) return `/admin-api/blobs/${blobId}`;
|
|
959
|
+
const params = new URLSearchParams({ context_id: options.contextId });
|
|
960
|
+
return `/admin-api/blobs/${blobId}?${params.toString()}`;
|
|
961
|
+
}
|
|
952
962
|
/**
|
|
953
963
|
* Download a blob's raw bytes. `GET /admin-api/blobs/:id` streams the blob
|
|
954
964
|
* content (e.g. `application/gzip`), NOT JSON — so fetch it as an ArrayBuffer.
|
|
955
965
|
* Use {@link listBlobs} for `{ blobId, size }` metadata.
|
|
966
|
+
*
|
|
967
|
+
* Without `contextId` the read is local-only: the node answers from its own
|
|
968
|
+
* blob store and returns immediately, or 404s. Passing `contextId` opts into
|
|
969
|
+
* network discovery — the node probes that context's peers (availability
|
|
970
|
+
* nodes first) for a holder, then transfers the bytes. Budget for it: core
|
|
971
|
+
* bounds discovery by a ~30s deadline, and the transfer is on top of that, so
|
|
972
|
+
* the worst case is well past what a UI should block on unhinted.
|
|
956
973
|
*/
|
|
957
|
-
async getBlob(blobId) {
|
|
958
|
-
return this.httpClient.get(
|
|
974
|
+
async getBlob(blobId, options) {
|
|
975
|
+
return this.httpClient.get(this.blobPath(blobId, options), {
|
|
959
976
|
parse: "arrayBuffer"
|
|
960
977
|
});
|
|
961
978
|
}
|
|
@@ -963,15 +980,26 @@ var AdminApiClient = class {
|
|
|
963
980
|
* Fetch a blob's metadata without downloading it. `HEAD /admin-api/blobs/:id`
|
|
964
981
|
* returns the info in response headers (size via `content-length`, plus
|
|
965
982
|
* `x-blob-id`/`x-blob-hash`/`x-blob-mime-type`).
|
|
983
|
+
*
|
|
984
|
+
* Without `contextId` this is a local-only presence check that returns
|
|
985
|
+
* immediately. Passing `contextId` opts into the same network discovery
|
|
986
|
+
* {@link getBlob} uses — presence and size answered by probing the context's
|
|
987
|
+
* peers, with no transfer — so it inherits core's ~30s discovery deadline as
|
|
988
|
+
* its worst case. A probe only carries `found` and `size`, so a peer-sourced
|
|
989
|
+
* answer has no `hash`/`mimeType`; read `source` to tell the two apart.
|
|
966
990
|
*/
|
|
967
|
-
async getBlobInfo(blobId) {
|
|
968
|
-
const { headers } = await this.httpClient.head(
|
|
991
|
+
async getBlobInfo(blobId, options) {
|
|
992
|
+
const { headers } = await this.httpClient.head(this.blobPath(blobId, options));
|
|
969
993
|
const size = Number(headers["content-length"]);
|
|
970
994
|
return {
|
|
971
995
|
blobId: headers["x-blob-id"] ?? blobId,
|
|
972
996
|
size: Number.isFinite(size) ? size : 0,
|
|
973
997
|
hash: headers["x-blob-hash"],
|
|
974
|
-
mimeType: headers["x-blob-mime-type"]
|
|
998
|
+
mimeType: headers["x-blob-mime-type"],
|
|
999
|
+
// Nodes that predate the context-aware HEAD omit this header entirely, so
|
|
1000
|
+
// it stays undefined rather than being defaulted to 'local' — absent means
|
|
1001
|
+
// "the node didn't say", which is not the same claim as "served locally".
|
|
1002
|
+
source: headers["x-blob-source"]
|
|
975
1003
|
};
|
|
976
1004
|
}
|
|
977
1005
|
// ---- Alias Management ----
|
|
@@ -3082,8 +3110,10 @@ async function derivePublicKey(secretHex) {
|
|
|
3082
3110
|
}
|
|
3083
3111
|
|
|
3084
3112
|
// src/warrant/warrant.ts
|
|
3085
|
-
var SIGN_DOMAIN = new TextEncoder().encode("calimero.warrant.
|
|
3113
|
+
var SIGN_DOMAIN = new TextEncoder().encode("calimero.warrant.v2");
|
|
3086
3114
|
var INTENT_DOMAIN = new TextEncoder().encode("calimero.warrant.intent.v1");
|
|
3115
|
+
var MAX_CITED_HEADS = 64;
|
|
3116
|
+
var UNPINNED_APP = "00".repeat(32);
|
|
3087
3117
|
async function intentHash(method, argsJson) {
|
|
3088
3118
|
const args = new TextEncoder().encode(JSON.stringify(argsJson));
|
|
3089
3119
|
return domainHash(INTENT_DOMAIN, [new TextEncoder().encode(method), args]);
|
|
@@ -3092,8 +3122,16 @@ async function signWarrant(input) {
|
|
|
3092
3122
|
const context = fromHex(input.context, "context", 32);
|
|
3093
3123
|
const authorAccount = fromHex(input.authorAccount, "authorAccount", 32);
|
|
3094
3124
|
const executor = fromHex(input.executor, "executor", 32);
|
|
3125
|
+
const appVersion = fromHex(
|
|
3126
|
+
input.appVersion ?? UNPINNED_APP,
|
|
3127
|
+
"appVersion",
|
|
3128
|
+
32
|
|
3129
|
+
);
|
|
3130
|
+
const accountHeads = citedHeads(input.accountHeads, "accountHeads");
|
|
3131
|
+
const governanceFloor = citedHeads(input.governanceFloor, "governanceFloor");
|
|
3095
3132
|
const key = await importSigningKey(input.deviceSecret);
|
|
3096
3133
|
const publicKey = await derivePublicKey(input.deviceSecret);
|
|
3134
|
+
const method = new TextEncoder().encode(input.method);
|
|
3097
3135
|
const commitment = await intentHash(input.method, input.argsJson);
|
|
3098
3136
|
const nonce = u64le(input.nonce);
|
|
3099
3137
|
const notAfter = u64le(input.notAfter);
|
|
@@ -3102,7 +3140,13 @@ async function signWarrant(input) {
|
|
|
3102
3140
|
authorAccount,
|
|
3103
3141
|
publicKey,
|
|
3104
3142
|
executor,
|
|
3143
|
+
appVersion,
|
|
3144
|
+
method,
|
|
3105
3145
|
commitment,
|
|
3146
|
+
u64le(accountHeads.length),
|
|
3147
|
+
...accountHeads,
|
|
3148
|
+
u64le(governanceFloor.length),
|
|
3149
|
+
...governanceFloor,
|
|
3106
3150
|
nonce,
|
|
3107
3151
|
notAfter
|
|
3108
3152
|
]);
|
|
@@ -3115,13 +3159,29 @@ async function signWarrant(input) {
|
|
|
3115
3159
|
authorAccount,
|
|
3116
3160
|
publicKey,
|
|
3117
3161
|
executor,
|
|
3162
|
+
appVersion,
|
|
3163
|
+
u32le(method.length),
|
|
3164
|
+
method,
|
|
3118
3165
|
commitment,
|
|
3166
|
+
u32le(accountHeads.length),
|
|
3167
|
+
...accountHeads,
|
|
3168
|
+
u32le(governanceFloor.length),
|
|
3169
|
+
...governanceFloor,
|
|
3119
3170
|
nonce,
|
|
3120
3171
|
notAfter,
|
|
3121
3172
|
signature
|
|
3122
3173
|
)
|
|
3123
3174
|
);
|
|
3124
3175
|
}
|
|
3176
|
+
function citedHeads(heads, label) {
|
|
3177
|
+
const list = heads ?? [];
|
|
3178
|
+
if (list.length > MAX_CITED_HEADS) {
|
|
3179
|
+
throw new Error(
|
|
3180
|
+
`${label} cites ${list.length} heads, over the ${MAX_CITED_HEADS} a node accepts`
|
|
3181
|
+
);
|
|
3182
|
+
}
|
|
3183
|
+
return list.map((head, i) => fromHex(head, `${label}[${i}]`, 32));
|
|
3184
|
+
}
|
|
3125
3185
|
|
|
3126
3186
|
// src/relay/relay-client.ts
|
|
3127
3187
|
var DEFAULT_TTL_SECONDS = 300;
|