Migrate to host/id based seed node records

Instead of having one record per service, we configure the host
and expect services to run on certain ports.
This commit is contained in:
Alexis Sellier
2021-09-14 15:08:13 +02:00
parent f7511a9e17
commit 75983dc98e
10 changed files with 33 additions and 36 deletions
+4 -1
View File
@@ -23,7 +23,10 @@
// Maximum is 15 characters.
// For simplification of the regex pattern we use a combined version of both requirements.
handle: /^[a-zA-Z0-9-_]{1,39}$/,
address: /^0x[a-zA-Z0-9]{40}$/
address: /^0x[a-zA-Z0-9]{40}$/,
id: /^[a-z0-9]+$/,
// Just make sure there is a TLD at the end.
domain: /\.[a-z]{2,}$/,
};
</script>
+5 -4
View File
@@ -5,8 +5,8 @@ export async function get(
params: Record<string, any>,
config: Config
): Promise<any> {
if (! config.seed.api) {
throw new Error("Seed HTTP API unavailable");
if (! config.seed.host) {
throw new Error("Seed host unavailable");
}
const query: Record<string, string> = {};
@@ -14,9 +14,10 @@ export async function get(
query[key] = val.toString();
}
const base = config.seed.api.replace(/\/$/, "");
const base = config.seed.host;
const port = config.seed.port;
const search = new URLSearchParams(query).toString();
const baseUrl = `${base}/v1/${path}`;
const baseUrl = `https://${base}:${port}/v1/${path}`;
const url = search ? `${baseUrl}?${search}` : baseUrl;
let response = null;
+2 -2
View File
@@ -188,9 +188,9 @@
<div class="stat">
<strong>{tree.stats.contributors}</strong> contributor(s)
</div>
{#if config.seed.api}
{#if config.seed.host}
<div class="stat" title="Project data is fetched from this seed">
<span>{utils.formatSeedApi(config.seed.api)}</span>
<span>{config.seed.host}</span>
</div>
{/if}
<div class="anchor">
+7 -5
View File
@@ -75,12 +75,14 @@
{ name: "github", validate: "handle", label: "GitHub", placeholder: "GitHub username, eg. 'acme'",
description: "The GitHub username associated with this name.",
value: r.profile.github, editable: true },
{ name: "seed.id", label: "Seed ID", placeholder: "hynkyn...3nrzc@seed.acme.org:8887",
description: "The ID of a Radicle Link node that hosts entities associated with this name.",
{ name: "seed.host", label: "Seed Host", validate: "domain", placeholder: "seed.acme.org",
description: "The seed host address. " +
"Only domain names with TLS are supported. " +
`HTTP(S) API requests use port ${config.seed.port}.`,
value: r.profile.seedHost, editable: true },
{ name: "seed.id", label: "Seed ID", validate: "id", placeholder: "hynkyndc6w3p8urucakobzncqny7xxtw88...",
description: "The Device ID of a Radicle Link node that hosts entities associated with this name.",
value: r.profile.seedId, editable: true },
{ name: "seed.api", label: "Seed API", validate: "url", placeholder: "https://seed.acme.org:8888",
description: "The HTTP address of a node that serves Radicle entities over HTTP.",
value: r.profile.seedApi, editable: true },
];
state = { status: Status.Found, registration: r };
} else {
+5 -5
View File
@@ -20,7 +20,7 @@ export interface EnsProfile {
owner?: string;
address: string | null;
seedId: string | null;
seedApi: string | null;
seedHost: string | null;
url: string | null;
avatar: string | null;
twitter: string | null;
@@ -72,12 +72,12 @@ export async function getRegistration(name: string, config: Config): Promise<Reg
resolver.getText('avatar'),
resolver.getText('url'),
resolver.getText('eth.radicle.seed.id'),
resolver.getText('eth.radicle.seed.api'),
resolver.getText('eth.radicle.seed.host'),
resolver.getText('com.twitter'),
resolver.getText('com.github'),
]);
const [address, avatar, url, seedId, seedApi, twitter, github] =
const [address, avatar, url, seedId, seedHost, twitter, github] =
meta.map(r => r.status == "fulfilled" ? r.value : null);
return {
@@ -88,7 +88,7 @@ export async function getRegistration(name: string, config: Config): Promise<Reg
url,
avatar,
seedId,
seedApi,
seedHost,
address,
twitter,
github,
@@ -113,7 +113,7 @@ export async function getSeed(name: string, config: Config): Promise<string | nu
if (! resolver) {
return null;
}
return resolver.getText('eth.radicle.seed.api');
return resolver.getText('eth.radicle.seed.host');
}
export function registrar(config: Config): ethers.Contract {
+1 -1
View File
@@ -35,7 +35,7 @@ export async function setRecords(name: string, records: EnsRecord[], resolver: E
);
break;
case "seed.id":
case "seed.api":
case "seed.host":
calls.push(
iface.encodeFunctionData("setText", [node, "eth.radicle." + r.name, r.value])
);
+1 -1
View File
@@ -50,7 +50,7 @@
},
"walletConnect": { "bridge": "https://radicle.bridge.walletconnect.org" },
"ceramic": { "api": "https://gateway.ceramic.network" },
"radicle": { "api": "http://0.0.0.0:8888" },
"radicle": { "seed": { "host": "0.0.0.0", "port": 8777 } },
"ipfs": { "gateway": "https://ipfs.io/ipfs/" },
"abi": {
"registrar": [
+4 -5
View File
@@ -55,7 +55,7 @@ export class Config {
viewer: string | null;
};
abi: { [contract: string]: string[] };
seed: { api?: string };
seed: { host?: string; port: number };
idx: { client: IDX };
ceramic: { client: CeramicClient };
tokens: string[];
@@ -66,7 +66,6 @@ export class Config {
provider: ethers.providers.JsonRpcProvider,
metamaskSigner: ethers.Signer & TypedDataSigner | null,
) {
const api = config.radicle.api;
const cfg = (<Record<string, any>> config)[network.name];
const ceramic = new CeramicClient(config.ceramic.api);
const idx = new IDX({ ceramic });
@@ -97,7 +96,7 @@ export class Config {
signer: wc.signer,
state: walletConnectState,
};
this.seed = { api };
this.seed = config.radicle.seed;
this.registrar = cfg.registrar;
this.radToken = cfg.radToken;
this.orgFactory = cfg.orgFactory;
@@ -126,10 +125,10 @@ export class Config {
}
// Return the config with an overwritten seed URL.
withSeed(seed: string): Config {
withSeed(seedHost: string): Config {
const cfg = {} as Config;
Object.assign(cfg, this);
cfg.seed.api = seed.replace(/\/$/, "");
cfg.seed.host = seedHost;
return cfg;
}
+1 -1
View File
@@ -73,7 +73,7 @@ export class Profile {
// Using undefined as return type if nothing to be returned since it works better with <a href> links
get seed(): string | undefined {
return this.profile?.ens?.seedApi ?? undefined;
return this.profile?.ens?.seedHost ?? undefined;
}
// Return the profile-specific config. This sets various URLs in the config,
+3 -11
View File
@@ -63,14 +63,6 @@ export function formatHash(hash: string): string {
+ hash.substring(hash.length - 4, hash.length);
}
export function formatSeedApi(input: string): string {
const match = input.match(/^https?:\/\/([^:]+)/);
if (match) {
return match[1];
}
return input;
}
export function formatNetwork(input: { name: string }): string {
let name = input.name;
@@ -256,13 +248,13 @@ export async function resolveEnsProfile(address: string, profileType: ProfileTyp
}
} else if (profileType === ProfileType.Project) {
const avatar = await getAvatar(name, config);
const seedApi = await getSeed(name, config);
const seedHost = await getSeed(name, config);
return {
name,
address,
avatar,
seedApi,
seedHost,
url: null,
seedId: null,
twitter: null,
@@ -277,7 +269,7 @@ export async function resolveEnsProfile(address: string, profileType: ProfileTyp
avatar,
url: null,
seedId: null,
seedApi: null,
seedHost: null,
twitter: null,
github: null,
};