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 @@
- 🌱{ - utils.formatSeedId(profile.seedId)}@{profile.seedHost - }:{config.seed.link.port} + 🌱 + + {utils.formatSeedId(profile.seedId)}@{profile.seedHost} + + :{config.seed.link.port}
{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.