@le-space/ui 0.6.4 → 0.6.6
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/package.json +4 -4
- package/react/index.d.ts +1 -0
- package/react/index.js +181 -41
- package/shared/index.d.ts +2 -1
- package/shared/index.js +180 -41
- package/svelte/SponsorRelayFab.svelte +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@le-space/ui",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.6",
|
|
4
4
|
"description": "Floating Aleph sponsor relay UI components for Svelte and React.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -44,9 +44,9 @@
|
|
|
44
44
|
"url": "https://github.com/NiKrause/relay-button/issues"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@le-space/browser": "0.6.
|
|
48
|
-
"@le-space/core": "0.6.
|
|
49
|
-
"viem": "^2.
|
|
47
|
+
"@le-space/browser": "0.6.6",
|
|
48
|
+
"@le-space/core": "0.6.6",
|
|
49
|
+
"viem": "^2.53.1"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
52
|
"react": ">=18",
|
package/react/index.d.ts
CHANGED
package/react/index.js
CHANGED
|
@@ -43,7 +43,7 @@ var RECENT_INSTANCE_RUNTIME_GRACE_MS = 10 * 60 * 1e3;
|
|
|
43
43
|
var DEPLOYMENT_PENDING_WARNING_MS = 3 * 60 * 1e3;
|
|
44
44
|
|
|
45
45
|
// src/shared/package-version.ts
|
|
46
|
-
var UI_PACKAGE_VERSION = "0.6.
|
|
46
|
+
var UI_PACKAGE_VERSION = "0.6.6";
|
|
47
47
|
|
|
48
48
|
// src/shared/format.ts
|
|
49
49
|
function shortHash(value, head = 8, tail = 6) {
|
|
@@ -135,7 +135,12 @@ async function fetchWithTimeout(input, init = {}, timeoutMs = 15e3) {
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
// ../browser/src/aleph-api.ts
|
|
138
|
-
var
|
|
138
|
+
var DEFAULT_ALEPH_API_HOSTS = [
|
|
139
|
+
"https://api3.aleph.im",
|
|
140
|
+
"https://api2.aleph.im",
|
|
141
|
+
"https://api.aleph.im"
|
|
142
|
+
];
|
|
143
|
+
var DEFAULT_ALEPH_API_HOST = DEFAULT_ALEPH_API_HOSTS[0] ?? "https://api3.aleph.im";
|
|
139
144
|
var DEFAULT_CRN_LIST_URL = "https://crns-list.aleph.sh/crns.json";
|
|
140
145
|
var DEFAULT_ALEPH_SCHEDULER_API_HOST = "https://scheduler.api.aleph.cloud";
|
|
141
146
|
var DEFAULT_2N6_API_HOST = "https://api.2n6.me";
|
|
@@ -805,29 +810,56 @@ function watchWallet(onChange, provider = getEthereumProvider()) {
|
|
|
805
810
|
}
|
|
806
811
|
|
|
807
812
|
// ../browser/src/client.ts
|
|
813
|
+
function normalizeApiHost(value) {
|
|
814
|
+
const trimmed = value.trim().replace(/\/+$/u, "");
|
|
815
|
+
return trimmed ? trimmed : null;
|
|
816
|
+
}
|
|
817
|
+
function normalizeApiHosts(input, fallbackApiHost) {
|
|
818
|
+
const rawValues = Array.isArray(input) ? input : typeof input === "string" ? input.split(/[\s,]+/u) : [];
|
|
819
|
+
const hosts = rawValues.map((value) => normalizeApiHost(String(value))).filter((value) => Boolean(value));
|
|
820
|
+
if (hosts.length > 0) return Array.from(new Set(hosts));
|
|
821
|
+
const fallback = normalizeApiHost(fallbackApiHost);
|
|
822
|
+
return fallback ? [fallback] : [...DEFAULT_ALEPH_API_HOSTS];
|
|
823
|
+
}
|
|
824
|
+
async function withApiHostFallback(apiHosts, run) {
|
|
825
|
+
let lastError = null;
|
|
826
|
+
for (let index = 0; index < apiHosts.length; index += 1) {
|
|
827
|
+
const apiHost = apiHosts[index];
|
|
828
|
+
try {
|
|
829
|
+
return await run(apiHost);
|
|
830
|
+
} catch (error) {
|
|
831
|
+
lastError = error;
|
|
832
|
+
if (index >= apiHosts.length - 1) break;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
if (lastError instanceof Error) throw lastError;
|
|
836
|
+
throw new Error(String(lastError));
|
|
837
|
+
}
|
|
808
838
|
function createAlephBrowserClient(options = {}) {
|
|
809
|
-
const
|
|
839
|
+
const apiHosts = options.apiHosts === void 0 && options.apiHost === void 0 ? [...DEFAULT_ALEPH_API_HOSTS] : normalizeApiHosts(options.apiHosts, options.apiHost ?? DEFAULT_ALEPH_API_HOST);
|
|
840
|
+
const apiHost = apiHosts[0] ?? DEFAULT_ALEPH_API_HOST;
|
|
810
841
|
const crnListUrl = options.crnListUrl ?? DEFAULT_CRN_LIST_URL;
|
|
811
842
|
const schedulerApiHost = options.schedulerApiHost ?? DEFAULT_ALEPH_SCHEDULER_API_HOST;
|
|
812
843
|
const twoN6ApiHost = options.twoN6ApiHost ?? DEFAULT_2N6_API_HOST;
|
|
813
844
|
return {
|
|
814
845
|
apiHost,
|
|
846
|
+
apiHosts,
|
|
815
847
|
crnListUrl,
|
|
816
848
|
schedulerApiHost,
|
|
817
849
|
fetchBalance(address) {
|
|
818
|
-
return fetchBalance(address,
|
|
850
|
+
return withApiHostFallback(apiHosts, (host) => fetchBalance(address, host));
|
|
819
851
|
},
|
|
820
852
|
fetchCrns() {
|
|
821
853
|
return fetchCrns(crnListUrl);
|
|
822
854
|
},
|
|
823
855
|
fetchInstances(address) {
|
|
824
|
-
return fetchInstances(address,
|
|
856
|
+
return withApiHostFallback(apiHosts, (host) => fetchInstances(address, host));
|
|
825
857
|
},
|
|
826
858
|
fetch2n6WebAccessUrl(itemHash) {
|
|
827
859
|
return fetch2n6WebAccessUrl(itemHash, twoN6ApiHost);
|
|
828
860
|
},
|
|
829
861
|
fetchMessageEnvelope(itemHash) {
|
|
830
|
-
return fetchMessageEnvelope(itemHash,
|
|
862
|
+
return withApiHostFallback(apiHosts, (host) => fetchMessageEnvelope(itemHash, host));
|
|
831
863
|
},
|
|
832
864
|
fetchSchedulerAllocation(itemHash) {
|
|
833
865
|
return fetchSchedulerAllocation(itemHash, schedulerApiHost);
|
|
@@ -842,16 +874,16 @@ function createAlephBrowserClient(options = {}) {
|
|
|
842
874
|
return configureOrbitdbRelaySetup(args);
|
|
843
875
|
},
|
|
844
876
|
inspectDeploymentResult(itemHash, rootfsRef) {
|
|
845
|
-
return inspectDeploymentResult(itemHash, rootfsRef,
|
|
877
|
+
return withApiHostFallback(apiHosts, (host) => inspectDeploymentResult(itemHash, rootfsRef, host));
|
|
846
878
|
},
|
|
847
879
|
waitForDeploymentResult(itemHash, rootfsRef, attempts, delayMs) {
|
|
848
|
-
return waitForDeploymentResult(itemHash, rootfsRef,
|
|
880
|
+
return withApiHostFallback(apiHosts, (host) => waitForDeploymentResult(itemHash, rootfsRef, host, attempts, delayMs));
|
|
849
881
|
},
|
|
850
882
|
broadcastInstanceMessage(message, sync) {
|
|
851
|
-
return broadcastInstanceMessage(message,
|
|
883
|
+
return withApiHostFallback(apiHosts, (host) => broadcastInstanceMessage(message, host, sync));
|
|
852
884
|
},
|
|
853
885
|
broadcastAlephMessage(message, sync) {
|
|
854
|
-
return broadcastAlephMessage(message,
|
|
886
|
+
return withApiHostFallback(apiHosts, (host) => broadcastAlephMessage(message, host, sync));
|
|
855
887
|
}
|
|
856
888
|
};
|
|
857
889
|
}
|
|
@@ -2333,9 +2365,11 @@ async function configureUcanStore(args) {
|
|
|
2333
2365
|
proxy_url: args.proxyUrl ?? void 0,
|
|
2334
2366
|
service_did: args.serviceDid ?? void 0,
|
|
2335
2367
|
service_origin: args.serviceOrigin ?? void 0,
|
|
2368
|
+
public_storage_origin: args.publicStorageOrigin ?? void 0,
|
|
2336
2369
|
webauthn_origin: args.webauthnOrigin ?? void 0,
|
|
2337
2370
|
webauthn_origin_fallbacks: args.webauthnOriginFallbacks ?? void 0,
|
|
2338
2371
|
admin_did: args.adminDid ?? void 0,
|
|
2372
|
+
admin_api_token: args.adminApiToken ?? void 0,
|
|
2339
2373
|
bootstrap_package: args.bootstrapPackage ?? void 0,
|
|
2340
2374
|
no_start: args.noStart === true ? true : void 0
|
|
2341
2375
|
};
|
|
@@ -2434,13 +2468,15 @@ async function fetchUcGoPeerMetadata(args) {
|
|
|
2434
2468
|
}
|
|
2435
2469
|
|
|
2436
2470
|
// ../aleph-bootstrap/src/index.ts
|
|
2437
|
-
import { recoverMessageAddress } from "viem";
|
|
2471
|
+
import { keccak256, recoverMessageAddress, stringToHex } from "viem";
|
|
2438
2472
|
var DEFAULT_ALEPH_API_HOST3 = "https://api.aleph.im";
|
|
2439
2473
|
var DEFAULT_ALEPH_BOOTSTRAP_CHANNEL = "simple-todo";
|
|
2440
2474
|
var DEFAULT_ALEPH_BOOTSTRAP_REF = "simple-todo-bootstrap";
|
|
2441
2475
|
var DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE = "relay-bootstrap";
|
|
2476
|
+
var DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE = "relay-bootstrap-v2";
|
|
2442
2477
|
var DEFAULT_BOOTSTRAP_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
2443
2478
|
var DEFAULT_BOOTSTRAP_PAGINATION = 50;
|
|
2479
|
+
var DEFAULT_BOOTSTRAP_COMPACT_MULTIADDR_LIMIT = 3;
|
|
2444
2480
|
var RELAY_BOOTSTRAP_SIGNATURE_SCHEME = "personal_sign";
|
|
2445
2481
|
function serializeOwnerAuthorizationPayload(payload) {
|
|
2446
2482
|
return JSON.stringify({
|
|
@@ -2458,14 +2494,61 @@ function serializeOwnerAuthorizationPayload(payload) {
|
|
|
2458
2494
|
function serializeRelayProofPayload(payload) {
|
|
2459
2495
|
return JSON.stringify({
|
|
2460
2496
|
peerId: payload.peerId,
|
|
2461
|
-
multiaddrs: dedupeMultiaddrs(payload.multiaddrs),
|
|
2497
|
+
multiaddrs: payload.multiaddrs ? dedupeMultiaddrs(payload.multiaddrs) : void 0,
|
|
2462
2498
|
browserMultiaddrs: payload.browserMultiaddrs ? dedupeMultiaddrs(payload.browserMultiaddrs) : void 0,
|
|
2499
|
+
multiaddrsHash: payload.multiaddrsHash,
|
|
2500
|
+
browserMultiaddrsHash: payload.browserMultiaddrsHash,
|
|
2463
2501
|
registrationId: payload.registrationId,
|
|
2464
2502
|
profile: payload.profile,
|
|
2465
2503
|
version: payload.version,
|
|
2466
2504
|
updatedAt: payload.updatedAt
|
|
2467
2505
|
});
|
|
2468
2506
|
}
|
|
2507
|
+
function relayBootstrapMultiaddrsHash(addrs) {
|
|
2508
|
+
return keccak256(stringToHex(JSON.stringify(dedupeMultiaddrs(addrs))));
|
|
2509
|
+
}
|
|
2510
|
+
function compactPostType(postType) {
|
|
2511
|
+
return (postType ?? DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE) === DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
|
|
2512
|
+
}
|
|
2513
|
+
function browserMultiaddrPreference(addr) {
|
|
2514
|
+
const normalized = addr.toLowerCase();
|
|
2515
|
+
if (normalized.includes("/tcp/443/tls/ws/")) return 0;
|
|
2516
|
+
if (normalized.includes("/tls/ws/")) return 1;
|
|
2517
|
+
if (normalized.includes("/webtransport/")) return 2;
|
|
2518
|
+
if (normalized.includes("/webrtc-direct/")) return 3;
|
|
2519
|
+
if (normalized.includes("/ws")) return 4;
|
|
2520
|
+
return 5;
|
|
2521
|
+
}
|
|
2522
|
+
function browserMultiaddrTransport(addr) {
|
|
2523
|
+
const normalized = addr.toLowerCase();
|
|
2524
|
+
if (normalized.includes("/webtransport/")) return "webtransport";
|
|
2525
|
+
if (normalized.includes("/webrtc-direct/")) return "webrtc";
|
|
2526
|
+
if (normalized.includes("/ws") || normalized.includes("/wss")) return "websocket";
|
|
2527
|
+
return "other";
|
|
2528
|
+
}
|
|
2529
|
+
function selectCompactRelayBootstrapMultiaddrs(addrs, limit = DEFAULT_BOOTSTRAP_COMPACT_MULTIADDR_LIMIT) {
|
|
2530
|
+
const entries = filterPublicMultiaddrs(addrs, {
|
|
2531
|
+
browserDialableOnly: true
|
|
2532
|
+
}).map((addr, index) => ({
|
|
2533
|
+
addr,
|
|
2534
|
+
index,
|
|
2535
|
+
transport: browserMultiaddrTransport(addr)
|
|
2536
|
+
}));
|
|
2537
|
+
entries.sort((left, right) => {
|
|
2538
|
+
const preference = browserMultiaddrPreference(left.addr) - browserMultiaddrPreference(right.addr);
|
|
2539
|
+
return preference !== 0 ? preference : left.index - right.index;
|
|
2540
|
+
});
|
|
2541
|
+
const perTransportLimit = Math.max(1, Math.floor(limit));
|
|
2542
|
+
const selectedByTransport = /* @__PURE__ */ new Map();
|
|
2543
|
+
const result = [];
|
|
2544
|
+
for (const entry of entries) {
|
|
2545
|
+
const selected = selectedByTransport.get(entry.transport) ?? 0;
|
|
2546
|
+
if (selected >= perTransportLimit) continue;
|
|
2547
|
+
selectedByTransport.set(entry.transport, selected + 1);
|
|
2548
|
+
result.push(entry.addr);
|
|
2549
|
+
}
|
|
2550
|
+
return result;
|
|
2551
|
+
}
|
|
2469
2552
|
function asTrimmedString(value) {
|
|
2470
2553
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
2471
2554
|
}
|
|
@@ -2621,8 +2704,10 @@ function normalizeRelayBootstrapProofPayload(value) {
|
|
|
2621
2704
|
const browserMultiaddrs = Array.isArray(payload.browserMultiaddrs) ? payload.browserMultiaddrs.filter((entry) => typeof entry === "string") : void 0;
|
|
2622
2705
|
return {
|
|
2623
2706
|
peerId,
|
|
2624
|
-
multiaddrs: dedupeMultiaddrs(multiaddrs),
|
|
2707
|
+
multiaddrs: multiaddrs.length > 0 ? dedupeMultiaddrs(multiaddrs) : void 0,
|
|
2625
2708
|
browserMultiaddrs: browserMultiaddrs ? dedupeMultiaddrs(browserMultiaddrs) : void 0,
|
|
2709
|
+
multiaddrsHash: asTrimmedString(payload.multiaddrsHash) ?? void 0,
|
|
2710
|
+
browserMultiaddrsHash: asTrimmedString(payload.browserMultiaddrsHash) ?? void 0,
|
|
2626
2711
|
registrationId: asTrimmedString(payload.registrationId) ?? void 0,
|
|
2627
2712
|
profile: asTrimmedString(payload.profile) ?? void 0,
|
|
2628
2713
|
version: asTrimmedString(payload.version) ?? void 0,
|
|
@@ -2654,16 +2739,24 @@ function normalizeRelayBootstrapPostRecord(value) {
|
|
|
2654
2739
|
function buildRelayBootstrapPostContent(args) {
|
|
2655
2740
|
const now = args.now ?? Date.now() / 1e3;
|
|
2656
2741
|
const updatedAt = args.now ?? Date.now();
|
|
2742
|
+
const postType = args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE;
|
|
2743
|
+
const compact = args.compact ?? compactPostType(postType);
|
|
2744
|
+
const fullMultiaddrs = filterPublicMultiaddrs(args.multiaddrs);
|
|
2745
|
+
const fullBrowserMultiaddrs = args.browserMultiaddrs ? filterPublicMultiaddrs(args.browserMultiaddrs, {
|
|
2746
|
+
browserDialableOnly: true
|
|
2747
|
+
}) : void 0;
|
|
2748
|
+
const compactMultiaddrs = selectCompactRelayBootstrapMultiaddrs(
|
|
2749
|
+
fullBrowserMultiaddrs && fullBrowserMultiaddrs.length > 0 ? fullBrowserMultiaddrs : fullMultiaddrs,
|
|
2750
|
+
args.compactMultiaddrLimit
|
|
2751
|
+
);
|
|
2657
2752
|
return {
|
|
2658
|
-
type:
|
|
2753
|
+
type: postType,
|
|
2659
2754
|
address: args.sender,
|
|
2660
2755
|
...args.ref ? { ref: args.ref } : {},
|
|
2661
2756
|
content: {
|
|
2662
2757
|
peerId: args.peerId,
|
|
2663
|
-
multiaddrs:
|
|
2664
|
-
browserMultiaddrs:
|
|
2665
|
-
browserDialableOnly: true
|
|
2666
|
-
}) : void 0,
|
|
2758
|
+
multiaddrs: compact ? compactMultiaddrs : fullMultiaddrs,
|
|
2759
|
+
browserMultiaddrs: compact ? void 0 : fullBrowserMultiaddrs,
|
|
2667
2760
|
registrationId: args.registrationId,
|
|
2668
2761
|
profile: args.profile,
|
|
2669
2762
|
version: args.version,
|
|
@@ -2693,6 +2786,8 @@ async function createRelayBootstrapPost(args) {
|
|
|
2693
2786
|
publisherAddress: args.publisherAddress,
|
|
2694
2787
|
authorization: args.authorization,
|
|
2695
2788
|
relayProof: args.relayProof,
|
|
2789
|
+
compact: args.compact,
|
|
2790
|
+
compactMultiaddrLimit: args.compactMultiaddrLimit,
|
|
2696
2791
|
now: nowMillis
|
|
2697
2792
|
});
|
|
2698
2793
|
itemContent.time = nowSeconds;
|
|
@@ -2730,12 +2825,20 @@ async function signRelayBootstrapAuthorization(args) {
|
|
|
2730
2825
|
};
|
|
2731
2826
|
}
|
|
2732
2827
|
async function signRelayBootstrapProof(args) {
|
|
2828
|
+
const fullMultiaddrs = filterPublicMultiaddrs(args.multiaddrs);
|
|
2829
|
+
const fullBrowserMultiaddrs = args.browserMultiaddrs ? filterPublicMultiaddrs(args.browserMultiaddrs, {
|
|
2830
|
+
browserDialableOnly: true
|
|
2831
|
+
}) : void 0;
|
|
2832
|
+
const compactMultiaddrs = selectCompactRelayBootstrapMultiaddrs(
|
|
2833
|
+
fullBrowserMultiaddrs && fullBrowserMultiaddrs.length > 0 ? fullBrowserMultiaddrs : fullMultiaddrs,
|
|
2834
|
+
args.compactMultiaddrLimit
|
|
2835
|
+
);
|
|
2836
|
+
const compact = args.compact ?? false;
|
|
2733
2837
|
const payload = {
|
|
2734
2838
|
peerId: args.peerId,
|
|
2735
|
-
multiaddrs:
|
|
2736
|
-
browserMultiaddrs:
|
|
2737
|
-
|
|
2738
|
-
}) : void 0,
|
|
2839
|
+
multiaddrs: compact ? void 0 : fullMultiaddrs,
|
|
2840
|
+
browserMultiaddrs: compact ? void 0 : fullBrowserMultiaddrs,
|
|
2841
|
+
multiaddrsHash: compact ? relayBootstrapMultiaddrsHash(compactMultiaddrs) : void 0,
|
|
2739
2842
|
registrationId: args.registrationId,
|
|
2740
2843
|
profile: args.profile,
|
|
2741
2844
|
version: args.version,
|
|
@@ -2782,7 +2885,7 @@ async function fetchAlephBootstrapPosts(options = {}) {
|
|
|
2782
2885
|
throw new Error(`Aleph bootstrap post lookup failed: ${response.status}`);
|
|
2783
2886
|
}
|
|
2784
2887
|
const payload = await response.json();
|
|
2785
|
-
return (payload.posts ?? []).map((entry) => normalizeRelayBootstrapPostRecord(entry)).filter((entry) => entry != null);
|
|
2888
|
+
return (payload.posts ?? []).map((entry) => normalizeRelayBootstrapPostRecord(entry)).filter((entry) => entry != null).sort((left, right) => compareRelayBootstrapPostRecency(right, left));
|
|
2786
2889
|
}
|
|
2787
2890
|
function compareRelayBootstrapPostRecency(left, right) {
|
|
2788
2891
|
const leftUpdatedAt = left.content?.updatedAt ?? 0;
|
|
@@ -2829,12 +2932,14 @@ async function waitForRelayBootstrapRegistration(args) {
|
|
|
2829
2932
|
const expectedSender = args.sender?.trim().toLowerCase() || null;
|
|
2830
2933
|
const expectedRegistrationId = args.registrationId?.trim() || null;
|
|
2831
2934
|
const expectedPeerId = args.peerId?.trim() || null;
|
|
2935
|
+
const postType = args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
|
|
2936
|
+
const sleepImpl = args.sleep ?? sleep;
|
|
2832
2937
|
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
2833
2938
|
const posts = await fetchAlephBootstrapPosts({
|
|
2834
2939
|
apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
|
|
2835
2940
|
channel: args.channel,
|
|
2836
2941
|
ref: args.ref,
|
|
2837
|
-
postType
|
|
2942
|
+
postType,
|
|
2838
2943
|
fetch: args.fetch
|
|
2839
2944
|
});
|
|
2840
2945
|
const currentPosts = selectCurrentRelayBootstrapPosts(posts);
|
|
@@ -2865,7 +2970,7 @@ async function waitForRelayBootstrapRegistration(args) {
|
|
|
2865
2970
|
}
|
|
2866
2971
|
args.onAttempt?.(null, attempt + 1, attempts);
|
|
2867
2972
|
if (attempt < attempts - 1) {
|
|
2868
|
-
await
|
|
2973
|
+
await sleepImpl(delayMs);
|
|
2869
2974
|
}
|
|
2870
2975
|
}
|
|
2871
2976
|
return null;
|
|
@@ -2873,6 +2978,8 @@ async function waitForRelayBootstrapRegistration(args) {
|
|
|
2873
2978
|
async function publishRelayBootstrapRegistration(args) {
|
|
2874
2979
|
const publisherAddress = args.publisherAddress ?? args.sender;
|
|
2875
2980
|
const ownerAddress = args.ownerAddress;
|
|
2981
|
+
const postType = args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
|
|
2982
|
+
const compact = postType === DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
|
|
2876
2983
|
let ownerAuthorization = args.ownerAuthorization;
|
|
2877
2984
|
let relayProof = args.relayProof;
|
|
2878
2985
|
if (!ownerAuthorization && ownerAddress && args.ownerSigner) {
|
|
@@ -2899,6 +3006,8 @@ async function publishRelayBootstrapRegistration(args) {
|
|
|
2899
3006
|
profile: args.profile,
|
|
2900
3007
|
version: args.version,
|
|
2901
3008
|
updatedAt: args.now ?? Date.now(),
|
|
3009
|
+
compact,
|
|
3010
|
+
compactMultiaddrLimit: args.compactMultiaddrLimit,
|
|
2902
3011
|
signer: args.publisherSigner
|
|
2903
3012
|
});
|
|
2904
3013
|
}
|
|
@@ -2910,13 +3019,15 @@ async function publishRelayBootstrapRegistration(args) {
|
|
|
2910
3019
|
registrationId: args.registrationId,
|
|
2911
3020
|
channel: args.channel,
|
|
2912
3021
|
ref: args.ref,
|
|
2913
|
-
postType
|
|
3022
|
+
postType,
|
|
2914
3023
|
profile: args.profile,
|
|
2915
3024
|
version: args.version,
|
|
2916
3025
|
ownerAddress,
|
|
2917
3026
|
publisherAddress,
|
|
2918
3027
|
authorization: ownerAuthorization,
|
|
2919
3028
|
relayProof,
|
|
3029
|
+
compact,
|
|
3030
|
+
compactMultiaddrLimit: args.compactMultiaddrLimit,
|
|
2920
3031
|
now: args.now,
|
|
2921
3032
|
hasher: args.hasher
|
|
2922
3033
|
});
|
|
@@ -2938,16 +3049,33 @@ async function publishRelayBootstrapRegistration(args) {
|
|
|
2938
3049
|
let forgottenHashes = [];
|
|
2939
3050
|
let forgetResult;
|
|
2940
3051
|
if (args.forgetPrevious && args.registrationId) {
|
|
2941
|
-
const
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
3052
|
+
const previousPostTypes = compact ? [postType, DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE] : [postType];
|
|
3053
|
+
const previousPosts = (await Promise.all(
|
|
3054
|
+
previousPostTypes.map(
|
|
3055
|
+
(previousPostType) => fetchAlephBootstrapPosts({
|
|
3056
|
+
apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
|
|
3057
|
+
channel: args.channel,
|
|
3058
|
+
ref: args.ref,
|
|
3059
|
+
postType: previousPostType,
|
|
3060
|
+
fetch: args.fetch
|
|
3061
|
+
})
|
|
3062
|
+
)
|
|
3063
|
+
)).flat();
|
|
3064
|
+
const forgottenHashSet = new Set(
|
|
3065
|
+
previousPosts.filter((post) => {
|
|
3066
|
+
const hash = post.itemHash ?? post.hash;
|
|
3067
|
+
if (!hash || hash === unsigned.item_hash) return false;
|
|
3068
|
+
if (post.address?.toLowerCase() !== args.sender.toLowerCase()) {
|
|
3069
|
+
return false;
|
|
3070
|
+
}
|
|
3071
|
+
const content2 = post.content;
|
|
3072
|
+
if (!content2) return false;
|
|
3073
|
+
if (content2.registrationId === args.registrationId) return true;
|
|
3074
|
+
if (content2.peerId !== args.peerId) return false;
|
|
3075
|
+
return !args.profile || content2.profile === args.profile;
|
|
3076
|
+
}).map((post) => post.itemHash ?? post.hash ?? "").filter(Boolean)
|
|
3077
|
+
);
|
|
3078
|
+
forgottenHashes = [...forgottenHashSet];
|
|
2951
3079
|
if (forgottenHashes.length > 0) {
|
|
2952
3080
|
forgetResult = await forgetAlephMessages({
|
|
2953
3081
|
sender: args.sender,
|
|
@@ -2968,7 +3096,7 @@ async function publishRelayBootstrapRegistration(args) {
|
|
|
2968
3096
|
response,
|
|
2969
3097
|
httpStatus,
|
|
2970
3098
|
publishedMultiaddrs: content.content?.multiaddrs ?? [],
|
|
2971
|
-
publishedBrowserMultiaddrs: content.content?.browserMultiaddrs ?? [],
|
|
3099
|
+
publishedBrowserMultiaddrs: content.content?.browserMultiaddrs ?? content.content?.multiaddrs ?? [],
|
|
2972
3100
|
forgottenHashes,
|
|
2973
3101
|
forgetResult
|
|
2974
3102
|
};
|
|
@@ -3966,6 +4094,7 @@ var SponsorRelayController = class {
|
|
|
3966
4094
|
this.debugEnabled = isDebugEnabled(props);
|
|
3967
4095
|
this.client = createAlephBrowserClient({
|
|
3968
4096
|
apiHost: props.apiHost,
|
|
4097
|
+
apiHosts: props.apiHosts,
|
|
3969
4098
|
crnListUrl: props.crnListUrl,
|
|
3970
4099
|
schedulerApiHost: props.schedulerApiHost,
|
|
3971
4100
|
twoN6ApiHost: props.twoN6ApiHost
|
|
@@ -4118,6 +4247,8 @@ var SponsorRelayController = class {
|
|
|
4118
4247
|
setupPort,
|
|
4119
4248
|
proxyUrl: serviceProxyUrl,
|
|
4120
4249
|
webauthnOrigin: serviceProxyUrl,
|
|
4250
|
+
serviceDid: bootstrapValidation.bootstrapPackage.serviceDid,
|
|
4251
|
+
serviceOrigin: bootstrapValidation.bootstrapPackage.serviceOrigin,
|
|
4121
4252
|
adminDid: bootstrapValidation.bootstrapPackage.adminDid,
|
|
4122
4253
|
bootstrapPackage: bootstrapValidation.bootstrapPackage,
|
|
4123
4254
|
fetch: (url, init) => fetch(url, init),
|
|
@@ -5020,10 +5151,18 @@ var SponsorRelayController = class {
|
|
|
5020
5151
|
const [nextBalance, rawInstances, rawBootstrapPosts] = await Promise.all([
|
|
5021
5152
|
this.client.fetchBalance(this.state.wallet.address),
|
|
5022
5153
|
this.state.showInstances ? this.client.fetchInstances(this.state.wallet.address) : Promise.resolve([]),
|
|
5023
|
-
bootstrapEnabled ?
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5154
|
+
bootstrapEnabled ? Promise.all(
|
|
5155
|
+
[
|
|
5156
|
+
DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE,
|
|
5157
|
+
DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE
|
|
5158
|
+
].map(
|
|
5159
|
+
(postType) => fetchAlephBootstrapPosts({
|
|
5160
|
+
apiHost: this.client.apiHost,
|
|
5161
|
+
postType,
|
|
5162
|
+
fetch
|
|
5163
|
+
}).catch(() => [])
|
|
5164
|
+
)
|
|
5165
|
+
).then((pages) => pages.flat()) : Promise.resolve([])
|
|
5027
5166
|
]);
|
|
5028
5167
|
balance = nextBalance;
|
|
5029
5168
|
instances = await Promise.all(
|
|
@@ -5896,6 +6035,7 @@ function useSponsorRelayController(props) {
|
|
|
5896
6035
|
() => createSponsorRelayController(props),
|
|
5897
6036
|
[
|
|
5898
6037
|
props.apiHost,
|
|
6038
|
+
props.apiHosts,
|
|
5899
6039
|
props.crnListUrl,
|
|
5900
6040
|
props.debug,
|
|
5901
6041
|
props.instanceName,
|
package/shared/index.d.ts
CHANGED
|
@@ -209,6 +209,7 @@ interface SponsorRelayProps {
|
|
|
209
209
|
launcherMode?: 'floating' | 'inline';
|
|
210
210
|
version?: string;
|
|
211
211
|
apiHost?: string;
|
|
212
|
+
apiHosts?: string | readonly string[];
|
|
212
213
|
crnListUrl?: string;
|
|
213
214
|
schedulerApiHost?: string;
|
|
214
215
|
twoN6ApiHost?: string;
|
|
@@ -330,7 +331,7 @@ declare const STALE_INSTANCE_ALLOCATION_COOLDOWN_MS: number;
|
|
|
330
331
|
declare const RECENT_INSTANCE_RUNTIME_GRACE_MS: number;
|
|
331
332
|
declare const DEPLOYMENT_PENDING_WARNING_MS: number;
|
|
332
333
|
|
|
333
|
-
declare const UI_PACKAGE_VERSION = "0.6.
|
|
334
|
+
declare const UI_PACKAGE_VERSION = "0.6.6";
|
|
334
335
|
|
|
335
336
|
interface RootfsRequiredPortForward {
|
|
336
337
|
port: number;
|
package/shared/index.js
CHANGED
|
@@ -42,7 +42,7 @@ var RECENT_INSTANCE_RUNTIME_GRACE_MS = 10 * 60 * 1e3;
|
|
|
42
42
|
var DEPLOYMENT_PENDING_WARNING_MS = 3 * 60 * 1e3;
|
|
43
43
|
|
|
44
44
|
// src/shared/package-version.ts
|
|
45
|
-
var UI_PACKAGE_VERSION = "0.6.
|
|
45
|
+
var UI_PACKAGE_VERSION = "0.6.6";
|
|
46
46
|
|
|
47
47
|
// src/shared/format.ts
|
|
48
48
|
function shortHash(value, head = 8, tail = 6) {
|
|
@@ -134,7 +134,12 @@ async function fetchWithTimeout(input, init = {}, timeoutMs = 15e3) {
|
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
// ../browser/src/aleph-api.ts
|
|
137
|
-
var
|
|
137
|
+
var DEFAULT_ALEPH_API_HOSTS = [
|
|
138
|
+
"https://api3.aleph.im",
|
|
139
|
+
"https://api2.aleph.im",
|
|
140
|
+
"https://api.aleph.im"
|
|
141
|
+
];
|
|
142
|
+
var DEFAULT_ALEPH_API_HOST = DEFAULT_ALEPH_API_HOSTS[0] ?? "https://api3.aleph.im";
|
|
138
143
|
var DEFAULT_CRN_LIST_URL = "https://crns-list.aleph.sh/crns.json";
|
|
139
144
|
var DEFAULT_ALEPH_SCHEDULER_API_HOST = "https://scheduler.api.aleph.cloud";
|
|
140
145
|
var DEFAULT_2N6_API_HOST = "https://api.2n6.me";
|
|
@@ -804,29 +809,56 @@ function watchWallet(onChange, provider = getEthereumProvider()) {
|
|
|
804
809
|
}
|
|
805
810
|
|
|
806
811
|
// ../browser/src/client.ts
|
|
812
|
+
function normalizeApiHost(value) {
|
|
813
|
+
const trimmed = value.trim().replace(/\/+$/u, "");
|
|
814
|
+
return trimmed ? trimmed : null;
|
|
815
|
+
}
|
|
816
|
+
function normalizeApiHosts(input, fallbackApiHost) {
|
|
817
|
+
const rawValues = Array.isArray(input) ? input : typeof input === "string" ? input.split(/[\s,]+/u) : [];
|
|
818
|
+
const hosts = rawValues.map((value) => normalizeApiHost(String(value))).filter((value) => Boolean(value));
|
|
819
|
+
if (hosts.length > 0) return Array.from(new Set(hosts));
|
|
820
|
+
const fallback = normalizeApiHost(fallbackApiHost);
|
|
821
|
+
return fallback ? [fallback] : [...DEFAULT_ALEPH_API_HOSTS];
|
|
822
|
+
}
|
|
823
|
+
async function withApiHostFallback(apiHosts, run) {
|
|
824
|
+
let lastError = null;
|
|
825
|
+
for (let index = 0; index < apiHosts.length; index += 1) {
|
|
826
|
+
const apiHost = apiHosts[index];
|
|
827
|
+
try {
|
|
828
|
+
return await run(apiHost);
|
|
829
|
+
} catch (error) {
|
|
830
|
+
lastError = error;
|
|
831
|
+
if (index >= apiHosts.length - 1) break;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
if (lastError instanceof Error) throw lastError;
|
|
835
|
+
throw new Error(String(lastError));
|
|
836
|
+
}
|
|
807
837
|
function createAlephBrowserClient(options = {}) {
|
|
808
|
-
const
|
|
838
|
+
const apiHosts = options.apiHosts === void 0 && options.apiHost === void 0 ? [...DEFAULT_ALEPH_API_HOSTS] : normalizeApiHosts(options.apiHosts, options.apiHost ?? DEFAULT_ALEPH_API_HOST);
|
|
839
|
+
const apiHost = apiHosts[0] ?? DEFAULT_ALEPH_API_HOST;
|
|
809
840
|
const crnListUrl = options.crnListUrl ?? DEFAULT_CRN_LIST_URL;
|
|
810
841
|
const schedulerApiHost = options.schedulerApiHost ?? DEFAULT_ALEPH_SCHEDULER_API_HOST;
|
|
811
842
|
const twoN6ApiHost = options.twoN6ApiHost ?? DEFAULT_2N6_API_HOST;
|
|
812
843
|
return {
|
|
813
844
|
apiHost,
|
|
845
|
+
apiHosts,
|
|
814
846
|
crnListUrl,
|
|
815
847
|
schedulerApiHost,
|
|
816
848
|
fetchBalance(address) {
|
|
817
|
-
return fetchBalance(address,
|
|
849
|
+
return withApiHostFallback(apiHosts, (host) => fetchBalance(address, host));
|
|
818
850
|
},
|
|
819
851
|
fetchCrns() {
|
|
820
852
|
return fetchCrns(crnListUrl);
|
|
821
853
|
},
|
|
822
854
|
fetchInstances(address) {
|
|
823
|
-
return fetchInstances(address,
|
|
855
|
+
return withApiHostFallback(apiHosts, (host) => fetchInstances(address, host));
|
|
824
856
|
},
|
|
825
857
|
fetch2n6WebAccessUrl(itemHash) {
|
|
826
858
|
return fetch2n6WebAccessUrl(itemHash, twoN6ApiHost);
|
|
827
859
|
},
|
|
828
860
|
fetchMessageEnvelope(itemHash) {
|
|
829
|
-
return fetchMessageEnvelope(itemHash,
|
|
861
|
+
return withApiHostFallback(apiHosts, (host) => fetchMessageEnvelope(itemHash, host));
|
|
830
862
|
},
|
|
831
863
|
fetchSchedulerAllocation(itemHash) {
|
|
832
864
|
return fetchSchedulerAllocation(itemHash, schedulerApiHost);
|
|
@@ -841,16 +873,16 @@ function createAlephBrowserClient(options = {}) {
|
|
|
841
873
|
return configureOrbitdbRelaySetup(args);
|
|
842
874
|
},
|
|
843
875
|
inspectDeploymentResult(itemHash, rootfsRef) {
|
|
844
|
-
return inspectDeploymentResult(itemHash, rootfsRef,
|
|
876
|
+
return withApiHostFallback(apiHosts, (host) => inspectDeploymentResult(itemHash, rootfsRef, host));
|
|
845
877
|
},
|
|
846
878
|
waitForDeploymentResult(itemHash, rootfsRef, attempts, delayMs) {
|
|
847
|
-
return waitForDeploymentResult(itemHash, rootfsRef,
|
|
879
|
+
return withApiHostFallback(apiHosts, (host) => waitForDeploymentResult(itemHash, rootfsRef, host, attempts, delayMs));
|
|
848
880
|
},
|
|
849
881
|
broadcastInstanceMessage(message, sync) {
|
|
850
|
-
return broadcastInstanceMessage(message,
|
|
882
|
+
return withApiHostFallback(apiHosts, (host) => broadcastInstanceMessage(message, host, sync));
|
|
851
883
|
},
|
|
852
884
|
broadcastAlephMessage(message, sync) {
|
|
853
|
-
return broadcastAlephMessage(message,
|
|
885
|
+
return withApiHostFallback(apiHosts, (host) => broadcastAlephMessage(message, host, sync));
|
|
854
886
|
}
|
|
855
887
|
};
|
|
856
888
|
}
|
|
@@ -2332,9 +2364,11 @@ async function configureUcanStore(args) {
|
|
|
2332
2364
|
proxy_url: args.proxyUrl ?? void 0,
|
|
2333
2365
|
service_did: args.serviceDid ?? void 0,
|
|
2334
2366
|
service_origin: args.serviceOrigin ?? void 0,
|
|
2367
|
+
public_storage_origin: args.publicStorageOrigin ?? void 0,
|
|
2335
2368
|
webauthn_origin: args.webauthnOrigin ?? void 0,
|
|
2336
2369
|
webauthn_origin_fallbacks: args.webauthnOriginFallbacks ?? void 0,
|
|
2337
2370
|
admin_did: args.adminDid ?? void 0,
|
|
2371
|
+
admin_api_token: args.adminApiToken ?? void 0,
|
|
2338
2372
|
bootstrap_package: args.bootstrapPackage ?? void 0,
|
|
2339
2373
|
no_start: args.noStart === true ? true : void 0
|
|
2340
2374
|
};
|
|
@@ -2433,13 +2467,15 @@ async function fetchUcGoPeerMetadata(args) {
|
|
|
2433
2467
|
}
|
|
2434
2468
|
|
|
2435
2469
|
// ../aleph-bootstrap/src/index.ts
|
|
2436
|
-
import { recoverMessageAddress } from "viem";
|
|
2470
|
+
import { keccak256, recoverMessageAddress, stringToHex } from "viem";
|
|
2437
2471
|
var DEFAULT_ALEPH_API_HOST3 = "https://api.aleph.im";
|
|
2438
2472
|
var DEFAULT_ALEPH_BOOTSTRAP_CHANNEL = "simple-todo";
|
|
2439
2473
|
var DEFAULT_ALEPH_BOOTSTRAP_REF = "simple-todo-bootstrap";
|
|
2440
2474
|
var DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE = "relay-bootstrap";
|
|
2475
|
+
var DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE = "relay-bootstrap-v2";
|
|
2441
2476
|
var DEFAULT_BOOTSTRAP_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
2442
2477
|
var DEFAULT_BOOTSTRAP_PAGINATION = 50;
|
|
2478
|
+
var DEFAULT_BOOTSTRAP_COMPACT_MULTIADDR_LIMIT = 3;
|
|
2443
2479
|
var RELAY_BOOTSTRAP_SIGNATURE_SCHEME = "personal_sign";
|
|
2444
2480
|
function serializeOwnerAuthorizationPayload(payload) {
|
|
2445
2481
|
return JSON.stringify({
|
|
@@ -2457,14 +2493,61 @@ function serializeOwnerAuthorizationPayload(payload) {
|
|
|
2457
2493
|
function serializeRelayProofPayload(payload) {
|
|
2458
2494
|
return JSON.stringify({
|
|
2459
2495
|
peerId: payload.peerId,
|
|
2460
|
-
multiaddrs: dedupeMultiaddrs(payload.multiaddrs),
|
|
2496
|
+
multiaddrs: payload.multiaddrs ? dedupeMultiaddrs(payload.multiaddrs) : void 0,
|
|
2461
2497
|
browserMultiaddrs: payload.browserMultiaddrs ? dedupeMultiaddrs(payload.browserMultiaddrs) : void 0,
|
|
2498
|
+
multiaddrsHash: payload.multiaddrsHash,
|
|
2499
|
+
browserMultiaddrsHash: payload.browserMultiaddrsHash,
|
|
2462
2500
|
registrationId: payload.registrationId,
|
|
2463
2501
|
profile: payload.profile,
|
|
2464
2502
|
version: payload.version,
|
|
2465
2503
|
updatedAt: payload.updatedAt
|
|
2466
2504
|
});
|
|
2467
2505
|
}
|
|
2506
|
+
function relayBootstrapMultiaddrsHash(addrs) {
|
|
2507
|
+
return keccak256(stringToHex(JSON.stringify(dedupeMultiaddrs(addrs))));
|
|
2508
|
+
}
|
|
2509
|
+
function compactPostType(postType) {
|
|
2510
|
+
return (postType ?? DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE) === DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
|
|
2511
|
+
}
|
|
2512
|
+
function browserMultiaddrPreference(addr) {
|
|
2513
|
+
const normalized = addr.toLowerCase();
|
|
2514
|
+
if (normalized.includes("/tcp/443/tls/ws/")) return 0;
|
|
2515
|
+
if (normalized.includes("/tls/ws/")) return 1;
|
|
2516
|
+
if (normalized.includes("/webtransport/")) return 2;
|
|
2517
|
+
if (normalized.includes("/webrtc-direct/")) return 3;
|
|
2518
|
+
if (normalized.includes("/ws")) return 4;
|
|
2519
|
+
return 5;
|
|
2520
|
+
}
|
|
2521
|
+
function browserMultiaddrTransport(addr) {
|
|
2522
|
+
const normalized = addr.toLowerCase();
|
|
2523
|
+
if (normalized.includes("/webtransport/")) return "webtransport";
|
|
2524
|
+
if (normalized.includes("/webrtc-direct/")) return "webrtc";
|
|
2525
|
+
if (normalized.includes("/ws") || normalized.includes("/wss")) return "websocket";
|
|
2526
|
+
return "other";
|
|
2527
|
+
}
|
|
2528
|
+
function selectCompactRelayBootstrapMultiaddrs(addrs, limit = DEFAULT_BOOTSTRAP_COMPACT_MULTIADDR_LIMIT) {
|
|
2529
|
+
const entries = filterPublicMultiaddrs(addrs, {
|
|
2530
|
+
browserDialableOnly: true
|
|
2531
|
+
}).map((addr, index) => ({
|
|
2532
|
+
addr,
|
|
2533
|
+
index,
|
|
2534
|
+
transport: browserMultiaddrTransport(addr)
|
|
2535
|
+
}));
|
|
2536
|
+
entries.sort((left, right) => {
|
|
2537
|
+
const preference = browserMultiaddrPreference(left.addr) - browserMultiaddrPreference(right.addr);
|
|
2538
|
+
return preference !== 0 ? preference : left.index - right.index;
|
|
2539
|
+
});
|
|
2540
|
+
const perTransportLimit = Math.max(1, Math.floor(limit));
|
|
2541
|
+
const selectedByTransport = /* @__PURE__ */ new Map();
|
|
2542
|
+
const result = [];
|
|
2543
|
+
for (const entry of entries) {
|
|
2544
|
+
const selected = selectedByTransport.get(entry.transport) ?? 0;
|
|
2545
|
+
if (selected >= perTransportLimit) continue;
|
|
2546
|
+
selectedByTransport.set(entry.transport, selected + 1);
|
|
2547
|
+
result.push(entry.addr);
|
|
2548
|
+
}
|
|
2549
|
+
return result;
|
|
2550
|
+
}
|
|
2468
2551
|
function asTrimmedString(value) {
|
|
2469
2552
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
2470
2553
|
}
|
|
@@ -2620,8 +2703,10 @@ function normalizeRelayBootstrapProofPayload(value) {
|
|
|
2620
2703
|
const browserMultiaddrs = Array.isArray(payload.browserMultiaddrs) ? payload.browserMultiaddrs.filter((entry) => typeof entry === "string") : void 0;
|
|
2621
2704
|
return {
|
|
2622
2705
|
peerId,
|
|
2623
|
-
multiaddrs: dedupeMultiaddrs(multiaddrs),
|
|
2706
|
+
multiaddrs: multiaddrs.length > 0 ? dedupeMultiaddrs(multiaddrs) : void 0,
|
|
2624
2707
|
browserMultiaddrs: browserMultiaddrs ? dedupeMultiaddrs(browserMultiaddrs) : void 0,
|
|
2708
|
+
multiaddrsHash: asTrimmedString(payload.multiaddrsHash) ?? void 0,
|
|
2709
|
+
browserMultiaddrsHash: asTrimmedString(payload.browserMultiaddrsHash) ?? void 0,
|
|
2625
2710
|
registrationId: asTrimmedString(payload.registrationId) ?? void 0,
|
|
2626
2711
|
profile: asTrimmedString(payload.profile) ?? void 0,
|
|
2627
2712
|
version: asTrimmedString(payload.version) ?? void 0,
|
|
@@ -2653,16 +2738,24 @@ function normalizeRelayBootstrapPostRecord(value) {
|
|
|
2653
2738
|
function buildRelayBootstrapPostContent(args) {
|
|
2654
2739
|
const now = args.now ?? Date.now() / 1e3;
|
|
2655
2740
|
const updatedAt = args.now ?? Date.now();
|
|
2741
|
+
const postType = args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE;
|
|
2742
|
+
const compact = args.compact ?? compactPostType(postType);
|
|
2743
|
+
const fullMultiaddrs = filterPublicMultiaddrs(args.multiaddrs);
|
|
2744
|
+
const fullBrowserMultiaddrs = args.browserMultiaddrs ? filterPublicMultiaddrs(args.browserMultiaddrs, {
|
|
2745
|
+
browserDialableOnly: true
|
|
2746
|
+
}) : void 0;
|
|
2747
|
+
const compactMultiaddrs = selectCompactRelayBootstrapMultiaddrs(
|
|
2748
|
+
fullBrowserMultiaddrs && fullBrowserMultiaddrs.length > 0 ? fullBrowserMultiaddrs : fullMultiaddrs,
|
|
2749
|
+
args.compactMultiaddrLimit
|
|
2750
|
+
);
|
|
2656
2751
|
return {
|
|
2657
|
-
type:
|
|
2752
|
+
type: postType,
|
|
2658
2753
|
address: args.sender,
|
|
2659
2754
|
...args.ref ? { ref: args.ref } : {},
|
|
2660
2755
|
content: {
|
|
2661
2756
|
peerId: args.peerId,
|
|
2662
|
-
multiaddrs:
|
|
2663
|
-
browserMultiaddrs:
|
|
2664
|
-
browserDialableOnly: true
|
|
2665
|
-
}) : void 0,
|
|
2757
|
+
multiaddrs: compact ? compactMultiaddrs : fullMultiaddrs,
|
|
2758
|
+
browserMultiaddrs: compact ? void 0 : fullBrowserMultiaddrs,
|
|
2666
2759
|
registrationId: args.registrationId,
|
|
2667
2760
|
profile: args.profile,
|
|
2668
2761
|
version: args.version,
|
|
@@ -2692,6 +2785,8 @@ async function createRelayBootstrapPost(args) {
|
|
|
2692
2785
|
publisherAddress: args.publisherAddress,
|
|
2693
2786
|
authorization: args.authorization,
|
|
2694
2787
|
relayProof: args.relayProof,
|
|
2788
|
+
compact: args.compact,
|
|
2789
|
+
compactMultiaddrLimit: args.compactMultiaddrLimit,
|
|
2695
2790
|
now: nowMillis
|
|
2696
2791
|
});
|
|
2697
2792
|
itemContent.time = nowSeconds;
|
|
@@ -2729,12 +2824,20 @@ async function signRelayBootstrapAuthorization(args) {
|
|
|
2729
2824
|
};
|
|
2730
2825
|
}
|
|
2731
2826
|
async function signRelayBootstrapProof(args) {
|
|
2827
|
+
const fullMultiaddrs = filterPublicMultiaddrs(args.multiaddrs);
|
|
2828
|
+
const fullBrowserMultiaddrs = args.browserMultiaddrs ? filterPublicMultiaddrs(args.browserMultiaddrs, {
|
|
2829
|
+
browserDialableOnly: true
|
|
2830
|
+
}) : void 0;
|
|
2831
|
+
const compactMultiaddrs = selectCompactRelayBootstrapMultiaddrs(
|
|
2832
|
+
fullBrowserMultiaddrs && fullBrowserMultiaddrs.length > 0 ? fullBrowserMultiaddrs : fullMultiaddrs,
|
|
2833
|
+
args.compactMultiaddrLimit
|
|
2834
|
+
);
|
|
2835
|
+
const compact = args.compact ?? false;
|
|
2732
2836
|
const payload = {
|
|
2733
2837
|
peerId: args.peerId,
|
|
2734
|
-
multiaddrs:
|
|
2735
|
-
browserMultiaddrs:
|
|
2736
|
-
|
|
2737
|
-
}) : void 0,
|
|
2838
|
+
multiaddrs: compact ? void 0 : fullMultiaddrs,
|
|
2839
|
+
browserMultiaddrs: compact ? void 0 : fullBrowserMultiaddrs,
|
|
2840
|
+
multiaddrsHash: compact ? relayBootstrapMultiaddrsHash(compactMultiaddrs) : void 0,
|
|
2738
2841
|
registrationId: args.registrationId,
|
|
2739
2842
|
profile: args.profile,
|
|
2740
2843
|
version: args.version,
|
|
@@ -2781,7 +2884,7 @@ async function fetchAlephBootstrapPosts(options = {}) {
|
|
|
2781
2884
|
throw new Error(`Aleph bootstrap post lookup failed: ${response.status}`);
|
|
2782
2885
|
}
|
|
2783
2886
|
const payload = await response.json();
|
|
2784
|
-
return (payload.posts ?? []).map((entry) => normalizeRelayBootstrapPostRecord(entry)).filter((entry) => entry != null);
|
|
2887
|
+
return (payload.posts ?? []).map((entry) => normalizeRelayBootstrapPostRecord(entry)).filter((entry) => entry != null).sort((left, right) => compareRelayBootstrapPostRecency(right, left));
|
|
2785
2888
|
}
|
|
2786
2889
|
function compareRelayBootstrapPostRecency(left, right) {
|
|
2787
2890
|
const leftUpdatedAt = left.content?.updatedAt ?? 0;
|
|
@@ -2828,12 +2931,14 @@ async function waitForRelayBootstrapRegistration(args) {
|
|
|
2828
2931
|
const expectedSender = args.sender?.trim().toLowerCase() || null;
|
|
2829
2932
|
const expectedRegistrationId = args.registrationId?.trim() || null;
|
|
2830
2933
|
const expectedPeerId = args.peerId?.trim() || null;
|
|
2934
|
+
const postType = args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
|
|
2935
|
+
const sleepImpl = args.sleep ?? sleep;
|
|
2831
2936
|
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
2832
2937
|
const posts = await fetchAlephBootstrapPosts({
|
|
2833
2938
|
apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
|
|
2834
2939
|
channel: args.channel,
|
|
2835
2940
|
ref: args.ref,
|
|
2836
|
-
postType
|
|
2941
|
+
postType,
|
|
2837
2942
|
fetch: args.fetch
|
|
2838
2943
|
});
|
|
2839
2944
|
const currentPosts = selectCurrentRelayBootstrapPosts(posts);
|
|
@@ -2864,7 +2969,7 @@ async function waitForRelayBootstrapRegistration(args) {
|
|
|
2864
2969
|
}
|
|
2865
2970
|
args.onAttempt?.(null, attempt + 1, attempts);
|
|
2866
2971
|
if (attempt < attempts - 1) {
|
|
2867
|
-
await
|
|
2972
|
+
await sleepImpl(delayMs);
|
|
2868
2973
|
}
|
|
2869
2974
|
}
|
|
2870
2975
|
return null;
|
|
@@ -2872,6 +2977,8 @@ async function waitForRelayBootstrapRegistration(args) {
|
|
|
2872
2977
|
async function publishRelayBootstrapRegistration(args) {
|
|
2873
2978
|
const publisherAddress = args.publisherAddress ?? args.sender;
|
|
2874
2979
|
const ownerAddress = args.ownerAddress;
|
|
2980
|
+
const postType = args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
|
|
2981
|
+
const compact = postType === DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
|
|
2875
2982
|
let ownerAuthorization = args.ownerAuthorization;
|
|
2876
2983
|
let relayProof = args.relayProof;
|
|
2877
2984
|
if (!ownerAuthorization && ownerAddress && args.ownerSigner) {
|
|
@@ -2898,6 +3005,8 @@ async function publishRelayBootstrapRegistration(args) {
|
|
|
2898
3005
|
profile: args.profile,
|
|
2899
3006
|
version: args.version,
|
|
2900
3007
|
updatedAt: args.now ?? Date.now(),
|
|
3008
|
+
compact,
|
|
3009
|
+
compactMultiaddrLimit: args.compactMultiaddrLimit,
|
|
2901
3010
|
signer: args.publisherSigner
|
|
2902
3011
|
});
|
|
2903
3012
|
}
|
|
@@ -2909,13 +3018,15 @@ async function publishRelayBootstrapRegistration(args) {
|
|
|
2909
3018
|
registrationId: args.registrationId,
|
|
2910
3019
|
channel: args.channel,
|
|
2911
3020
|
ref: args.ref,
|
|
2912
|
-
postType
|
|
3021
|
+
postType,
|
|
2913
3022
|
profile: args.profile,
|
|
2914
3023
|
version: args.version,
|
|
2915
3024
|
ownerAddress,
|
|
2916
3025
|
publisherAddress,
|
|
2917
3026
|
authorization: ownerAuthorization,
|
|
2918
3027
|
relayProof,
|
|
3028
|
+
compact,
|
|
3029
|
+
compactMultiaddrLimit: args.compactMultiaddrLimit,
|
|
2919
3030
|
now: args.now,
|
|
2920
3031
|
hasher: args.hasher
|
|
2921
3032
|
});
|
|
@@ -2937,16 +3048,33 @@ async function publishRelayBootstrapRegistration(args) {
|
|
|
2937
3048
|
let forgottenHashes = [];
|
|
2938
3049
|
let forgetResult;
|
|
2939
3050
|
if (args.forgetPrevious && args.registrationId) {
|
|
2940
|
-
const
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
3051
|
+
const previousPostTypes = compact ? [postType, DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE] : [postType];
|
|
3052
|
+
const previousPosts = (await Promise.all(
|
|
3053
|
+
previousPostTypes.map(
|
|
3054
|
+
(previousPostType) => fetchAlephBootstrapPosts({
|
|
3055
|
+
apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
|
|
3056
|
+
channel: args.channel,
|
|
3057
|
+
ref: args.ref,
|
|
3058
|
+
postType: previousPostType,
|
|
3059
|
+
fetch: args.fetch
|
|
3060
|
+
})
|
|
3061
|
+
)
|
|
3062
|
+
)).flat();
|
|
3063
|
+
const forgottenHashSet = new Set(
|
|
3064
|
+
previousPosts.filter((post) => {
|
|
3065
|
+
const hash = post.itemHash ?? post.hash;
|
|
3066
|
+
if (!hash || hash === unsigned.item_hash) return false;
|
|
3067
|
+
if (post.address?.toLowerCase() !== args.sender.toLowerCase()) {
|
|
3068
|
+
return false;
|
|
3069
|
+
}
|
|
3070
|
+
const content2 = post.content;
|
|
3071
|
+
if (!content2) return false;
|
|
3072
|
+
if (content2.registrationId === args.registrationId) return true;
|
|
3073
|
+
if (content2.peerId !== args.peerId) return false;
|
|
3074
|
+
return !args.profile || content2.profile === args.profile;
|
|
3075
|
+
}).map((post) => post.itemHash ?? post.hash ?? "").filter(Boolean)
|
|
3076
|
+
);
|
|
3077
|
+
forgottenHashes = [...forgottenHashSet];
|
|
2950
3078
|
if (forgottenHashes.length > 0) {
|
|
2951
3079
|
forgetResult = await forgetAlephMessages({
|
|
2952
3080
|
sender: args.sender,
|
|
@@ -2967,7 +3095,7 @@ async function publishRelayBootstrapRegistration(args) {
|
|
|
2967
3095
|
response,
|
|
2968
3096
|
httpStatus,
|
|
2969
3097
|
publishedMultiaddrs: content.content?.multiaddrs ?? [],
|
|
2970
|
-
publishedBrowserMultiaddrs: content.content?.browserMultiaddrs ?? [],
|
|
3098
|
+
publishedBrowserMultiaddrs: content.content?.browserMultiaddrs ?? content.content?.multiaddrs ?? [],
|
|
2971
3099
|
forgottenHashes,
|
|
2972
3100
|
forgetResult
|
|
2973
3101
|
};
|
|
@@ -3965,6 +4093,7 @@ var SponsorRelayController = class {
|
|
|
3965
4093
|
this.debugEnabled = isDebugEnabled(props);
|
|
3966
4094
|
this.client = createAlephBrowserClient({
|
|
3967
4095
|
apiHost: props.apiHost,
|
|
4096
|
+
apiHosts: props.apiHosts,
|
|
3968
4097
|
crnListUrl: props.crnListUrl,
|
|
3969
4098
|
schedulerApiHost: props.schedulerApiHost,
|
|
3970
4099
|
twoN6ApiHost: props.twoN6ApiHost
|
|
@@ -4117,6 +4246,8 @@ var SponsorRelayController = class {
|
|
|
4117
4246
|
setupPort,
|
|
4118
4247
|
proxyUrl: serviceProxyUrl,
|
|
4119
4248
|
webauthnOrigin: serviceProxyUrl,
|
|
4249
|
+
serviceDid: bootstrapValidation.bootstrapPackage.serviceDid,
|
|
4250
|
+
serviceOrigin: bootstrapValidation.bootstrapPackage.serviceOrigin,
|
|
4120
4251
|
adminDid: bootstrapValidation.bootstrapPackage.adminDid,
|
|
4121
4252
|
bootstrapPackage: bootstrapValidation.bootstrapPackage,
|
|
4122
4253
|
fetch: (url, init) => fetch(url, init),
|
|
@@ -5019,10 +5150,18 @@ var SponsorRelayController = class {
|
|
|
5019
5150
|
const [nextBalance, rawInstances, rawBootstrapPosts] = await Promise.all([
|
|
5020
5151
|
this.client.fetchBalance(this.state.wallet.address),
|
|
5021
5152
|
this.state.showInstances ? this.client.fetchInstances(this.state.wallet.address) : Promise.resolve([]),
|
|
5022
|
-
bootstrapEnabled ?
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5153
|
+
bootstrapEnabled ? Promise.all(
|
|
5154
|
+
[
|
|
5155
|
+
DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE,
|
|
5156
|
+
DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE
|
|
5157
|
+
].map(
|
|
5158
|
+
(postType) => fetchAlephBootstrapPosts({
|
|
5159
|
+
apiHost: this.client.apiHost,
|
|
5160
|
+
postType,
|
|
5161
|
+
fetch
|
|
5162
|
+
}).catch(() => [])
|
|
5163
|
+
)
|
|
5164
|
+
).then((pages) => pages.flat()) : Promise.resolve([])
|
|
5026
5165
|
]);
|
|
5027
5166
|
balance = nextBalance;
|
|
5028
5167
|
instances = await Promise.all(
|
|
@@ -18,6 +18,7 @@ export let openByDefault = false
|
|
|
18
18
|
export let launcherMode = 'floating'
|
|
19
19
|
export let version = ''
|
|
20
20
|
export let apiHost = undefined
|
|
21
|
+
export let apiHosts = undefined
|
|
21
22
|
export let crnListUrl = undefined
|
|
22
23
|
export let schedulerApiHost = undefined
|
|
23
24
|
export let twoN6ApiHost = undefined
|
|
@@ -32,6 +33,7 @@ export let apiHost = undefined
|
|
|
32
33
|
openByDefault,
|
|
33
34
|
launcherMode,
|
|
34
35
|
apiHost,
|
|
36
|
+
apiHosts,
|
|
35
37
|
crnListUrl,
|
|
36
38
|
schedulerApiHost,
|
|
37
39
|
twoN6ApiHost
|