Radish alpha
r
Radicle web interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Migrate to host/id based seed node records
Alexis Sellier committed 4 years ago
commit 75983dc98ee0654f9af2aed7e08119527cfa4a3a
parent f7511a9e17144b869a01d8d2eb8928057098f9f9
10 files changed +33 -36
modified src/Form.svelte
@@ -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>

modified src/api.ts
@@ -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;
modified src/base/projects/Browser.svelte
@@ -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">
modified src/base/registrations/View.svelte
@@ -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 {
modified src/base/registrations/registrar.ts
@@ -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 {
modified src/base/registrations/resolver.ts
@@ -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])
        );
modified src/config.json
@@ -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": [
modified src/config.ts
@@ -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;
  }
modified src/profile.ts
@@ -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,
modified src/utils.ts
@@ -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,
      };