diff --git a/src/App.svelte b/src/App.svelte
index 85db48e77..42c827b35 100644
--- a/src/App.svelte
+++ b/src/App.svelte
@@ -8,6 +8,7 @@
import Registrations from '@app/base/registrations/Routes.svelte';
import Orgs from '@app/base/orgs/Routes.svelte';
import Users from '@app/base/users/Routes.svelte';
+ import Seeds from '@app/base/seeds/Routes.svelte';
import Faucet from '@app/base/faucet/Routes.svelte';
import Projects from '@app/base/projects/Routes.svelte';
import Resolver from '@app/base/resolver/Routes.svelte';
@@ -83,6 +84,7 @@
+
diff --git a/src/api.ts b/src/api.ts
index 8e1689a8a..443fbb339 100644
--- a/src/api.ts
+++ b/src/api.ts
@@ -17,7 +17,13 @@ export async function get(
const base = config.seed.api.host;
const port = config.seed.api.port;
const search = new URLSearchParams(query).toString();
- const baseUrl = `https://${base}:${port}/v1/${path}`;
+ // Allow using the functionality with local runned http-api
+ const isLocalhost = /^0.0.0.0$/.test(base);
+ const protocol = isLocalhost ? "http://" : "https://";
+
+ const baseUrl = path
+ ? `${protocol}${base}:${port}/v1/${path}`
+ : `${protocol}${base}:${port}`;
const url = search ? `${baseUrl}?${search}` : baseUrl;
let response = null;
diff --git a/src/base/orgs/View.svelte b/src/base/orgs/View.svelte
index 8f78bc198..bfb08c98a 100644
--- a/src/base/orgs/View.svelte
+++ b/src/base/orgs/View.svelte
@@ -275,9 +275,11 @@
{info.meta.description}
- commit {formatCommit(project.anchor.stateHash)}
- commit {project.anchor.stateHash}
+
+
+
{#each info.meta.maintainers as urn}
@@ -147,11 +148,11 @@
{/if}
- commit {formatCommit(project.anchor.stateHash)}
- commit {project.anchor.stateHash}
+
+
+
-
-
+
{/if}
diff --git a/src/base/registrations/registrar.ts b/src/base/registrations/registrar.ts
index 2a3de90c5..6ed987ce5 100644
--- a/src/base/registrations/registrar.ts
+++ b/src/base/registrations/registrar.ts
@@ -6,35 +6,15 @@ import type { TypedDataSigner } from '@ethersproject/abstract-signer';
import * as session from '@app/session';
import { Failure } from '@app/error';
import type { Config } from '@app/config';
-import { isDomain, unixTime } from '@app/utils';
+import { unixTime } from '@app/utils';
import { assert } from '@app/error';
+import { Seed } from '@app/base/seeds/Seed';
export interface Registration {
profile: EnsProfile;
resolver: EnsResolver;
}
-export class Seed {
- id?: string;
- host?: string;
- git?: string;
- api?: string;
-
- constructor(id?: string, host?: string, git?: string, api?: string) {
- if (id && /^[a-z0-9]+$/.test(id)) {
- this.id = id;
- }
- if (host && isDomain(host)) {
- this.host = host;
- }
- if (api && isDomain(api)) {
- this.api = api;
- }
- if (git && isDomain(git)) {
- this.git = git;
- }
- }
-}
export interface EnsProfile {
name: string;
@@ -113,8 +93,9 @@ export async function getRegistration(name: string, config: Config, resolver?: E
url,
avatar,
seed: new Seed(
- seedId,
+ config,
seedHost,
+ seedId,
seedGit,
seedApi,
),
@@ -161,7 +142,7 @@ export async function getSeed(name: string, config: Config, resolver?: EnsResolv
resolver.getText('eth.radicle.seed.api'),
]);
- return new Seed(id, host, git, api);
+ return new Seed(config, host, id, git, api);
}
export function registrar(config: Config): ethers.Contract {
diff --git a/src/base/seeds/Routes.svelte b/src/base/seeds/Routes.svelte
new file mode 100644
index 000000000..38e4a54ab
--- /dev/null
+++ b/src/base/seeds/Routes.svelte
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/src/base/seeds/Seed.ts b/src/base/seeds/Seed.ts
new file mode 100644
index 000000000..c43e301ca
--- /dev/null
+++ b/src/base/seeds/Seed.ts
@@ -0,0 +1,46 @@
+import * as api from '@app/api';
+import type { Config } from '@app/config';
+import { getInfo, getProjects } from '@app/project';
+import type { Info, Project } from "@app/project";
+import { isDomain } from '@app/utils';
+
+export interface SeedInfo {
+ version: string;
+}
+
+export class Seed {
+ host?: string;
+ id?: string;
+ git?: string;
+ api?: string;
+ config: Config;
+
+ constructor(config: Config, host?: string, id?: string, git?: string, api?: string) {
+ if (id && /^[a-z0-9]+$/.test(id)) {
+ this.id = id;
+ }
+ if (host && isDomain(host)) {
+ this.host = host;
+ }
+ if (api && isDomain(api)) {
+ this.api = api;
+ }
+ if (git && isDomain(git)) {
+ this.git = git;
+ }
+ this.config = config.withSeed(this);
+ }
+ async getInfo(): Promise {
+ return api.get(``, {}, this.config);
+ }
+ async getPeer(): Promise<{ id: string }> {
+ return api.get("peer", {}, this.config);
+ }
+ async getProject(urn: string): Promise {
+ return getInfo(urn, this.config);
+ }
+ async getProjects(): Promise {
+ const result = await getProjects(this.config);
+ return result.map((project: any) => ({ ...project, id: project.urn }));
+ }
+}
diff --git a/src/base/seeds/View.svelte b/src/base/seeds/View.svelte
new file mode 100644
index 000000000..5cef0392b
--- /dev/null
+++ b/src/base/seeds/View.svelte
@@ -0,0 +1,169 @@
+
+
+
+
+
+ {seed.host}
+
+
+{#await seed.getInfo()}
+
+
+
+{:then info}
+
+
+
+
+
+ {seed.host}
+
+
+
+
+
+
+
+
Seed
+ {#if info.version === "0.2.0" && seed.host}
+ {#await seed.getPeer() then peer}
+
+
+
+
+ 🌱
+ {utils.formatSeedId(peer.id)}@{seed.host}
+ :{seed.config.seed.link.port}
+
+
+
+
+ {/await}
+ {:else}
+
N/A
+
+ {/if}
+
+
API Port
+
{seed.config.seed.api.port}
+
+
+
Version
+
{info.version}
+
+
+
+ {#if info.version === "0.2.0"}
+ {#await seed.getProjects() then projects}
+
+ {#each projects as project}
+
+
+
+ {/each}
+
+ {/await}
+ {:else}
+ For seed project listing, update http-api to v0.2.0
+ {/if}
+
+{/await}
diff --git a/src/config.ts b/src/config.ts
index e42ae1ec0..38594fcf2 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -7,7 +7,7 @@ import { Core } from '@self.id/core';
import WalletConnect from "@walletconnect/client";
import config from "@app/config.json";
import { WalletConnectSigner } from "./WalletConnectSigner";
-import type { Seed } from "@app/base/registrations/registrar";
+import type { Seed } from '@app/base/seeds/Seed';
declare global {
interface Window {
diff --git a/src/profile.ts b/src/profile.ts
index 4800438b2..fcf8f4a4d 100644
--- a/src/profile.ts
+++ b/src/profile.ts
@@ -1,9 +1,10 @@
-import type { EnsProfile, Seed } from "@app/base/registrations/registrar";
+import type { EnsProfile } from "@app/base/registrations/registrar";
import type { BasicProfile } from '@datamodels/identity-profile-basic';
import {
isAddress, formatCAIP10Address, formatIpfsFile, resolveEnsProfile, resolveIdxProfile, parseUsername, parseEnsLabel
} from "@app/utils";
import type { Config } from "@app/config";
+import type { Seed } from "@app/base/seeds/Seed";
export interface IProfile {
address: string;
diff --git a/src/project.ts b/src/project.ts
index b887939ea..8343cdb97 100644
--- a/src/project.ts
+++ b/src/project.ts
@@ -82,6 +82,10 @@ export async function getInfo(urn: string, config: Config): Promise {
return api.get(`projects/${urn}`, {}, config);
}
+export async function getProjects(config: Config): Promise {
+ return api.get("projects", {}, config);
+}
+
export async function getTree(
urn: string,
commit: string,
diff --git a/src/utils.ts b/src/utils.ts
index c43847baa..c4312e2ab 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -417,8 +417,10 @@ export function isMarkdownPath(path: string): boolean {
}
// Check whether the given input string is a domain, eg. `alt-clients.radicle.xyz.
+// Also accepts in dev env 0.0.0.0 as domain
export function isDomain(input: string): boolean {
- return /^[a-z][a-z0-9.-]+$/.test(input) && /\.[a-z]+$/.test(input);
+ return (/^[a-z][a-z0-9.-]+$/.test(input) && /\.[a-z]+$/.test(input))
+ || (!import.meta.env.PROD && /^0.0.0.0$/.test(input)) ;
}
// Propose a Gnosis Safe multi-sig transaction.