@tinycloud/sdk-core 2.2.0-beta.1 → 2.2.0-beta.4
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.cjs +420 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +100 -1
- package/dist/index.d.ts +100 -1
- package/dist/index.js +404 -1
- package/dist/index.js.map +1 -1
- package/package.json +7 -1
package/dist/index.cjs
CHANGED
|
@@ -36,10 +36,13 @@ __export(index_exports, {
|
|
|
36
36
|
CapabilityKeyRegistry: () => CapabilityKeyRegistry,
|
|
37
37
|
CapabilityKeyRegistryErrorCodes: () => CapabilityKeyRegistryErrorCodes,
|
|
38
38
|
ClientSessionSchema: () => ClientSessionSchema,
|
|
39
|
+
CloudLocationResolutionError: () => CloudLocationResolutionError,
|
|
39
40
|
DEFAULT_DEFAULTS: () => DEFAULT_DEFAULTS,
|
|
40
41
|
DEFAULT_EXPIRY: () => DEFAULT_EXPIRY,
|
|
41
42
|
DEFAULT_MANIFEST_SPACE: () => DEFAULT_MANIFEST_SPACE,
|
|
42
43
|
DEFAULT_MANIFEST_VERSION: () => DEFAULT_MANIFEST_VERSION,
|
|
44
|
+
DEFAULT_TINYCLOUD_FALLBACK_HOST: () => DEFAULT_TINYCLOUD_FALLBACK_HOST,
|
|
45
|
+
DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL: () => DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL,
|
|
43
46
|
DataVaultService: () => import_sdk_services4.DataVaultService,
|
|
44
47
|
DatabaseHandle: () => import_sdk_services4.DatabaseHandle,
|
|
45
48
|
DelegationErrorCodes: () => DelegationErrorCodes,
|
|
@@ -51,6 +54,7 @@ __export(index_exports, {
|
|
|
51
54
|
ErrorCodes: () => import_sdk_services4.ErrorCodes,
|
|
52
55
|
HooksService: () => import_sdk_services4.HooksService,
|
|
53
56
|
KVService: () => import_sdk_services4.KVService,
|
|
57
|
+
LocationRecordValidationError: () => LocationRecordValidationError,
|
|
54
58
|
ManifestValidationError: () => ManifestValidationError,
|
|
55
59
|
PermissionNotInManifestError: () => PermissionNotInManifestError,
|
|
56
60
|
PrefixedKVService: () => import_sdk_services4.PrefixedKVService,
|
|
@@ -76,6 +80,7 @@ __export(index_exports, {
|
|
|
76
80
|
activateSessionWithHost: () => activateSessionWithHost,
|
|
77
81
|
applyPrefix: () => applyPrefix,
|
|
78
82
|
buildSpaceUri: () => buildSpaceUri,
|
|
83
|
+
canonicalLocationPayload: () => canonicalLocationPayload,
|
|
79
84
|
checkNodeInfo: () => checkNodeInfo,
|
|
80
85
|
composeManifestRequest: () => composeManifestRequest,
|
|
81
86
|
createCapabilityKeyRegistry: () => createCapabilityKeyRegistry,
|
|
@@ -87,24 +92,34 @@ __export(index_exports, {
|
|
|
87
92
|
defaultSpaceCreationHandler: () => defaultSpaceCreationHandler,
|
|
88
93
|
err: () => import_sdk_services4.err,
|
|
89
94
|
expandActionShortNames: () => expandActionShortNames,
|
|
95
|
+
fetchLocationRecord: () => fetchLocationRecord,
|
|
90
96
|
fetchPeerId: () => fetchPeerId,
|
|
97
|
+
httpUrlToMultiaddr: () => httpUrlToMultiaddr,
|
|
91
98
|
isCapabilitySubset: () => isCapabilitySubset,
|
|
92
99
|
loadManifest: () => loadManifest,
|
|
100
|
+
locationPayloadForRecord: () => locationPayloadForRecord,
|
|
93
101
|
makePublicSpaceId: () => makePublicSpaceId,
|
|
94
102
|
manifestAbilitiesUnion: () => manifestAbilitiesUnion,
|
|
103
|
+
multiaddrToHttpUrl: () => multiaddrToHttpUrl,
|
|
95
104
|
normalizeDefaults: () => normalizeDefaults,
|
|
96
105
|
ok: () => import_sdk_services4.ok,
|
|
97
106
|
parseExpiry: () => parseExpiry,
|
|
98
107
|
parseRecapCapabilities: () => parseRecapCapabilities,
|
|
99
108
|
parseSpaceUri: () => parseSpaceUri,
|
|
109
|
+
resolveCloudLocation: () => resolveCloudLocation,
|
|
100
110
|
resolveManifest: () => resolveManifest,
|
|
111
|
+
resolveTinyCloudHosts: () => resolveTinyCloudHosts,
|
|
101
112
|
resourceCapabilitiesToAbilitiesMap: () => resourceCapabilitiesToAbilitiesMap,
|
|
102
113
|
resourceCapabilitiesToSpaceAbilitiesMap: () => resourceCapabilitiesToSpaceAbilitiesMap,
|
|
103
114
|
serviceError: () => import_sdk_services4.serviceError,
|
|
115
|
+
signLocationRecord: () => signLocationRecord,
|
|
104
116
|
submitHostDelegation: () => submitHostDelegation,
|
|
105
117
|
validateClientSession: () => validateClientSession,
|
|
118
|
+
validateLocationRecord: () => validateLocationRecord,
|
|
119
|
+
validateLocationRecordPayload: () => validateLocationRecordPayload,
|
|
106
120
|
validateManifest: () => validateManifest,
|
|
107
|
-
validatePersistedSessionData: () => validatePersistedSessionData
|
|
121
|
+
validatePersistedSessionData: () => validatePersistedSessionData,
|
|
122
|
+
verifyLocationRecord: () => verifyLocationRecord
|
|
108
123
|
});
|
|
109
124
|
module.exports = __toCommonJS(index_exports);
|
|
110
125
|
|
|
@@ -4330,6 +4345,394 @@ async function checkNodeInfo(host, sdkProtocol, fetchFn = globalThis.fetch.bind(
|
|
|
4330
4345
|
};
|
|
4331
4346
|
}
|
|
4332
4347
|
|
|
4348
|
+
// src/location.ts
|
|
4349
|
+
var import_multiaddr = require("@multiformats/multiaddr");
|
|
4350
|
+
var import_multiaddr_to_uri = require("@multiformats/multiaddr-to-uri");
|
|
4351
|
+
var import_uri_to_multiaddr = require("@multiformats/uri-to-multiaddr");
|
|
4352
|
+
var import_ed25519 = require("@noble/curves/ed25519");
|
|
4353
|
+
var import_basics = require("multiformats/basics");
|
|
4354
|
+
var import_viem = require("viem");
|
|
4355
|
+
var DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL = "https://registry.tinycloud.xyz";
|
|
4356
|
+
var DEFAULT_TINYCLOUD_FALLBACK_HOST = "https://node.tinycloud.xyz";
|
|
4357
|
+
var LocationRecordValidationError = class extends Error {
|
|
4358
|
+
constructor(message) {
|
|
4359
|
+
super(`Location record validation failed: ${message}`);
|
|
4360
|
+
this.name = "LocationRecordValidationError";
|
|
4361
|
+
}
|
|
4362
|
+
};
|
|
4363
|
+
var CloudLocationResolutionError = class extends Error {
|
|
4364
|
+
constructor(subject, attempts) {
|
|
4365
|
+
super(`Unable to resolve TinyCloud location for ${subject}`);
|
|
4366
|
+
this.name = "CloudLocationResolutionError";
|
|
4367
|
+
this.attempts = attempts;
|
|
4368
|
+
}
|
|
4369
|
+
};
|
|
4370
|
+
function locationPayloadForRecord(record) {
|
|
4371
|
+
return {
|
|
4372
|
+
version: record.version,
|
|
4373
|
+
subject: record.subject,
|
|
4374
|
+
multiaddrs: [...record.multiaddrs],
|
|
4375
|
+
updated_at: record.updated_at,
|
|
4376
|
+
sequence: record.sequence
|
|
4377
|
+
};
|
|
4378
|
+
}
|
|
4379
|
+
function canonicalLocationPayload(payload) {
|
|
4380
|
+
return JSON.stringify({
|
|
4381
|
+
version: payload.version,
|
|
4382
|
+
subject: payload.subject,
|
|
4383
|
+
multiaddrs: payload.multiaddrs,
|
|
4384
|
+
updated_at: payload.updated_at,
|
|
4385
|
+
sequence: payload.sequence
|
|
4386
|
+
});
|
|
4387
|
+
}
|
|
4388
|
+
async function signLocationRecord(payload, signer) {
|
|
4389
|
+
validateLocationRecordPayload(payload);
|
|
4390
|
+
const message = canonicalLocationPayload(payload);
|
|
4391
|
+
const signature = signer.type === "did:pkh" ? await signer.signMessage(message) : base64UrlEncode2(
|
|
4392
|
+
await signer.signBytes(new TextEncoder().encode(message))
|
|
4393
|
+
);
|
|
4394
|
+
return { ...payload, signature };
|
|
4395
|
+
}
|
|
4396
|
+
function validateLocationRecordPayload(input) {
|
|
4397
|
+
if (input === null || typeof input !== "object") {
|
|
4398
|
+
throw new LocationRecordValidationError("payload must be an object");
|
|
4399
|
+
}
|
|
4400
|
+
const payload = input;
|
|
4401
|
+
if (payload.version !== 1) {
|
|
4402
|
+
throw new LocationRecordValidationError("version must be 1");
|
|
4403
|
+
}
|
|
4404
|
+
validateSubject(payload.subject);
|
|
4405
|
+
validateMultiaddrs(payload.multiaddrs);
|
|
4406
|
+
if (typeof payload.updated_at !== "string" || Number.isNaN(Date.parse(payload.updated_at))) {
|
|
4407
|
+
throw new LocationRecordValidationError(
|
|
4408
|
+
"updated_at must be an ISO timestamp"
|
|
4409
|
+
);
|
|
4410
|
+
}
|
|
4411
|
+
if (typeof payload.sequence !== "number" || !Number.isSafeInteger(payload.sequence) || payload.sequence < 0) {
|
|
4412
|
+
throw new LocationRecordValidationError(
|
|
4413
|
+
"sequence must be a non-negative safe integer"
|
|
4414
|
+
);
|
|
4415
|
+
}
|
|
4416
|
+
return {
|
|
4417
|
+
version: 1,
|
|
4418
|
+
subject: payload.subject,
|
|
4419
|
+
multiaddrs: [...payload.multiaddrs],
|
|
4420
|
+
updated_at: payload.updated_at,
|
|
4421
|
+
sequence: payload.sequence
|
|
4422
|
+
};
|
|
4423
|
+
}
|
|
4424
|
+
function validateLocationRecord(input) {
|
|
4425
|
+
const payload = validateLocationRecordPayload(input);
|
|
4426
|
+
const signature = input.signature;
|
|
4427
|
+
if (typeof signature !== "string" || signature.length === 0) {
|
|
4428
|
+
throw new LocationRecordValidationError(
|
|
4429
|
+
"signature must be a non-empty string"
|
|
4430
|
+
);
|
|
4431
|
+
}
|
|
4432
|
+
return { ...payload, signature };
|
|
4433
|
+
}
|
|
4434
|
+
async function verifyLocationRecord(input) {
|
|
4435
|
+
const record = validateLocationRecord(input);
|
|
4436
|
+
const payload = canonicalLocationPayload(locationPayloadForRecord(record));
|
|
4437
|
+
if (record.subject.startsWith("did:pkh:")) {
|
|
4438
|
+
return verifyPkhSignature(record.subject, payload, record.signature);
|
|
4439
|
+
}
|
|
4440
|
+
if (record.subject.startsWith("did:key:")) {
|
|
4441
|
+
return verifyDidKeySignature(record.subject, payload, record.signature);
|
|
4442
|
+
}
|
|
4443
|
+
return false;
|
|
4444
|
+
}
|
|
4445
|
+
async function fetchLocationRecord(registryUrl, subject, fetchFn = globalThis.fetch) {
|
|
4446
|
+
const url = `${registryUrl.replace(/\/$/, "")}/v1/locations/${encodeURIComponent(subject)}`;
|
|
4447
|
+
const response = await fetchFn(url);
|
|
4448
|
+
if (response.status === 404) {
|
|
4449
|
+
return null;
|
|
4450
|
+
}
|
|
4451
|
+
if (!response.ok) {
|
|
4452
|
+
throw new Error(`location registry returned HTTP ${response.status}`);
|
|
4453
|
+
}
|
|
4454
|
+
const body = await response.json();
|
|
4455
|
+
if (body.record === void 0) {
|
|
4456
|
+
throw new LocationRecordValidationError("registry response missing record");
|
|
4457
|
+
}
|
|
4458
|
+
return validateLocationRecord(body.record);
|
|
4459
|
+
}
|
|
4460
|
+
async function resolveCloudLocation(subject, options = {}) {
|
|
4461
|
+
validateSubject(subject);
|
|
4462
|
+
const verifyRecords = options.verifyRecords ?? true;
|
|
4463
|
+
const attempts = await Promise.all([
|
|
4464
|
+
resolveExplicit(subject, options.explicitMultiaddrs),
|
|
4465
|
+
resolveBlockchain(subject, options.blockchain, verifyRecords),
|
|
4466
|
+
resolveCentralized(subject, options, verifyRecords),
|
|
4467
|
+
resolveFallback(subject, options.fallbackMultiaddrs)
|
|
4468
|
+
]);
|
|
4469
|
+
const winner = attempts.find((attempt) => attempt.candidate)?.candidate;
|
|
4470
|
+
if (!winner) {
|
|
4471
|
+
throw new CloudLocationResolutionError(subject, attempts);
|
|
4472
|
+
}
|
|
4473
|
+
return {
|
|
4474
|
+
subject,
|
|
4475
|
+
source: winner.source,
|
|
4476
|
+
multiaddrs: [...winner.multiaddrs],
|
|
4477
|
+
...winner.record ? { record: winner.record } : {},
|
|
4478
|
+
attempts,
|
|
4479
|
+
resolvedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4480
|
+
};
|
|
4481
|
+
}
|
|
4482
|
+
async function resolveTinyCloudHosts(subject, options = {}) {
|
|
4483
|
+
const location = await resolveCloudLocation(subject, {
|
|
4484
|
+
explicitMultiaddrs: hostsToMultiaddrs(options.explicitHosts),
|
|
4485
|
+
blockchain: options.blockchain,
|
|
4486
|
+
centralizedRegistryUrl: options.registryUrl === null ? void 0 : options.registryUrl ?? DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL,
|
|
4487
|
+
fallbackMultiaddrs: hostsToMultiaddrs(
|
|
4488
|
+
options.fallbackHosts === null ? void 0 : options.fallbackHosts ?? [DEFAULT_TINYCLOUD_FALLBACK_HOST]
|
|
4489
|
+
),
|
|
4490
|
+
fetch: options.fetch,
|
|
4491
|
+
verifyRecords: options.verifyRecords
|
|
4492
|
+
});
|
|
4493
|
+
return {
|
|
4494
|
+
hosts: location.multiaddrs.map((addr) => multiaddrToHttpUrl(addr)),
|
|
4495
|
+
location
|
|
4496
|
+
};
|
|
4497
|
+
}
|
|
4498
|
+
function multiaddrToHttpUrl(input) {
|
|
4499
|
+
const uri = (0, import_multiaddr_to_uri.multiaddrToUri)((0, import_multiaddr.multiaddr)(input));
|
|
4500
|
+
if (!uri.startsWith("http://") && !uri.startsWith("https://")) {
|
|
4501
|
+
throw new LocationRecordValidationError(
|
|
4502
|
+
`multiaddr does not resolve to http/https: ${input}`
|
|
4503
|
+
);
|
|
4504
|
+
}
|
|
4505
|
+
return uri;
|
|
4506
|
+
}
|
|
4507
|
+
function httpUrlToMultiaddr(input) {
|
|
4508
|
+
const url = new URL(input);
|
|
4509
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
4510
|
+
throw new LocationRecordValidationError("URL must use http or https");
|
|
4511
|
+
}
|
|
4512
|
+
return (0, import_uri_to_multiaddr.uriToMultiaddr)(url.toString()).toString();
|
|
4513
|
+
}
|
|
4514
|
+
function hostsToMultiaddrs(hosts) {
|
|
4515
|
+
if (hosts === void 0 || hosts.length === 0) {
|
|
4516
|
+
return void 0;
|
|
4517
|
+
}
|
|
4518
|
+
return hosts.map(
|
|
4519
|
+
(host) => host.startsWith("/") ? host : httpUrlToMultiaddr(host)
|
|
4520
|
+
);
|
|
4521
|
+
}
|
|
4522
|
+
async function resolveExplicit(subject, multiaddrs) {
|
|
4523
|
+
return resolveAttempt("explicit", async () => {
|
|
4524
|
+
if (multiaddrs === void 0 || multiaddrs.length === 0) {
|
|
4525
|
+
return null;
|
|
4526
|
+
}
|
|
4527
|
+
return toCandidate(subject, "explicit", multiaddrs, false);
|
|
4528
|
+
});
|
|
4529
|
+
}
|
|
4530
|
+
async function resolveBlockchain(subject, resolver, verifyRecords) {
|
|
4531
|
+
return resolveAttempt("blockchain", async () => {
|
|
4532
|
+
if (!resolver) {
|
|
4533
|
+
return null;
|
|
4534
|
+
}
|
|
4535
|
+
return toCandidate(
|
|
4536
|
+
subject,
|
|
4537
|
+
"blockchain",
|
|
4538
|
+
await resolver(subject),
|
|
4539
|
+
verifyRecords
|
|
4540
|
+
);
|
|
4541
|
+
});
|
|
4542
|
+
}
|
|
4543
|
+
async function resolveCentralized(subject, options, verifyRecords) {
|
|
4544
|
+
return resolveAttempt("centralized", async () => {
|
|
4545
|
+
if (!options.centralizedRegistryUrl) {
|
|
4546
|
+
return null;
|
|
4547
|
+
}
|
|
4548
|
+
const record = await fetchLocationRecord(
|
|
4549
|
+
options.centralizedRegistryUrl,
|
|
4550
|
+
subject,
|
|
4551
|
+
options.fetch
|
|
4552
|
+
);
|
|
4553
|
+
return toCandidate(subject, "centralized", record, verifyRecords);
|
|
4554
|
+
});
|
|
4555
|
+
}
|
|
4556
|
+
async function resolveFallback(subject, multiaddrs) {
|
|
4557
|
+
return resolveAttempt("fallback", async () => {
|
|
4558
|
+
if (multiaddrs === void 0 || multiaddrs.length === 0) {
|
|
4559
|
+
return null;
|
|
4560
|
+
}
|
|
4561
|
+
return toCandidate(subject, "fallback", multiaddrs, false);
|
|
4562
|
+
});
|
|
4563
|
+
}
|
|
4564
|
+
async function resolveAttempt(source, resolve) {
|
|
4565
|
+
try {
|
|
4566
|
+
const candidate = await resolve();
|
|
4567
|
+
return candidate ? { source, candidate } : { source };
|
|
4568
|
+
} catch (error) {
|
|
4569
|
+
return {
|
|
4570
|
+
source,
|
|
4571
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
4572
|
+
};
|
|
4573
|
+
}
|
|
4574
|
+
}
|
|
4575
|
+
async function toCandidate(subject, source, input, verifyRecord) {
|
|
4576
|
+
if (input === null || input === void 0) {
|
|
4577
|
+
return null;
|
|
4578
|
+
}
|
|
4579
|
+
if (Array.isArray(input)) {
|
|
4580
|
+
validateMultiaddrs(input);
|
|
4581
|
+
return { source, multiaddrs: [...input] };
|
|
4582
|
+
}
|
|
4583
|
+
const maybeRecord = input;
|
|
4584
|
+
if (maybeRecord.version === 1 && maybeRecord.signature !== void 0) {
|
|
4585
|
+
const record = validateLocationRecord(input);
|
|
4586
|
+
if (record.subject !== subject) {
|
|
4587
|
+
throw new LocationRecordValidationError(
|
|
4588
|
+
"location record subject does not match requested subject"
|
|
4589
|
+
);
|
|
4590
|
+
}
|
|
4591
|
+
if (verifyRecord && !await verifyLocationRecord(record)) {
|
|
4592
|
+
throw new LocationRecordValidationError(
|
|
4593
|
+
"location record signature is invalid"
|
|
4594
|
+
);
|
|
4595
|
+
}
|
|
4596
|
+
return { source, multiaddrs: [...record.multiaddrs], record };
|
|
4597
|
+
}
|
|
4598
|
+
const candidateInput = input;
|
|
4599
|
+
if (!Array.isArray(candidateInput.multiaddrs)) {
|
|
4600
|
+
throw new LocationRecordValidationError(
|
|
4601
|
+
"candidate multiaddrs must be an array"
|
|
4602
|
+
);
|
|
4603
|
+
}
|
|
4604
|
+
validateMultiaddrs(candidateInput.multiaddrs);
|
|
4605
|
+
if (candidateInput.record !== void 0) {
|
|
4606
|
+
const record = validateLocationRecord(candidateInput.record);
|
|
4607
|
+
if (record.subject !== subject) {
|
|
4608
|
+
throw new LocationRecordValidationError(
|
|
4609
|
+
"location record subject does not match requested subject"
|
|
4610
|
+
);
|
|
4611
|
+
}
|
|
4612
|
+
if (verifyRecord && !await verifyLocationRecord(record)) {
|
|
4613
|
+
throw new LocationRecordValidationError(
|
|
4614
|
+
"location record signature is invalid"
|
|
4615
|
+
);
|
|
4616
|
+
}
|
|
4617
|
+
return { source, multiaddrs: [...candidateInput.multiaddrs], record };
|
|
4618
|
+
}
|
|
4619
|
+
return { source, multiaddrs: [...candidateInput.multiaddrs] };
|
|
4620
|
+
}
|
|
4621
|
+
function validateSubject(subject) {
|
|
4622
|
+
if (typeof subject !== "string" || subject.length === 0) {
|
|
4623
|
+
throw new LocationRecordValidationError(
|
|
4624
|
+
"subject must be a non-empty string"
|
|
4625
|
+
);
|
|
4626
|
+
}
|
|
4627
|
+
if (!subject.startsWith("did:pkh:") && !subject.startsWith("did:key:")) {
|
|
4628
|
+
throw new LocationRecordValidationError(
|
|
4629
|
+
"subject must be did:pkh or did:key"
|
|
4630
|
+
);
|
|
4631
|
+
}
|
|
4632
|
+
}
|
|
4633
|
+
function validateMultiaddrs(input) {
|
|
4634
|
+
if (!Array.isArray(input)) {
|
|
4635
|
+
throw new LocationRecordValidationError("multiaddrs must be an array");
|
|
4636
|
+
}
|
|
4637
|
+
for (const addr of input) {
|
|
4638
|
+
if (typeof addr !== "string" || addr.length === 0) {
|
|
4639
|
+
throw new LocationRecordValidationError(
|
|
4640
|
+
"multiaddr entries must be non-empty strings"
|
|
4641
|
+
);
|
|
4642
|
+
}
|
|
4643
|
+
try {
|
|
4644
|
+
(0, import_multiaddr.multiaddr)(addr);
|
|
4645
|
+
} catch {
|
|
4646
|
+
throw new LocationRecordValidationError(`invalid multiaddr: ${addr}`);
|
|
4647
|
+
}
|
|
4648
|
+
}
|
|
4649
|
+
}
|
|
4650
|
+
async function verifyPkhSignature(did, payload, signature) {
|
|
4651
|
+
const address = did.split(":").at(-1);
|
|
4652
|
+
if (!address || !/^0x[a-fA-F0-9]{40}$/.test(address)) {
|
|
4653
|
+
throw new LocationRecordValidationError(
|
|
4654
|
+
"did:pkh subject must end with an EVM address"
|
|
4655
|
+
);
|
|
4656
|
+
}
|
|
4657
|
+
if (!/^0x[0-9a-fA-F]+$/.test(signature)) {
|
|
4658
|
+
throw new LocationRecordValidationError("did:pkh signature must be hex");
|
|
4659
|
+
}
|
|
4660
|
+
return (0, import_viem.verifyMessage)({
|
|
4661
|
+
address,
|
|
4662
|
+
message: payload,
|
|
4663
|
+
signature
|
|
4664
|
+
});
|
|
4665
|
+
}
|
|
4666
|
+
function verifyDidKeySignature(did, payload, signature) {
|
|
4667
|
+
const publicKey = ed25519PublicKeyFromDidKey(did);
|
|
4668
|
+
const signatureBytes = decodeBase64Url(signature);
|
|
4669
|
+
if (signatureBytes.length !== 64) {
|
|
4670
|
+
throw new LocationRecordValidationError(
|
|
4671
|
+
"did:key signature must be a base64url Ed25519 signature"
|
|
4672
|
+
);
|
|
4673
|
+
}
|
|
4674
|
+
return import_ed25519.ed25519.verify(
|
|
4675
|
+
signatureBytes,
|
|
4676
|
+
new TextEncoder().encode(payload),
|
|
4677
|
+
publicKey
|
|
4678
|
+
);
|
|
4679
|
+
}
|
|
4680
|
+
function ed25519PublicKeyFromDidKey(did) {
|
|
4681
|
+
const identifier = did.slice("did:key:".length);
|
|
4682
|
+
if (!identifier.startsWith("z")) {
|
|
4683
|
+
throw new LocationRecordValidationError(
|
|
4684
|
+
"did:key must use base58btc multibase"
|
|
4685
|
+
);
|
|
4686
|
+
}
|
|
4687
|
+
const bytes = import_basics.bases.base58btc.decode(identifier);
|
|
4688
|
+
if (bytes.length !== 34 || bytes[0] !== 237 || bytes[1] !== 1) {
|
|
4689
|
+
throw new LocationRecordValidationError(
|
|
4690
|
+
"did:key must be an Ed25519 public key"
|
|
4691
|
+
);
|
|
4692
|
+
}
|
|
4693
|
+
return bytes.slice(2);
|
|
4694
|
+
}
|
|
4695
|
+
function base64UrlEncode2(bytes) {
|
|
4696
|
+
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
4697
|
+
let output = "";
|
|
4698
|
+
for (let i = 0; i < bytes.length; i += 3) {
|
|
4699
|
+
const a = bytes[i];
|
|
4700
|
+
const b = bytes[i + 1];
|
|
4701
|
+
const c = bytes[i + 2];
|
|
4702
|
+
const triplet = a << 16 | (b ?? 0) << 8 | (c ?? 0);
|
|
4703
|
+
output += alphabet[triplet >> 18 & 63];
|
|
4704
|
+
output += alphabet[triplet >> 12 & 63];
|
|
4705
|
+
if (i + 1 < bytes.length) {
|
|
4706
|
+
output += alphabet[triplet >> 6 & 63];
|
|
4707
|
+
}
|
|
4708
|
+
if (i + 2 < bytes.length) {
|
|
4709
|
+
output += alphabet[triplet & 63];
|
|
4710
|
+
}
|
|
4711
|
+
}
|
|
4712
|
+
return output;
|
|
4713
|
+
}
|
|
4714
|
+
function decodeBase64Url(value) {
|
|
4715
|
+
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
4716
|
+
const bytes = [];
|
|
4717
|
+
let buffer = 0;
|
|
4718
|
+
let bits = 0;
|
|
4719
|
+
for (const char of value) {
|
|
4720
|
+
const index = alphabet.indexOf(char);
|
|
4721
|
+
if (index < 0) {
|
|
4722
|
+
throw new LocationRecordValidationError(
|
|
4723
|
+
"did:key signature must be base64url"
|
|
4724
|
+
);
|
|
4725
|
+
}
|
|
4726
|
+
buffer = buffer << 6 | index;
|
|
4727
|
+
bits += 6;
|
|
4728
|
+
if (bits >= 8) {
|
|
4729
|
+
bits -= 8;
|
|
4730
|
+
bytes.push(buffer >> bits & 255);
|
|
4731
|
+
}
|
|
4732
|
+
}
|
|
4733
|
+
return Uint8Array.from(bytes);
|
|
4734
|
+
}
|
|
4735
|
+
|
|
4333
4736
|
// src/capabilities.ts
|
|
4334
4737
|
var PermissionNotInManifestError = class extends Error {
|
|
4335
4738
|
constructor(missing, granted) {
|
|
@@ -4451,10 +4854,13 @@ function parseRecapCapabilities(parseWasm, siwe) {
|
|
|
4451
4854
|
CapabilityKeyRegistry,
|
|
4452
4855
|
CapabilityKeyRegistryErrorCodes,
|
|
4453
4856
|
ClientSessionSchema,
|
|
4857
|
+
CloudLocationResolutionError,
|
|
4454
4858
|
DEFAULT_DEFAULTS,
|
|
4455
4859
|
DEFAULT_EXPIRY,
|
|
4456
4860
|
DEFAULT_MANIFEST_SPACE,
|
|
4457
4861
|
DEFAULT_MANIFEST_VERSION,
|
|
4862
|
+
DEFAULT_TINYCLOUD_FALLBACK_HOST,
|
|
4863
|
+
DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL,
|
|
4458
4864
|
DataVaultService,
|
|
4459
4865
|
DatabaseHandle,
|
|
4460
4866
|
DelegationErrorCodes,
|
|
@@ -4466,6 +4872,7 @@ function parseRecapCapabilities(parseWasm, siwe) {
|
|
|
4466
4872
|
ErrorCodes,
|
|
4467
4873
|
HooksService,
|
|
4468
4874
|
KVService,
|
|
4875
|
+
LocationRecordValidationError,
|
|
4469
4876
|
ManifestValidationError,
|
|
4470
4877
|
PermissionNotInManifestError,
|
|
4471
4878
|
PrefixedKVService,
|
|
@@ -4491,6 +4898,7 @@ function parseRecapCapabilities(parseWasm, siwe) {
|
|
|
4491
4898
|
activateSessionWithHost,
|
|
4492
4899
|
applyPrefix,
|
|
4493
4900
|
buildSpaceUri,
|
|
4901
|
+
canonicalLocationPayload,
|
|
4494
4902
|
checkNodeInfo,
|
|
4495
4903
|
composeManifestRequest,
|
|
4496
4904
|
createCapabilityKeyRegistry,
|
|
@@ -4502,23 +4910,33 @@ function parseRecapCapabilities(parseWasm, siwe) {
|
|
|
4502
4910
|
defaultSpaceCreationHandler,
|
|
4503
4911
|
err,
|
|
4504
4912
|
expandActionShortNames,
|
|
4913
|
+
fetchLocationRecord,
|
|
4505
4914
|
fetchPeerId,
|
|
4915
|
+
httpUrlToMultiaddr,
|
|
4506
4916
|
isCapabilitySubset,
|
|
4507
4917
|
loadManifest,
|
|
4918
|
+
locationPayloadForRecord,
|
|
4508
4919
|
makePublicSpaceId,
|
|
4509
4920
|
manifestAbilitiesUnion,
|
|
4921
|
+
multiaddrToHttpUrl,
|
|
4510
4922
|
normalizeDefaults,
|
|
4511
4923
|
ok,
|
|
4512
4924
|
parseExpiry,
|
|
4513
4925
|
parseRecapCapabilities,
|
|
4514
4926
|
parseSpaceUri,
|
|
4927
|
+
resolveCloudLocation,
|
|
4515
4928
|
resolveManifest,
|
|
4929
|
+
resolveTinyCloudHosts,
|
|
4516
4930
|
resourceCapabilitiesToAbilitiesMap,
|
|
4517
4931
|
resourceCapabilitiesToSpaceAbilitiesMap,
|
|
4518
4932
|
serviceError,
|
|
4933
|
+
signLocationRecord,
|
|
4519
4934
|
submitHostDelegation,
|
|
4520
4935
|
validateClientSession,
|
|
4936
|
+
validateLocationRecord,
|
|
4937
|
+
validateLocationRecordPayload,
|
|
4521
4938
|
validateManifest,
|
|
4522
|
-
validatePersistedSessionData
|
|
4939
|
+
validatePersistedSessionData,
|
|
4940
|
+
verifyLocationRecord
|
|
4523
4941
|
});
|
|
4524
4942
|
//# sourceMappingURL=index.cjs.map
|