@le-space/ui 0.6.24 → 0.6.26
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/README.md +1 -1
- package/package.json +4 -4
- package/react/index.js +103 -75
- package/shared/index.d.ts +1 -1
- package/shared/index.js +102 -74
- package/svelte/SponsorRelayFab.svelte +1 -1
- package/svelte/components/LauncherButton.svelte +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Floating Aleph relay deployment UI components for Svelte and React.
|
|
|
4
4
|
|
|
5
5
|
Primary goals:
|
|
6
6
|
|
|
7
|
-
- Svelte-first floating `
|
|
7
|
+
- Svelte-first floating `Relay Button` panel
|
|
8
8
|
- lightweight React wrapper
|
|
9
9
|
- shared controller and browser-safe Aleph helpers
|
|
10
10
|
- minimal host configuration beyond a rootfs manifest URL
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@le-space/ui",
|
|
3
|
-
"version": "0.6.
|
|
4
|
-
"description": "Floating Aleph
|
|
3
|
+
"version": "0.6.26",
|
|
4
|
+
"description": "Floating Aleph Relay Button UI components for Svelte and React.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|
|
@@ -44,8 +44,8 @@
|
|
|
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.
|
|
47
|
+
"@le-space/browser": "0.6.26",
|
|
48
|
+
"@le-space/core": "0.6.26",
|
|
49
49
|
"viem": "^2.53.1"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
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.26";
|
|
47
47
|
|
|
48
48
|
// src/shared/format.ts
|
|
49
49
|
function shortHash(value, head = 8, tail = 6) {
|
|
@@ -2486,8 +2486,7 @@ import { keccak256, recoverMessageAddress, stringToHex } from "viem";
|
|
|
2486
2486
|
var DEFAULT_ALEPH_API_HOST3 = "https://api.aleph.im";
|
|
2487
2487
|
var DEFAULT_ALEPH_BOOTSTRAP_CHANNEL = "simple-todo";
|
|
2488
2488
|
var DEFAULT_ALEPH_BOOTSTRAP_REF = "simple-todo-bootstrap";
|
|
2489
|
-
var DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE = "relay-bootstrap";
|
|
2490
|
-
var DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE = "relay-bootstrap-v2";
|
|
2489
|
+
var DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE = "relay-bootstrap-v2";
|
|
2491
2490
|
var DEFAULT_BOOTSTRAP_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
2492
2491
|
var DEFAULT_BOOTSTRAP_PAGINATION = 50;
|
|
2493
2492
|
var DEFAULT_BOOTSTRAP_COMPACT_MULTIADDR_LIMIT = 3;
|
|
@@ -2521,9 +2520,6 @@ function serializeRelayProofPayload(payload) {
|
|
|
2521
2520
|
function relayBootstrapMultiaddrsHash(addrs) {
|
|
2522
2521
|
return keccak256(stringToHex(JSON.stringify(dedupeMultiaddrs(addrs))));
|
|
2523
2522
|
}
|
|
2524
|
-
function compactPostType(postType) {
|
|
2525
|
-
return (postType ?? DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE) === DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
|
|
2526
|
-
}
|
|
2527
2523
|
function browserMultiaddrPreference(addr) {
|
|
2528
2524
|
const normalized = addr.toLowerCase();
|
|
2529
2525
|
if (normalized.includes("/tcp/443/tls/ws/")) return 0;
|
|
@@ -2537,7 +2533,8 @@ function browserMultiaddrTransport(addr) {
|
|
|
2537
2533
|
const normalized = addr.toLowerCase();
|
|
2538
2534
|
if (normalized.includes("/webtransport/")) return "webtransport";
|
|
2539
2535
|
if (normalized.includes("/webrtc-direct/")) return "webrtc";
|
|
2540
|
-
if (normalized.includes("/ws") || normalized.includes("/wss"))
|
|
2536
|
+
if (normalized.includes("/ws") || normalized.includes("/wss"))
|
|
2537
|
+
return "websocket";
|
|
2541
2538
|
return "other";
|
|
2542
2539
|
}
|
|
2543
2540
|
function selectCompactRelayBootstrapMultiaddrs(addrs, limit = DEFAULT_BOOTSTRAP_COMPACT_MULTIADDR_LIMIT) {
|
|
@@ -2614,7 +2611,10 @@ function hasPeerId(addr) {
|
|
|
2614
2611
|
}
|
|
2615
2612
|
function isBrowserDialableMultiaddr(addr) {
|
|
2616
2613
|
const normalized = addr.toLowerCase();
|
|
2617
|
-
|
|
2614
|
+
if (normalized.includes("/webtransport") || normalized.includes("/webrtc-direct")) {
|
|
2615
|
+
return normalized.includes("/certhash/");
|
|
2616
|
+
}
|
|
2617
|
+
return normalized.includes("/ws") || normalized.includes("/wss");
|
|
2618
2618
|
}
|
|
2619
2619
|
function dedupeMultiaddrs(addrs) {
|
|
2620
2620
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -2660,8 +2660,12 @@ function normalizeRelayBootstrapContent(value) {
|
|
|
2660
2660
|
const peerId = asTrimmedString(content.peerId);
|
|
2661
2661
|
const updatedAt = asNumber4(content.updatedAt);
|
|
2662
2662
|
if (!peerId || updatedAt == null) return null;
|
|
2663
|
-
const multiaddrs = Array.isArray(content.multiaddrs) ? content.multiaddrs.filter(
|
|
2664
|
-
|
|
2663
|
+
const multiaddrs = Array.isArray(content.multiaddrs) ? content.multiaddrs.filter(
|
|
2664
|
+
(entry) => typeof entry === "string"
|
|
2665
|
+
) : [];
|
|
2666
|
+
const browserMultiaddrs = Array.isArray(content.browserMultiaddrs) ? content.browserMultiaddrs.filter(
|
|
2667
|
+
(entry) => typeof entry === "string"
|
|
2668
|
+
) : void 0;
|
|
2665
2669
|
return {
|
|
2666
2670
|
peerId,
|
|
2667
2671
|
multiaddrs: dedupeMultiaddrs(multiaddrs),
|
|
@@ -2714,8 +2718,12 @@ function normalizeRelayBootstrapProofPayload(value) {
|
|
|
2714
2718
|
const peerId = asTrimmedString(payload.peerId);
|
|
2715
2719
|
const updatedAt = asNumber4(payload.updatedAt);
|
|
2716
2720
|
if (!peerId || updatedAt == null) return null;
|
|
2717
|
-
const multiaddrs = Array.isArray(payload.multiaddrs) ? payload.multiaddrs.filter(
|
|
2718
|
-
|
|
2721
|
+
const multiaddrs = Array.isArray(payload.multiaddrs) ? payload.multiaddrs.filter(
|
|
2722
|
+
(entry) => typeof entry === "string"
|
|
2723
|
+
) : [];
|
|
2724
|
+
const browserMultiaddrs = Array.isArray(payload.browserMultiaddrs) ? payload.browserMultiaddrs.filter(
|
|
2725
|
+
(entry) => typeof entry === "string"
|
|
2726
|
+
) : void 0;
|
|
2719
2727
|
return {
|
|
2720
2728
|
peerId,
|
|
2721
2729
|
multiaddrs: multiaddrs.length > 0 ? dedupeMultiaddrs(multiaddrs) : void 0,
|
|
@@ -2753,8 +2761,6 @@ function normalizeRelayBootstrapPostRecord(value) {
|
|
|
2753
2761
|
function buildRelayBootstrapPostContent(args) {
|
|
2754
2762
|
const now = args.now ?? Date.now() / 1e3;
|
|
2755
2763
|
const updatedAt = args.now ?? Date.now();
|
|
2756
|
-
const postType = args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE;
|
|
2757
|
-
const compact = args.compact ?? compactPostType(postType);
|
|
2758
2764
|
const fullMultiaddrs = filterPublicMultiaddrs(args.multiaddrs);
|
|
2759
2765
|
const fullBrowserMultiaddrs = args.browserMultiaddrs ? filterPublicMultiaddrs(args.browserMultiaddrs, {
|
|
2760
2766
|
browserDialableOnly: true
|
|
@@ -2764,13 +2770,13 @@ function buildRelayBootstrapPostContent(args) {
|
|
|
2764
2770
|
args.compactMultiaddrLimit
|
|
2765
2771
|
);
|
|
2766
2772
|
return {
|
|
2767
|
-
type:
|
|
2773
|
+
type: DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE,
|
|
2768
2774
|
address: args.sender,
|
|
2769
2775
|
...args.ref ? { ref: args.ref } : {},
|
|
2770
2776
|
content: {
|
|
2771
2777
|
peerId: args.peerId,
|
|
2772
|
-
multiaddrs:
|
|
2773
|
-
browserMultiaddrs:
|
|
2778
|
+
multiaddrs: compactMultiaddrs,
|
|
2779
|
+
browserMultiaddrs: void 0,
|
|
2774
2780
|
registrationId: args.registrationId,
|
|
2775
2781
|
profile: args.profile,
|
|
2776
2782
|
version: args.version,
|
|
@@ -2793,14 +2799,12 @@ async function createRelayBootstrapPost(args) {
|
|
|
2793
2799
|
browserMultiaddrs: args.browserMultiaddrs,
|
|
2794
2800
|
registrationId: args.registrationId,
|
|
2795
2801
|
ref: args.ref ?? DEFAULT_ALEPH_BOOTSTRAP_REF,
|
|
2796
|
-
postType: args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE,
|
|
2797
2802
|
profile: args.profile,
|
|
2798
2803
|
version: args.version,
|
|
2799
2804
|
ownerAddress: args.ownerAddress,
|
|
2800
2805
|
publisherAddress: args.publisherAddress,
|
|
2801
2806
|
authorization: args.authorization,
|
|
2802
2807
|
relayProof: args.relayProof,
|
|
2803
|
-
compact: args.compact,
|
|
2804
2808
|
compactMultiaddrLimit: args.compactMultiaddrLimit,
|
|
2805
2809
|
now: nowMillis
|
|
2806
2810
|
});
|
|
@@ -2847,12 +2851,11 @@ async function signRelayBootstrapProof(args) {
|
|
|
2847
2851
|
fullBrowserMultiaddrs && fullBrowserMultiaddrs.length > 0 ? fullBrowserMultiaddrs : fullMultiaddrs,
|
|
2848
2852
|
args.compactMultiaddrLimit
|
|
2849
2853
|
);
|
|
2850
|
-
const compact = args.compact ?? false;
|
|
2851
2854
|
const payload = {
|
|
2852
2855
|
peerId: args.peerId,
|
|
2853
|
-
multiaddrs:
|
|
2854
|
-
browserMultiaddrs:
|
|
2855
|
-
multiaddrsHash:
|
|
2856
|
+
multiaddrs: void 0,
|
|
2857
|
+
browserMultiaddrs: void 0,
|
|
2858
|
+
multiaddrsHash: relayBootstrapMultiaddrsHash(compactMultiaddrs),
|
|
2856
2859
|
registrationId: args.registrationId,
|
|
2857
2860
|
profile: args.profile,
|
|
2858
2861
|
version: args.version,
|
|
@@ -2882,10 +2885,7 @@ async function fetchAlephBootstrapPosts(options = {}) {
|
|
|
2882
2885
|
options.channel ?? DEFAULT_ALEPH_BOOTSTRAP_CHANNEL
|
|
2883
2886
|
);
|
|
2884
2887
|
url.searchParams.set("refs", options.ref ?? DEFAULT_ALEPH_BOOTSTRAP_REF);
|
|
2885
|
-
url.searchParams.set(
|
|
2886
|
-
"types",
|
|
2887
|
-
options.postType ?? DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE
|
|
2888
|
-
);
|
|
2888
|
+
url.searchParams.set("types", DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE);
|
|
2889
2889
|
url.searchParams.set(
|
|
2890
2890
|
"pagination",
|
|
2891
2891
|
String(options.pagination ?? DEFAULT_BOOTSTRAP_PAGINATION)
|
|
@@ -2899,7 +2899,21 @@ async function fetchAlephBootstrapPosts(options = {}) {
|
|
|
2899
2899
|
throw new Error(`Aleph bootstrap post lookup failed: ${response.status}`);
|
|
2900
2900
|
}
|
|
2901
2901
|
const payload = await response.json();
|
|
2902
|
-
|
|
2902
|
+
const posts = (payload.posts ?? []).map((entry) => normalizeRelayBootstrapPostRecord(entry)).filter((entry) => entry != null).sort((left, right) => compareRelayBootstrapPostRecency(right, left));
|
|
2903
|
+
posts.forEach(assertSupportedRelayBootstrapPost);
|
|
2904
|
+
return posts;
|
|
2905
|
+
}
|
|
2906
|
+
function assertSupportedRelayBootstrapPost(post) {
|
|
2907
|
+
if (post.type === "relay-bootstrap") {
|
|
2908
|
+
throw new Error(
|
|
2909
|
+
"Legacy relay-bootstrap record encountered. Only relay-bootstrap-v2 is supported."
|
|
2910
|
+
);
|
|
2911
|
+
}
|
|
2912
|
+
if (post.type && post.type !== DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE) {
|
|
2913
|
+
throw new Error(
|
|
2914
|
+
`Unsupported relay bootstrap post type: ${post.type}. Expected ${DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE}.`
|
|
2915
|
+
);
|
|
2916
|
+
}
|
|
2903
2917
|
}
|
|
2904
2918
|
function compareRelayBootstrapPostRecency(left, right) {
|
|
2905
2919
|
const leftUpdatedAt = left.content?.updatedAt ?? 0;
|
|
@@ -2921,6 +2935,7 @@ function selectCurrentRelayBootstrapPosts(posts, options = {}) {
|
|
|
2921
2935
|
const now = options.now ?? Date.now();
|
|
2922
2936
|
const selected = /* @__PURE__ */ new Map();
|
|
2923
2937
|
for (const post of posts) {
|
|
2938
|
+
assertSupportedRelayBootstrapPost(post);
|
|
2924
2939
|
const content = post.content;
|
|
2925
2940
|
if (!content) continue;
|
|
2926
2941
|
if (now - content.updatedAt > maxAgeMs) continue;
|
|
@@ -2946,14 +2961,12 @@ async function waitForRelayBootstrapRegistration(args) {
|
|
|
2946
2961
|
const expectedSender = args.sender?.trim().toLowerCase() || null;
|
|
2947
2962
|
const expectedRegistrationId = args.registrationId?.trim() || null;
|
|
2948
2963
|
const expectedPeerId = args.peerId?.trim() || null;
|
|
2949
|
-
const postType = args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
|
|
2950
2964
|
const sleepImpl = args.sleep ?? sleep;
|
|
2951
2965
|
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
2952
2966
|
const posts = await fetchAlephBootstrapPosts({
|
|
2953
2967
|
apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
|
|
2954
2968
|
channel: args.channel,
|
|
2955
2969
|
ref: args.ref,
|
|
2956
|
-
postType,
|
|
2957
2970
|
fetch: args.fetch
|
|
2958
2971
|
});
|
|
2959
2972
|
const currentPosts = selectCurrentRelayBootstrapPosts(posts);
|
|
@@ -2992,8 +3005,6 @@ async function waitForRelayBootstrapRegistration(args) {
|
|
|
2992
3005
|
async function publishRelayBootstrapRegistration(args) {
|
|
2993
3006
|
const publisherAddress = args.publisherAddress ?? args.sender;
|
|
2994
3007
|
const ownerAddress = args.ownerAddress;
|
|
2995
|
-
const postType = args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
|
|
2996
|
-
const compact = postType === DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
|
|
2997
3008
|
let ownerAuthorization = args.ownerAuthorization;
|
|
2998
3009
|
let relayProof = args.relayProof;
|
|
2999
3010
|
if (!ownerAuthorization && ownerAddress && args.ownerSigner) {
|
|
@@ -3020,7 +3031,6 @@ async function publishRelayBootstrapRegistration(args) {
|
|
|
3020
3031
|
profile: args.profile,
|
|
3021
3032
|
version: args.version,
|
|
3022
3033
|
updatedAt: args.now ?? Date.now(),
|
|
3023
|
-
compact,
|
|
3024
3034
|
compactMultiaddrLimit: args.compactMultiaddrLimit,
|
|
3025
3035
|
signer: args.publisherSigner
|
|
3026
3036
|
});
|
|
@@ -3033,14 +3043,12 @@ async function publishRelayBootstrapRegistration(args) {
|
|
|
3033
3043
|
registrationId: args.registrationId,
|
|
3034
3044
|
channel: args.channel,
|
|
3035
3045
|
ref: args.ref,
|
|
3036
|
-
postType,
|
|
3037
3046
|
profile: args.profile,
|
|
3038
3047
|
version: args.version,
|
|
3039
3048
|
ownerAddress,
|
|
3040
3049
|
publisherAddress,
|
|
3041
3050
|
authorization: ownerAuthorization,
|
|
3042
3051
|
relayProof,
|
|
3043
|
-
compact,
|
|
3044
3052
|
compactMultiaddrLimit: args.compactMultiaddrLimit,
|
|
3045
3053
|
now: args.now,
|
|
3046
3054
|
hasher: args.hasher
|
|
@@ -3063,18 +3071,12 @@ async function publishRelayBootstrapRegistration(args) {
|
|
|
3063
3071
|
let forgottenHashes = [];
|
|
3064
3072
|
let forgetResult;
|
|
3065
3073
|
if (args.forgetPrevious && args.registrationId) {
|
|
3066
|
-
const
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
ref: args.ref,
|
|
3073
|
-
postType: previousPostType,
|
|
3074
|
-
fetch: args.fetch
|
|
3075
|
-
})
|
|
3076
|
-
)
|
|
3077
|
-
)).flat();
|
|
3074
|
+
const previousPosts = await fetchAlephBootstrapPosts({
|
|
3075
|
+
apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
|
|
3076
|
+
channel: args.channel,
|
|
3077
|
+
ref: args.ref,
|
|
3078
|
+
fetch: args.fetch
|
|
3079
|
+
});
|
|
3078
3080
|
const forgottenHashSet = new Set(
|
|
3079
3081
|
previousPosts.filter((post) => {
|
|
3080
3082
|
const hash = post.itemHash ?? post.hash;
|
|
@@ -3676,7 +3678,9 @@ function draftUcanStoreBootstrapErrors(args) {
|
|
|
3676
3678
|
const errors = [];
|
|
3677
3679
|
const { input } = args;
|
|
3678
3680
|
if (!args.operatorAddress) {
|
|
3679
|
-
errors.push(
|
|
3681
|
+
errors.push(
|
|
3682
|
+
"Connect MetaMask before configuring the ucan-store bootstrap package."
|
|
3683
|
+
);
|
|
3680
3684
|
}
|
|
3681
3685
|
if (!input.adminDid.trim().startsWith("did:")) {
|
|
3682
3686
|
errors.push("Admin DID must be a non-empty DID string.");
|
|
@@ -3727,7 +3731,9 @@ function buildUcanStoreBootstrapPackage(args) {
|
|
|
3727
3731
|
serviceDid: args.input.serviceDid.trim() || null,
|
|
3728
3732
|
spaceDid: args.input.spaceDid.trim(),
|
|
3729
3733
|
rootDelegationProof: args.input.rootDelegationProof.trim(),
|
|
3730
|
-
allowedCapabilities: parseAllowedCapabilities(
|
|
3734
|
+
allowedCapabilities: parseAllowedCapabilities(
|
|
3735
|
+
args.input.allowedCapabilities
|
|
3736
|
+
),
|
|
3731
3737
|
defaultUserDelegationExpiration: parseOptionalExpiration(
|
|
3732
3738
|
args.input.defaultUserDelegationExpiration
|
|
3733
3739
|
),
|
|
@@ -3766,7 +3772,9 @@ function defaultState(props = {}) {
|
|
|
3766
3772
|
instanceName: props.instanceName ?? DEFAULT_INSTANCE_NAME,
|
|
3767
3773
|
ucanStoreBootstrap: defaultUcanStoreBootstrapInput(props),
|
|
3768
3774
|
tierId: DEFAULT_TIER_ID,
|
|
3769
|
-
showAdvanced: Boolean(
|
|
3775
|
+
showAdvanced: Boolean(
|
|
3776
|
+
props.manifestJson?.trim() || props.sshPublicKey?.trim()
|
|
3777
|
+
),
|
|
3770
3778
|
showInstances: props.showInstances ?? true,
|
|
3771
3779
|
showPasteManifest: Boolean(props.manifestJson?.trim()),
|
|
3772
3780
|
busy: {
|
|
@@ -4186,7 +4194,9 @@ var SponsorRelayController = class {
|
|
|
4186
4194
|
const profile = bootstrapRelayProfileForManifest(this.state.manifest);
|
|
4187
4195
|
if (!profile && deploymentProfile !== "ucan-store") return;
|
|
4188
4196
|
if (profile && !this.state.wallet.address) {
|
|
4189
|
-
throw new Error(
|
|
4197
|
+
throw new Error(
|
|
4198
|
+
"A connected wallet is required to register relay bootstrap addresses."
|
|
4199
|
+
);
|
|
4190
4200
|
}
|
|
4191
4201
|
const runtimeHostIpv4 = args.runtime.hostIpv4;
|
|
4192
4202
|
if (!runtimeHostIpv4) {
|
|
@@ -4210,7 +4220,9 @@ var SponsorRelayController = class {
|
|
|
4210
4220
|
}
|
|
4211
4221
|
const walletAddress2 = this.state.wallet.address;
|
|
4212
4222
|
if (!walletAddress2) {
|
|
4213
|
-
throw new Error(
|
|
4223
|
+
throw new Error(
|
|
4224
|
+
"A connected wallet is required to configure the ucan-store bootstrap package."
|
|
4225
|
+
);
|
|
4214
4226
|
}
|
|
4215
4227
|
const bootstrapValidation = buildUcanStoreBootstrapPackage({
|
|
4216
4228
|
input: this.state.ucanStoreBootstrap,
|
|
@@ -4325,7 +4337,9 @@ var SponsorRelayController = class {
|
|
|
4325
4337
|
if (!profile) return;
|
|
4326
4338
|
const walletAddress = this.state.wallet.address;
|
|
4327
4339
|
if (!walletAddress) {
|
|
4328
|
-
throw new Error(
|
|
4340
|
+
throw new Error(
|
|
4341
|
+
"A connected wallet is required to register relay bootstrap addresses."
|
|
4342
|
+
);
|
|
4329
4343
|
}
|
|
4330
4344
|
let bootstrapSignalRelayMetadata = null;
|
|
4331
4345
|
if (profile === "orbitdb-relay") {
|
|
@@ -4371,7 +4385,9 @@ var SponsorRelayController = class {
|
|
|
4371
4385
|
const tcpPort = mappedPorts2["9091"]?.host ?? 0;
|
|
4372
4386
|
const wsPort = mappedPorts2["9092"]?.host ?? mappedPorts2["443"]?.host ?? 0;
|
|
4373
4387
|
if (!tcpPort || !wsPort) {
|
|
4374
|
-
throw new Error(
|
|
4388
|
+
throw new Error(
|
|
4389
|
+
"OrbitDB relay runtime is missing required mapped TCP/WS ports."
|
|
4390
|
+
);
|
|
4375
4391
|
}
|
|
4376
4392
|
const configureResult = await configureOrbitdbRelaySetup2({
|
|
4377
4393
|
hostIpv4: runtimeHostIpv4,
|
|
@@ -4394,7 +4410,9 @@ var SponsorRelayController = class {
|
|
|
4394
4410
|
}
|
|
4395
4411
|
} else {
|
|
4396
4412
|
if (!args.deploymentToken) {
|
|
4397
|
-
throw new Error(
|
|
4413
|
+
throw new Error(
|
|
4414
|
+
"Missing deployment token for Aleph bootstrap config handoff."
|
|
4415
|
+
);
|
|
4398
4416
|
}
|
|
4399
4417
|
if (runtime.proxyUrl && runtime.webAccess?.active !== true) {
|
|
4400
4418
|
this.emitProgress({
|
|
@@ -4620,7 +4638,19 @@ var SponsorRelayController = class {
|
|
|
4620
4638
|
});
|
|
4621
4639
|
return;
|
|
4622
4640
|
}
|
|
4623
|
-
throw new Error(
|
|
4641
|
+
throw new Error(
|
|
4642
|
+
"Relay metadata did not include a peer ID and public multiaddrs."
|
|
4643
|
+
);
|
|
4644
|
+
}
|
|
4645
|
+
if (profile === "uc-go-peer") {
|
|
4646
|
+
const browserDialableMultiaddrs = relayMetadata.browserBootstrapMultiaddrs.filter(
|
|
4647
|
+
(multiaddr) => /\/(?:tls\/ws|wss)\/p2p\//.test(multiaddr) || /\/(?:webtransport|webrtc-direct)\//.test(multiaddr) && /\/certhash\//.test(multiaddr)
|
|
4648
|
+
);
|
|
4649
|
+
if (browserDialableMultiaddrs.length === 0) {
|
|
4650
|
+
throw new Error(
|
|
4651
|
+
"Relay metadata did not include a browser-dialable WSS address or a WebTransport/WebRTC Direct address with certhash."
|
|
4652
|
+
);
|
|
4653
|
+
}
|
|
4624
4654
|
}
|
|
4625
4655
|
const { peerId } = relayMetadata;
|
|
4626
4656
|
const registrationId = createRelayBootstrapRegistrationId(
|
|
@@ -5172,18 +5202,10 @@ var SponsorRelayController = class {
|
|
|
5172
5202
|
const [nextBalance, rawInstances, rawBootstrapPosts] = await Promise.all([
|
|
5173
5203
|
this.client.fetchBalance(this.state.wallet.address),
|
|
5174
5204
|
this.state.showInstances ? this.client.fetchInstances(this.state.wallet.address) : Promise.resolve([]),
|
|
5175
|
-
bootstrapEnabled ?
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
].map(
|
|
5180
|
-
(postType) => fetchAlephBootstrapPosts({
|
|
5181
|
-
apiHost: this.client.apiHost,
|
|
5182
|
-
postType,
|
|
5183
|
-
fetch
|
|
5184
|
-
}).catch(() => [])
|
|
5185
|
-
)
|
|
5186
|
-
).then((pages) => pages.flat()) : Promise.resolve([])
|
|
5205
|
+
bootstrapEnabled ? fetchAlephBootstrapPosts({
|
|
5206
|
+
apiHost: this.client.apiHost,
|
|
5207
|
+
fetch
|
|
5208
|
+
}) : Promise.resolve([])
|
|
5187
5209
|
]);
|
|
5188
5210
|
balance = nextBalance;
|
|
5189
5211
|
instances = await Promise.all(
|
|
@@ -5247,7 +5269,9 @@ var SponsorRelayController = class {
|
|
|
5247
5269
|
const activeInstanceHashes = new Set(
|
|
5248
5270
|
instances.map((entry) => entry.instance.item_hash)
|
|
5249
5271
|
);
|
|
5250
|
-
bootstrapRegistrations = selectCurrentRelayBootstrapPosts(
|
|
5272
|
+
bootstrapRegistrations = selectCurrentRelayBootstrapPosts(
|
|
5273
|
+
rawBootstrapPosts
|
|
5274
|
+
).filter(
|
|
5251
5275
|
(entry) => relayBootstrapMatchesCurrentWallet(
|
|
5252
5276
|
entry,
|
|
5253
5277
|
normalizedWalletAddress,
|
|
@@ -5270,7 +5294,9 @@ var SponsorRelayController = class {
|
|
|
5270
5294
|
peerId: entry.content.peerId,
|
|
5271
5295
|
registrationId: entry.content.registrationId,
|
|
5272
5296
|
multiaddrs: Array.isArray(entry.content.multiaddrs) ? entry.content.multiaddrs : [],
|
|
5273
|
-
browserMultiaddrs: Array.isArray(
|
|
5297
|
+
browserMultiaddrs: Array.isArray(
|
|
5298
|
+
entry.content.browserMultiaddrs
|
|
5299
|
+
) ? entry.content.browserMultiaddrs : [],
|
|
5274
5300
|
ownerAddress: typeof entry.content.ownerAddress === "string" ? entry.content.ownerAddress : void 0,
|
|
5275
5301
|
publisherAddress: typeof entry.content.publisherAddress === "string" ? entry.content.publisherAddress : void 0,
|
|
5276
5302
|
updatedAt: entry.content.updatedAt
|
|
@@ -5391,7 +5417,9 @@ var SponsorRelayController = class {
|
|
|
5391
5417
|
...compatibleCrns2.filter((crn) => crn.hash !== preferredCrnHash)
|
|
5392
5418
|
].slice(0, 5);
|
|
5393
5419
|
if (orderedCrns.length === 0) {
|
|
5394
|
-
throw new Error(
|
|
5420
|
+
throw new Error(
|
|
5421
|
+
"No compatible CRN is currently available for this tier."
|
|
5422
|
+
);
|
|
5395
5423
|
}
|
|
5396
5424
|
const attemptErrors = [];
|
|
5397
5425
|
let lastError = null;
|
|
@@ -5824,7 +5852,7 @@ var SponsorRelayController = class {
|
|
|
5824
5852
|
await forgetAlephMessages({
|
|
5825
5853
|
sender: this.state.wallet.address,
|
|
5826
5854
|
hashes: [attemptItemHash],
|
|
5827
|
-
reason: `Discard failed
|
|
5855
|
+
reason: `Discard failed Relay Button deployment attempt on ${attemptLabel}`,
|
|
5828
5856
|
signer: personalSign,
|
|
5829
5857
|
hasher: sha256Hex,
|
|
5830
5858
|
fetch: (url, init) => fetch(url, init).then(async (response) => ({
|
|
@@ -5934,7 +5962,7 @@ var SponsorRelayController = class {
|
|
|
5934
5962
|
await forgetAlephMessages({
|
|
5935
5963
|
sender: this.state.wallet.address,
|
|
5936
5964
|
hashes: hashesToForget,
|
|
5937
|
-
reason: linkedRegistrationCount > 0 ? `Deleted instance and ${linkedRegistrationCount} linked relay bootstrap registration${linkedRegistrationCount === 1 ? "" : "s"} from
|
|
5965
|
+
reason: linkedRegistrationCount > 0 ? `Deleted instance and ${linkedRegistrationCount} linked relay bootstrap registration${linkedRegistrationCount === 1 ? "" : "s"} from Relay Button panel` : "Deleted from Relay Button panel",
|
|
5938
5966
|
signer: personalSign,
|
|
5939
5967
|
hasher: sha256Hex,
|
|
5940
5968
|
fetch: asJsonFetch,
|
|
@@ -6003,7 +6031,7 @@ var SponsorRelayController = class {
|
|
|
6003
6031
|
await forgetAlephMessages({
|
|
6004
6032
|
sender: this.state.wallet.address,
|
|
6005
6033
|
hashes: [registrationHash],
|
|
6006
|
-
reason: "Deleted orphan relay bootstrap registration from
|
|
6034
|
+
reason: "Deleted orphan relay bootstrap registration from Relay Button panel",
|
|
6007
6035
|
signer: personalSign,
|
|
6008
6036
|
hasher: sha256Hex,
|
|
6009
6037
|
fetch: asJsonFetch,
|
|
@@ -6208,7 +6236,7 @@ function supportsBootstrapUi(state) {
|
|
|
6208
6236
|
return stateDeploymentProfile(state) !== "ucan-store";
|
|
6209
6237
|
}
|
|
6210
6238
|
function deploymentPanelTitle(state) {
|
|
6211
|
-
return stateDeploymentProfile(state) === "ucan-store" ? "Sponsor Service" : "
|
|
6239
|
+
return stateDeploymentProfile(state) === "ucan-store" ? "Sponsor Service" : "Relay Button";
|
|
6212
6240
|
}
|
|
6213
6241
|
function deploymentLauncherLabel(state, compactInlineLabel, launcherMode) {
|
|
6214
6242
|
if (launcherMode === "inline" && compactInlineLabel) {
|
package/shared/index.d.ts
CHANGED
|
@@ -332,7 +332,7 @@ declare const STALE_INSTANCE_ALLOCATION_COOLDOWN_MS: number;
|
|
|
332
332
|
declare const RECENT_INSTANCE_RUNTIME_GRACE_MS: number;
|
|
333
333
|
declare const DEPLOYMENT_PENDING_WARNING_MS: number;
|
|
334
334
|
|
|
335
|
-
declare const UI_PACKAGE_VERSION = "0.6.
|
|
335
|
+
declare const UI_PACKAGE_VERSION = "0.6.26";
|
|
336
336
|
|
|
337
337
|
interface RootfsRequiredPortForward {
|
|
338
338
|
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.26";
|
|
46
46
|
|
|
47
47
|
// src/shared/format.ts
|
|
48
48
|
function shortHash(value, head = 8, tail = 6) {
|
|
@@ -2485,8 +2485,7 @@ import { keccak256, recoverMessageAddress, stringToHex } from "viem";
|
|
|
2485
2485
|
var DEFAULT_ALEPH_API_HOST3 = "https://api.aleph.im";
|
|
2486
2486
|
var DEFAULT_ALEPH_BOOTSTRAP_CHANNEL = "simple-todo";
|
|
2487
2487
|
var DEFAULT_ALEPH_BOOTSTRAP_REF = "simple-todo-bootstrap";
|
|
2488
|
-
var DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE = "relay-bootstrap";
|
|
2489
|
-
var DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE = "relay-bootstrap-v2";
|
|
2488
|
+
var DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE = "relay-bootstrap-v2";
|
|
2490
2489
|
var DEFAULT_BOOTSTRAP_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
2491
2490
|
var DEFAULT_BOOTSTRAP_PAGINATION = 50;
|
|
2492
2491
|
var DEFAULT_BOOTSTRAP_COMPACT_MULTIADDR_LIMIT = 3;
|
|
@@ -2520,9 +2519,6 @@ function serializeRelayProofPayload(payload) {
|
|
|
2520
2519
|
function relayBootstrapMultiaddrsHash(addrs) {
|
|
2521
2520
|
return keccak256(stringToHex(JSON.stringify(dedupeMultiaddrs(addrs))));
|
|
2522
2521
|
}
|
|
2523
|
-
function compactPostType(postType) {
|
|
2524
|
-
return (postType ?? DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE) === DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
|
|
2525
|
-
}
|
|
2526
2522
|
function browserMultiaddrPreference(addr) {
|
|
2527
2523
|
const normalized = addr.toLowerCase();
|
|
2528
2524
|
if (normalized.includes("/tcp/443/tls/ws/")) return 0;
|
|
@@ -2536,7 +2532,8 @@ function browserMultiaddrTransport(addr) {
|
|
|
2536
2532
|
const normalized = addr.toLowerCase();
|
|
2537
2533
|
if (normalized.includes("/webtransport/")) return "webtransport";
|
|
2538
2534
|
if (normalized.includes("/webrtc-direct/")) return "webrtc";
|
|
2539
|
-
if (normalized.includes("/ws") || normalized.includes("/wss"))
|
|
2535
|
+
if (normalized.includes("/ws") || normalized.includes("/wss"))
|
|
2536
|
+
return "websocket";
|
|
2540
2537
|
return "other";
|
|
2541
2538
|
}
|
|
2542
2539
|
function selectCompactRelayBootstrapMultiaddrs(addrs, limit = DEFAULT_BOOTSTRAP_COMPACT_MULTIADDR_LIMIT) {
|
|
@@ -2613,7 +2610,10 @@ function hasPeerId(addr) {
|
|
|
2613
2610
|
}
|
|
2614
2611
|
function isBrowserDialableMultiaddr(addr) {
|
|
2615
2612
|
const normalized = addr.toLowerCase();
|
|
2616
|
-
|
|
2613
|
+
if (normalized.includes("/webtransport") || normalized.includes("/webrtc-direct")) {
|
|
2614
|
+
return normalized.includes("/certhash/");
|
|
2615
|
+
}
|
|
2616
|
+
return normalized.includes("/ws") || normalized.includes("/wss");
|
|
2617
2617
|
}
|
|
2618
2618
|
function dedupeMultiaddrs(addrs) {
|
|
2619
2619
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -2659,8 +2659,12 @@ function normalizeRelayBootstrapContent(value) {
|
|
|
2659
2659
|
const peerId = asTrimmedString(content.peerId);
|
|
2660
2660
|
const updatedAt = asNumber4(content.updatedAt);
|
|
2661
2661
|
if (!peerId || updatedAt == null) return null;
|
|
2662
|
-
const multiaddrs = Array.isArray(content.multiaddrs) ? content.multiaddrs.filter(
|
|
2663
|
-
|
|
2662
|
+
const multiaddrs = Array.isArray(content.multiaddrs) ? content.multiaddrs.filter(
|
|
2663
|
+
(entry) => typeof entry === "string"
|
|
2664
|
+
) : [];
|
|
2665
|
+
const browserMultiaddrs = Array.isArray(content.browserMultiaddrs) ? content.browserMultiaddrs.filter(
|
|
2666
|
+
(entry) => typeof entry === "string"
|
|
2667
|
+
) : void 0;
|
|
2664
2668
|
return {
|
|
2665
2669
|
peerId,
|
|
2666
2670
|
multiaddrs: dedupeMultiaddrs(multiaddrs),
|
|
@@ -2713,8 +2717,12 @@ function normalizeRelayBootstrapProofPayload(value) {
|
|
|
2713
2717
|
const peerId = asTrimmedString(payload.peerId);
|
|
2714
2718
|
const updatedAt = asNumber4(payload.updatedAt);
|
|
2715
2719
|
if (!peerId || updatedAt == null) return null;
|
|
2716
|
-
const multiaddrs = Array.isArray(payload.multiaddrs) ? payload.multiaddrs.filter(
|
|
2717
|
-
|
|
2720
|
+
const multiaddrs = Array.isArray(payload.multiaddrs) ? payload.multiaddrs.filter(
|
|
2721
|
+
(entry) => typeof entry === "string"
|
|
2722
|
+
) : [];
|
|
2723
|
+
const browserMultiaddrs = Array.isArray(payload.browserMultiaddrs) ? payload.browserMultiaddrs.filter(
|
|
2724
|
+
(entry) => typeof entry === "string"
|
|
2725
|
+
) : void 0;
|
|
2718
2726
|
return {
|
|
2719
2727
|
peerId,
|
|
2720
2728
|
multiaddrs: multiaddrs.length > 0 ? dedupeMultiaddrs(multiaddrs) : void 0,
|
|
@@ -2752,8 +2760,6 @@ function normalizeRelayBootstrapPostRecord(value) {
|
|
|
2752
2760
|
function buildRelayBootstrapPostContent(args) {
|
|
2753
2761
|
const now = args.now ?? Date.now() / 1e3;
|
|
2754
2762
|
const updatedAt = args.now ?? Date.now();
|
|
2755
|
-
const postType = args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE;
|
|
2756
|
-
const compact = args.compact ?? compactPostType(postType);
|
|
2757
2763
|
const fullMultiaddrs = filterPublicMultiaddrs(args.multiaddrs);
|
|
2758
2764
|
const fullBrowserMultiaddrs = args.browserMultiaddrs ? filterPublicMultiaddrs(args.browserMultiaddrs, {
|
|
2759
2765
|
browserDialableOnly: true
|
|
@@ -2763,13 +2769,13 @@ function buildRelayBootstrapPostContent(args) {
|
|
|
2763
2769
|
args.compactMultiaddrLimit
|
|
2764
2770
|
);
|
|
2765
2771
|
return {
|
|
2766
|
-
type:
|
|
2772
|
+
type: DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE,
|
|
2767
2773
|
address: args.sender,
|
|
2768
2774
|
...args.ref ? { ref: args.ref } : {},
|
|
2769
2775
|
content: {
|
|
2770
2776
|
peerId: args.peerId,
|
|
2771
|
-
multiaddrs:
|
|
2772
|
-
browserMultiaddrs:
|
|
2777
|
+
multiaddrs: compactMultiaddrs,
|
|
2778
|
+
browserMultiaddrs: void 0,
|
|
2773
2779
|
registrationId: args.registrationId,
|
|
2774
2780
|
profile: args.profile,
|
|
2775
2781
|
version: args.version,
|
|
@@ -2792,14 +2798,12 @@ async function createRelayBootstrapPost(args) {
|
|
|
2792
2798
|
browserMultiaddrs: args.browserMultiaddrs,
|
|
2793
2799
|
registrationId: args.registrationId,
|
|
2794
2800
|
ref: args.ref ?? DEFAULT_ALEPH_BOOTSTRAP_REF,
|
|
2795
|
-
postType: args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE,
|
|
2796
2801
|
profile: args.profile,
|
|
2797
2802
|
version: args.version,
|
|
2798
2803
|
ownerAddress: args.ownerAddress,
|
|
2799
2804
|
publisherAddress: args.publisherAddress,
|
|
2800
2805
|
authorization: args.authorization,
|
|
2801
2806
|
relayProof: args.relayProof,
|
|
2802
|
-
compact: args.compact,
|
|
2803
2807
|
compactMultiaddrLimit: args.compactMultiaddrLimit,
|
|
2804
2808
|
now: nowMillis
|
|
2805
2809
|
});
|
|
@@ -2846,12 +2850,11 @@ async function signRelayBootstrapProof(args) {
|
|
|
2846
2850
|
fullBrowserMultiaddrs && fullBrowserMultiaddrs.length > 0 ? fullBrowserMultiaddrs : fullMultiaddrs,
|
|
2847
2851
|
args.compactMultiaddrLimit
|
|
2848
2852
|
);
|
|
2849
|
-
const compact = args.compact ?? false;
|
|
2850
2853
|
const payload = {
|
|
2851
2854
|
peerId: args.peerId,
|
|
2852
|
-
multiaddrs:
|
|
2853
|
-
browserMultiaddrs:
|
|
2854
|
-
multiaddrsHash:
|
|
2855
|
+
multiaddrs: void 0,
|
|
2856
|
+
browserMultiaddrs: void 0,
|
|
2857
|
+
multiaddrsHash: relayBootstrapMultiaddrsHash(compactMultiaddrs),
|
|
2855
2858
|
registrationId: args.registrationId,
|
|
2856
2859
|
profile: args.profile,
|
|
2857
2860
|
version: args.version,
|
|
@@ -2881,10 +2884,7 @@ async function fetchAlephBootstrapPosts(options = {}) {
|
|
|
2881
2884
|
options.channel ?? DEFAULT_ALEPH_BOOTSTRAP_CHANNEL
|
|
2882
2885
|
);
|
|
2883
2886
|
url.searchParams.set("refs", options.ref ?? DEFAULT_ALEPH_BOOTSTRAP_REF);
|
|
2884
|
-
url.searchParams.set(
|
|
2885
|
-
"types",
|
|
2886
|
-
options.postType ?? DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE
|
|
2887
|
-
);
|
|
2887
|
+
url.searchParams.set("types", DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE);
|
|
2888
2888
|
url.searchParams.set(
|
|
2889
2889
|
"pagination",
|
|
2890
2890
|
String(options.pagination ?? DEFAULT_BOOTSTRAP_PAGINATION)
|
|
@@ -2898,7 +2898,21 @@ async function fetchAlephBootstrapPosts(options = {}) {
|
|
|
2898
2898
|
throw new Error(`Aleph bootstrap post lookup failed: ${response.status}`);
|
|
2899
2899
|
}
|
|
2900
2900
|
const payload = await response.json();
|
|
2901
|
-
|
|
2901
|
+
const posts = (payload.posts ?? []).map((entry) => normalizeRelayBootstrapPostRecord(entry)).filter((entry) => entry != null).sort((left, right) => compareRelayBootstrapPostRecency(right, left));
|
|
2902
|
+
posts.forEach(assertSupportedRelayBootstrapPost);
|
|
2903
|
+
return posts;
|
|
2904
|
+
}
|
|
2905
|
+
function assertSupportedRelayBootstrapPost(post) {
|
|
2906
|
+
if (post.type === "relay-bootstrap") {
|
|
2907
|
+
throw new Error(
|
|
2908
|
+
"Legacy relay-bootstrap record encountered. Only relay-bootstrap-v2 is supported."
|
|
2909
|
+
);
|
|
2910
|
+
}
|
|
2911
|
+
if (post.type && post.type !== DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE) {
|
|
2912
|
+
throw new Error(
|
|
2913
|
+
`Unsupported relay bootstrap post type: ${post.type}. Expected ${DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE}.`
|
|
2914
|
+
);
|
|
2915
|
+
}
|
|
2902
2916
|
}
|
|
2903
2917
|
function compareRelayBootstrapPostRecency(left, right) {
|
|
2904
2918
|
const leftUpdatedAt = left.content?.updatedAt ?? 0;
|
|
@@ -2920,6 +2934,7 @@ function selectCurrentRelayBootstrapPosts(posts, options = {}) {
|
|
|
2920
2934
|
const now = options.now ?? Date.now();
|
|
2921
2935
|
const selected = /* @__PURE__ */ new Map();
|
|
2922
2936
|
for (const post of posts) {
|
|
2937
|
+
assertSupportedRelayBootstrapPost(post);
|
|
2923
2938
|
const content = post.content;
|
|
2924
2939
|
if (!content) continue;
|
|
2925
2940
|
if (now - content.updatedAt > maxAgeMs) continue;
|
|
@@ -2945,14 +2960,12 @@ async function waitForRelayBootstrapRegistration(args) {
|
|
|
2945
2960
|
const expectedSender = args.sender?.trim().toLowerCase() || null;
|
|
2946
2961
|
const expectedRegistrationId = args.registrationId?.trim() || null;
|
|
2947
2962
|
const expectedPeerId = args.peerId?.trim() || null;
|
|
2948
|
-
const postType = args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
|
|
2949
2963
|
const sleepImpl = args.sleep ?? sleep;
|
|
2950
2964
|
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
2951
2965
|
const posts = await fetchAlephBootstrapPosts({
|
|
2952
2966
|
apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
|
|
2953
2967
|
channel: args.channel,
|
|
2954
2968
|
ref: args.ref,
|
|
2955
|
-
postType,
|
|
2956
2969
|
fetch: args.fetch
|
|
2957
2970
|
});
|
|
2958
2971
|
const currentPosts = selectCurrentRelayBootstrapPosts(posts);
|
|
@@ -2991,8 +3004,6 @@ async function waitForRelayBootstrapRegistration(args) {
|
|
|
2991
3004
|
async function publishRelayBootstrapRegistration(args) {
|
|
2992
3005
|
const publisherAddress = args.publisherAddress ?? args.sender;
|
|
2993
3006
|
const ownerAddress = args.ownerAddress;
|
|
2994
|
-
const postType = args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
|
|
2995
|
-
const compact = postType === DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
|
|
2996
3007
|
let ownerAuthorization = args.ownerAuthorization;
|
|
2997
3008
|
let relayProof = args.relayProof;
|
|
2998
3009
|
if (!ownerAuthorization && ownerAddress && args.ownerSigner) {
|
|
@@ -3019,7 +3030,6 @@ async function publishRelayBootstrapRegistration(args) {
|
|
|
3019
3030
|
profile: args.profile,
|
|
3020
3031
|
version: args.version,
|
|
3021
3032
|
updatedAt: args.now ?? Date.now(),
|
|
3022
|
-
compact,
|
|
3023
3033
|
compactMultiaddrLimit: args.compactMultiaddrLimit,
|
|
3024
3034
|
signer: args.publisherSigner
|
|
3025
3035
|
});
|
|
@@ -3032,14 +3042,12 @@ async function publishRelayBootstrapRegistration(args) {
|
|
|
3032
3042
|
registrationId: args.registrationId,
|
|
3033
3043
|
channel: args.channel,
|
|
3034
3044
|
ref: args.ref,
|
|
3035
|
-
postType,
|
|
3036
3045
|
profile: args.profile,
|
|
3037
3046
|
version: args.version,
|
|
3038
3047
|
ownerAddress,
|
|
3039
3048
|
publisherAddress,
|
|
3040
3049
|
authorization: ownerAuthorization,
|
|
3041
3050
|
relayProof,
|
|
3042
|
-
compact,
|
|
3043
3051
|
compactMultiaddrLimit: args.compactMultiaddrLimit,
|
|
3044
3052
|
now: args.now,
|
|
3045
3053
|
hasher: args.hasher
|
|
@@ -3062,18 +3070,12 @@ async function publishRelayBootstrapRegistration(args) {
|
|
|
3062
3070
|
let forgottenHashes = [];
|
|
3063
3071
|
let forgetResult;
|
|
3064
3072
|
if (args.forgetPrevious && args.registrationId) {
|
|
3065
|
-
const
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
ref: args.ref,
|
|
3072
|
-
postType: previousPostType,
|
|
3073
|
-
fetch: args.fetch
|
|
3074
|
-
})
|
|
3075
|
-
)
|
|
3076
|
-
)).flat();
|
|
3073
|
+
const previousPosts = await fetchAlephBootstrapPosts({
|
|
3074
|
+
apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
|
|
3075
|
+
channel: args.channel,
|
|
3076
|
+
ref: args.ref,
|
|
3077
|
+
fetch: args.fetch
|
|
3078
|
+
});
|
|
3077
3079
|
const forgottenHashSet = new Set(
|
|
3078
3080
|
previousPosts.filter((post) => {
|
|
3079
3081
|
const hash = post.itemHash ?? post.hash;
|
|
@@ -3675,7 +3677,9 @@ function draftUcanStoreBootstrapErrors(args) {
|
|
|
3675
3677
|
const errors = [];
|
|
3676
3678
|
const { input } = args;
|
|
3677
3679
|
if (!args.operatorAddress) {
|
|
3678
|
-
errors.push(
|
|
3680
|
+
errors.push(
|
|
3681
|
+
"Connect MetaMask before configuring the ucan-store bootstrap package."
|
|
3682
|
+
);
|
|
3679
3683
|
}
|
|
3680
3684
|
if (!input.adminDid.trim().startsWith("did:")) {
|
|
3681
3685
|
errors.push("Admin DID must be a non-empty DID string.");
|
|
@@ -3726,7 +3730,9 @@ function buildUcanStoreBootstrapPackage(args) {
|
|
|
3726
3730
|
serviceDid: args.input.serviceDid.trim() || null,
|
|
3727
3731
|
spaceDid: args.input.spaceDid.trim(),
|
|
3728
3732
|
rootDelegationProof: args.input.rootDelegationProof.trim(),
|
|
3729
|
-
allowedCapabilities: parseAllowedCapabilities(
|
|
3733
|
+
allowedCapabilities: parseAllowedCapabilities(
|
|
3734
|
+
args.input.allowedCapabilities
|
|
3735
|
+
),
|
|
3730
3736
|
defaultUserDelegationExpiration: parseOptionalExpiration(
|
|
3731
3737
|
args.input.defaultUserDelegationExpiration
|
|
3732
3738
|
),
|
|
@@ -3765,7 +3771,9 @@ function defaultState(props = {}) {
|
|
|
3765
3771
|
instanceName: props.instanceName ?? DEFAULT_INSTANCE_NAME,
|
|
3766
3772
|
ucanStoreBootstrap: defaultUcanStoreBootstrapInput(props),
|
|
3767
3773
|
tierId: DEFAULT_TIER_ID,
|
|
3768
|
-
showAdvanced: Boolean(
|
|
3774
|
+
showAdvanced: Boolean(
|
|
3775
|
+
props.manifestJson?.trim() || props.sshPublicKey?.trim()
|
|
3776
|
+
),
|
|
3769
3777
|
showInstances: props.showInstances ?? true,
|
|
3770
3778
|
showPasteManifest: Boolean(props.manifestJson?.trim()),
|
|
3771
3779
|
busy: {
|
|
@@ -4185,7 +4193,9 @@ var SponsorRelayController = class {
|
|
|
4185
4193
|
const profile = bootstrapRelayProfileForManifest(this.state.manifest);
|
|
4186
4194
|
if (!profile && deploymentProfile !== "ucan-store") return;
|
|
4187
4195
|
if (profile && !this.state.wallet.address) {
|
|
4188
|
-
throw new Error(
|
|
4196
|
+
throw new Error(
|
|
4197
|
+
"A connected wallet is required to register relay bootstrap addresses."
|
|
4198
|
+
);
|
|
4189
4199
|
}
|
|
4190
4200
|
const runtimeHostIpv4 = args.runtime.hostIpv4;
|
|
4191
4201
|
if (!runtimeHostIpv4) {
|
|
@@ -4209,7 +4219,9 @@ var SponsorRelayController = class {
|
|
|
4209
4219
|
}
|
|
4210
4220
|
const walletAddress2 = this.state.wallet.address;
|
|
4211
4221
|
if (!walletAddress2) {
|
|
4212
|
-
throw new Error(
|
|
4222
|
+
throw new Error(
|
|
4223
|
+
"A connected wallet is required to configure the ucan-store bootstrap package."
|
|
4224
|
+
);
|
|
4213
4225
|
}
|
|
4214
4226
|
const bootstrapValidation = buildUcanStoreBootstrapPackage({
|
|
4215
4227
|
input: this.state.ucanStoreBootstrap,
|
|
@@ -4324,7 +4336,9 @@ var SponsorRelayController = class {
|
|
|
4324
4336
|
if (!profile) return;
|
|
4325
4337
|
const walletAddress = this.state.wallet.address;
|
|
4326
4338
|
if (!walletAddress) {
|
|
4327
|
-
throw new Error(
|
|
4339
|
+
throw new Error(
|
|
4340
|
+
"A connected wallet is required to register relay bootstrap addresses."
|
|
4341
|
+
);
|
|
4328
4342
|
}
|
|
4329
4343
|
let bootstrapSignalRelayMetadata = null;
|
|
4330
4344
|
if (profile === "orbitdb-relay") {
|
|
@@ -4370,7 +4384,9 @@ var SponsorRelayController = class {
|
|
|
4370
4384
|
const tcpPort = mappedPorts2["9091"]?.host ?? 0;
|
|
4371
4385
|
const wsPort = mappedPorts2["9092"]?.host ?? mappedPorts2["443"]?.host ?? 0;
|
|
4372
4386
|
if (!tcpPort || !wsPort) {
|
|
4373
|
-
throw new Error(
|
|
4387
|
+
throw new Error(
|
|
4388
|
+
"OrbitDB relay runtime is missing required mapped TCP/WS ports."
|
|
4389
|
+
);
|
|
4374
4390
|
}
|
|
4375
4391
|
const configureResult = await configureOrbitdbRelaySetup2({
|
|
4376
4392
|
hostIpv4: runtimeHostIpv4,
|
|
@@ -4393,7 +4409,9 @@ var SponsorRelayController = class {
|
|
|
4393
4409
|
}
|
|
4394
4410
|
} else {
|
|
4395
4411
|
if (!args.deploymentToken) {
|
|
4396
|
-
throw new Error(
|
|
4412
|
+
throw new Error(
|
|
4413
|
+
"Missing deployment token for Aleph bootstrap config handoff."
|
|
4414
|
+
);
|
|
4397
4415
|
}
|
|
4398
4416
|
if (runtime.proxyUrl && runtime.webAccess?.active !== true) {
|
|
4399
4417
|
this.emitProgress({
|
|
@@ -4619,7 +4637,19 @@ var SponsorRelayController = class {
|
|
|
4619
4637
|
});
|
|
4620
4638
|
return;
|
|
4621
4639
|
}
|
|
4622
|
-
throw new Error(
|
|
4640
|
+
throw new Error(
|
|
4641
|
+
"Relay metadata did not include a peer ID and public multiaddrs."
|
|
4642
|
+
);
|
|
4643
|
+
}
|
|
4644
|
+
if (profile === "uc-go-peer") {
|
|
4645
|
+
const browserDialableMultiaddrs = relayMetadata.browserBootstrapMultiaddrs.filter(
|
|
4646
|
+
(multiaddr) => /\/(?:tls\/ws|wss)\/p2p\//.test(multiaddr) || /\/(?:webtransport|webrtc-direct)\//.test(multiaddr) && /\/certhash\//.test(multiaddr)
|
|
4647
|
+
);
|
|
4648
|
+
if (browserDialableMultiaddrs.length === 0) {
|
|
4649
|
+
throw new Error(
|
|
4650
|
+
"Relay metadata did not include a browser-dialable WSS address or a WebTransport/WebRTC Direct address with certhash."
|
|
4651
|
+
);
|
|
4652
|
+
}
|
|
4623
4653
|
}
|
|
4624
4654
|
const { peerId } = relayMetadata;
|
|
4625
4655
|
const registrationId = createRelayBootstrapRegistrationId(
|
|
@@ -5171,18 +5201,10 @@ var SponsorRelayController = class {
|
|
|
5171
5201
|
const [nextBalance, rawInstances, rawBootstrapPosts] = await Promise.all([
|
|
5172
5202
|
this.client.fetchBalance(this.state.wallet.address),
|
|
5173
5203
|
this.state.showInstances ? this.client.fetchInstances(this.state.wallet.address) : Promise.resolve([]),
|
|
5174
|
-
bootstrapEnabled ?
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
].map(
|
|
5179
|
-
(postType) => fetchAlephBootstrapPosts({
|
|
5180
|
-
apiHost: this.client.apiHost,
|
|
5181
|
-
postType,
|
|
5182
|
-
fetch
|
|
5183
|
-
}).catch(() => [])
|
|
5184
|
-
)
|
|
5185
|
-
).then((pages) => pages.flat()) : Promise.resolve([])
|
|
5204
|
+
bootstrapEnabled ? fetchAlephBootstrapPosts({
|
|
5205
|
+
apiHost: this.client.apiHost,
|
|
5206
|
+
fetch
|
|
5207
|
+
}) : Promise.resolve([])
|
|
5186
5208
|
]);
|
|
5187
5209
|
balance = nextBalance;
|
|
5188
5210
|
instances = await Promise.all(
|
|
@@ -5246,7 +5268,9 @@ var SponsorRelayController = class {
|
|
|
5246
5268
|
const activeInstanceHashes = new Set(
|
|
5247
5269
|
instances.map((entry) => entry.instance.item_hash)
|
|
5248
5270
|
);
|
|
5249
|
-
bootstrapRegistrations = selectCurrentRelayBootstrapPosts(
|
|
5271
|
+
bootstrapRegistrations = selectCurrentRelayBootstrapPosts(
|
|
5272
|
+
rawBootstrapPosts
|
|
5273
|
+
).filter(
|
|
5250
5274
|
(entry) => relayBootstrapMatchesCurrentWallet(
|
|
5251
5275
|
entry,
|
|
5252
5276
|
normalizedWalletAddress,
|
|
@@ -5269,7 +5293,9 @@ var SponsorRelayController = class {
|
|
|
5269
5293
|
peerId: entry.content.peerId,
|
|
5270
5294
|
registrationId: entry.content.registrationId,
|
|
5271
5295
|
multiaddrs: Array.isArray(entry.content.multiaddrs) ? entry.content.multiaddrs : [],
|
|
5272
|
-
browserMultiaddrs: Array.isArray(
|
|
5296
|
+
browserMultiaddrs: Array.isArray(
|
|
5297
|
+
entry.content.browserMultiaddrs
|
|
5298
|
+
) ? entry.content.browserMultiaddrs : [],
|
|
5273
5299
|
ownerAddress: typeof entry.content.ownerAddress === "string" ? entry.content.ownerAddress : void 0,
|
|
5274
5300
|
publisherAddress: typeof entry.content.publisherAddress === "string" ? entry.content.publisherAddress : void 0,
|
|
5275
5301
|
updatedAt: entry.content.updatedAt
|
|
@@ -5390,7 +5416,9 @@ var SponsorRelayController = class {
|
|
|
5390
5416
|
...compatibleCrns2.filter((crn) => crn.hash !== preferredCrnHash)
|
|
5391
5417
|
].slice(0, 5);
|
|
5392
5418
|
if (orderedCrns.length === 0) {
|
|
5393
|
-
throw new Error(
|
|
5419
|
+
throw new Error(
|
|
5420
|
+
"No compatible CRN is currently available for this tier."
|
|
5421
|
+
);
|
|
5394
5422
|
}
|
|
5395
5423
|
const attemptErrors = [];
|
|
5396
5424
|
let lastError = null;
|
|
@@ -5823,7 +5851,7 @@ var SponsorRelayController = class {
|
|
|
5823
5851
|
await forgetAlephMessages({
|
|
5824
5852
|
sender: this.state.wallet.address,
|
|
5825
5853
|
hashes: [attemptItemHash],
|
|
5826
|
-
reason: `Discard failed
|
|
5854
|
+
reason: `Discard failed Relay Button deployment attempt on ${attemptLabel}`,
|
|
5827
5855
|
signer: personalSign,
|
|
5828
5856
|
hasher: sha256Hex,
|
|
5829
5857
|
fetch: (url, init) => fetch(url, init).then(async (response) => ({
|
|
@@ -5933,7 +5961,7 @@ var SponsorRelayController = class {
|
|
|
5933
5961
|
await forgetAlephMessages({
|
|
5934
5962
|
sender: this.state.wallet.address,
|
|
5935
5963
|
hashes: hashesToForget,
|
|
5936
|
-
reason: linkedRegistrationCount > 0 ? `Deleted instance and ${linkedRegistrationCount} linked relay bootstrap registration${linkedRegistrationCount === 1 ? "" : "s"} from
|
|
5964
|
+
reason: linkedRegistrationCount > 0 ? `Deleted instance and ${linkedRegistrationCount} linked relay bootstrap registration${linkedRegistrationCount === 1 ? "" : "s"} from Relay Button panel` : "Deleted from Relay Button panel",
|
|
5937
5965
|
signer: personalSign,
|
|
5938
5966
|
hasher: sha256Hex,
|
|
5939
5967
|
fetch: asJsonFetch,
|
|
@@ -6002,7 +6030,7 @@ var SponsorRelayController = class {
|
|
|
6002
6030
|
await forgetAlephMessages({
|
|
6003
6031
|
sender: this.state.wallet.address,
|
|
6004
6032
|
hashes: [registrationHash],
|
|
6005
|
-
reason: "Deleted orphan relay bootstrap registration from
|
|
6033
|
+
reason: "Deleted orphan relay bootstrap registration from Relay Button panel",
|
|
6006
6034
|
signer: personalSign,
|
|
6007
6035
|
hasher: sha256Hex,
|
|
6008
6036
|
fetch: asJsonFetch,
|
|
@@ -51,7 +51,7 @@ export let apiHosts = undefined
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
function deploymentTitle() {
|
|
54
|
-
return deploymentProfile() === 'ucan-store' ? '
|
|
54
|
+
return deploymentProfile() === 'ucan-store' ? 'Service Button' : 'Relay Button'
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
function deploymentInstanceFallbackLabel() {
|