diff --git a/src/App.svelte b/src/App.svelte index cfe01422a..3742210b7 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -6,8 +6,6 @@ import Home from "@app/base/home/Index.svelte"; import Vesting from "@app/base/vesting/Index.svelte"; 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"; @@ -92,10 +90,8 @@ - - diff --git a/src/Card.svelte b/src/Card.svelte deleted file mode 100644 index 62bd94b2d..000000000 --- a/src/Card.svelte +++ /dev/null @@ -1,113 +0,0 @@ - - - - - -
-
- {#if profile} - - {:else if seed} - - {seed.emoji} - - {/if} -
-
- {#if profile} - {#if profile.name} - {formatName(profile.name, config)} - {:else} - {formatAddress(profile.address)} - {/if} - {:else if seed} - {seed.host} - {/if} -
-
- {#if profile} - {#if members.length > 0} - {members.length} member(s) - {:else} - {formatAddress(profile.address)} - {/if} - {/if} -
-
- diff --git a/src/Cards.svelte b/src/Cards.svelte deleted file mode 100644 index c6dae9b4f..000000000 --- a/src/Cards.svelte +++ /dev/null @@ -1,71 +0,0 @@ - - - - -
- {#each orgs as org} - {#await Profile.get(org.name ?? org.address, ProfileType.Minimal, config)} - - {:then profile} - {#if orgMembers[profile.address]?.length} - - {:else} - - {/if} - {/await} - {/each} - - {#each profiles as profile} - - {/each} - - {#each seeds as seed} - - {/each} - - {#if !orgs.length && !profiles.length && !seeds.length} - - {/if} -
diff --git a/src/Options.svelte b/src/Options.svelte deleted file mode 100644 index 5675d0316..000000000 --- a/src/Options.svelte +++ /dev/null @@ -1,92 +0,0 @@ - - - - -
-
- {#each options as option} - - {#if option.description} -
- {@html marked(option.description.join("\n"))} -
- {/if} - {/each} -
-
diff --git a/src/Profile.svelte b/src/Profile.svelte index fe875afa1..ecf06483f 100644 --- a/src/Profile.svelte +++ b/src/Profile.svelte @@ -6,7 +6,7 @@ import Icon from "@app/Icon.svelte"; import SetName from "@app/ens/SetName.svelte"; import SeedAddress from "@app/SeedAddress.svelte"; - import TransferOwnership from "@app/base/orgs/TransferOwnership.svelte"; + import TransferOwnership from "@app/components/TransferOwnership.svelte"; import Link from "@app/Link.svelte"; import { getBalance, Profile, ProfileType } from "@app/profile"; import Loading from "@app/Loading.svelte"; @@ -16,7 +16,7 @@ import Message from "@app/Message.svelte"; import Error from "@app/Error.svelte"; import { User } from "@app/base/users/User"; - import Projects from "@app/base/orgs/View/Projects.svelte"; + import Projects from "@app/base/seeds/View/Projects.svelte"; import { MissingReverseRecord, NotFoundError } from "@app/error"; import NotFound from "@app/NotFound.svelte"; import RadicleUrn from "@app/RadicleUrn.svelte"; @@ -448,12 +448,7 @@ {/if} {#if profile.seed?.valid} - + {/if} diff --git a/src/anchors.ts b/src/anchors.ts deleted file mode 100644 index 71b21cda1..000000000 --- a/src/anchors.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { ethers } from "ethers"; -import type { Config } from "./config"; -import { decodeRadicleId, formatProjectHash, querySubgraph } from "@app/utils"; - -const GetAllAnchors = ` - query GetAllAnchors($project: Bytes!, $org: ID!) { - anchors(orderBy: timestamp, orderDirection: desc, where: { objectId: $project, org: $org }) { - multihash - timestamp - } - } -`; - -interface AnchorObject { - timestamp: number; - multihash: string; -} - -export async function getProjectAnchors( - urn: string, - anchorsStorage: string, - config: Config, -): Promise { - const unpadded = decodeRadicleId(urn); - const id = ethers.utils.hexZeroPad(unpadded, 32); - const allAnchors = await querySubgraph(config.orgs.subgraph, GetAllAnchors, { - project: id, - org: anchorsStorage, - }); - - return allAnchors.anchors.map((anchor: AnchorObject) => - formatProjectHash(ethers.utils.arrayify(anchor.multihash)), - ); -} diff --git a/src/base/orgs/Create.svelte b/src/base/orgs/Create.svelte deleted file mode 100644 index 07410b917..000000000 --- a/src/base/orgs/Create.svelte +++ /dev/null @@ -1,225 +0,0 @@ - - - - -{#if error} - -{:else if org} - - - 🎉 - - - Your org was successfully created. - - - -
- Address -
- - Owner -
-
-
- - - - -
-{:else} - - - -
🎪
- Create an Org -
- - - {#if state === State.Idle} -
Select how you'd like to create your org
- {:else if state === State.Signing} -
- Please confirm the transaction in your wallet. -
- {:else if state === State.Pending} -
Waiting for transaction to be processed...
- {/if} -
- - - {#if state === State.Idle} -
-
- Notice: - Orgs V1 are being deprecated. It is recommended not to create new orgs - at this point. -
- -
- -
- - - -
- {:else} - - {/if} -
- - - {#if state === State.Idle} - - - - {/if} - -
-{/if} diff --git a/src/base/orgs/Index.svelte b/src/base/orgs/Index.svelte deleted file mode 100644 index fb40eba0e..000000000 --- a/src/base/orgs/Index.svelte +++ /dev/null @@ -1,122 +0,0 @@ - - - - - - Radicle: Orgs - - -
- {#if account} -
-
- - My Orgs - - -
- - {#await Org.getOrgsByMember(account, config)} -
- -
- {:then orgs} - -
- Orgs you are a member of show up here. -
-
- {:catch} -
- - Error: - failed to load orgs. - -
- {/await} -
- {/if} - -
- - Orgs - of the Radicle network - -
- - {#await Org.getAll(config)} -
- -
- {:then orgs} - -
There are no orgs.
-
- {:catch} -
- - Error: - failed to load orgs. - -
- {/await} -
- - (modal = null)} /> diff --git a/src/base/orgs/Org.ts b/src/base/orgs/Org.ts index 0bd8481b5..e8c7b0910 100644 --- a/src/base/orgs/Org.ts +++ b/src/base/orgs/Org.ts @@ -1,37 +1,12 @@ import * as ethers from "ethers"; import type { TransactionResponse } from "@ethersproject/providers"; -import type { ContractReceipt } from "@ethersproject/contracts"; import { OperationType } from "@gnosis.pm/safe-core-sdk-types"; import { assert } from "@app/error"; import * as utils from "@app/utils"; import * as cache from "@app/cache"; -import type { SafeMultisigTransactionListResponse } from "@gnosis.pm/safe-service-client"; -import type SafeServiceClient from "@gnosis.pm/safe-service-client"; import type { Safe } from "@app/utils"; import type { Config } from "@app/config"; -import type { PendingAnchor, Anchor } from "@app/project"; - -const GetProjects = ` - query GetProjects($org: ID!) { - projects(where: { org: $org }) { - anchor { - objectId - multihash - timestamp - } - } - } -`; - -const GetOrgs = ` - query GetOrgs { - orgs { - id - owner - } - } -`; const GetSafesByOwners = ` query GetSafesByOwners($owners: [String!]!) { @@ -198,119 +173,6 @@ export class Org { return members.includes(address.toLowerCase()); } - async getProjects(config: Config): Promise { - const result = await utils.querySubgraph( - config.orgs.subgraph, - GetProjects, - { org: this.address }, - ); - const projects: Anchor[] = []; - - for (const p of result.projects) { - try { - const proj: Anchor = { - confirmed: true, - id: utils.formatRadicleId(ethers.utils.arrayify(p.anchor.objectId)), - anchor: { - stateHash: utils.formatProjectHash( - ethers.utils.arrayify(p.anchor.multihash), - ), - }, - }; - projects.push(proj); - } catch (e) { - console.error(e); - } - } - return projects; - } - - async getPendingProjects(config: Config): Promise { - if (!config.safe.client) return []; - - try { - const orgAddr = ethers.utils.getAddress(this.address); - const response = await getPendingProjects( - ethers.utils.getAddress(this.owner), - config.safe.client, - ); - const projects: PendingAnchor[] = []; - - for (const tx of response.results || []) { - if (tx.data && tx.to === orgAddr) { - const anchor = parseAnchorTx(tx.data, config); - const confirmations = tx.confirmations?.map(t => t.owner) || []; - - if (anchor) { - projects.push({ - id: anchor.id, - anchor: { stateHash: anchor.stateHash }, - confirmations, - safeTxHash: tx.safeTxHash, - confirmed: false, - }); - } - } - } - return projects; - } catch { - return []; - } - } - - static async getAnchor( - orgAddr: string, - urn: string, - config: Config, - ): Promise { - const org = new ethers.Contract(orgAddr, config.abi.org, config.provider); - const unpadded = utils.decodeRadicleId(urn); - const id = ethers.utils.zeroPad(unpadded, 32); - - try { - const [, hash] = await org.anchors(id); - const anchor = utils.formatProjectHash(ethers.utils.arrayify(hash)); - - return anchor; - } catch (e) { - console.error(e); - return null; - } - } - - static async getMulti(ids: string[], config: Config): Promise> { - const results = await Promise.all(ids.map(addr => Org.get(addr, config))); - const orgs = results.filter((org): org is Org => org !== null); - - return orgs; - } - - static async getAll(config: Config): Promise> { - const result = await utils.querySubgraph(config.orgs.subgraph, GetOrgs, {}); - const orgs: Org[] = []; - - for (const o of result.orgs) { - try { - orgs.push(new Org(o.id, o.owner)); - } catch (e) { - console.error(e); - } - } - return orgs; - } - - static fromReceipt(receipt: ContractReceipt): Org | null { - const event = receipt.events?.find(e => e.event === "OrgCreated"); - - if (event && event.args) { - const address = event.args[0]; - const owner = event.args[1]; - - return new Org(address, owner); - } - return null; - } - static async get(addressOrName: string, config: Config): Promise { const org = await getOrgContract(addressOrName, config); @@ -354,62 +216,6 @@ export class Org { return orgs.map(o => new Org(o.id, o.owner)); } - - static async createMultiSig( - owners: [string], - threshold: number, - config: Config, - ): Promise { - assert(config.signer); - - const orgFactory = new ethers.Contract( - config.orgFactory.address, - config.abi.orgFactory, - config.signer, - ); - - return orgFactory["createOrg(address[],uint256)"](owners, threshold, { - gasLimit: config.gasLimits.createOrg, - }); - } - - static async create( - owner: string, - config: Config, - ): Promise { - assert(config.signer); - - const orgFactory = new ethers.Contract( - config.orgFactory.address, - config.abi.orgFactory, - config.signer, - ); - - return orgFactory["createOrg(address)"](owner, { - gasLimit: config.gasLimits.createOrg, - }); - } -} - -export function parseAnchorTx( - data: string, - config: Config, -): { id: string; stateHash: string } | null { - const iface = new ethers.utils.Interface(config.abi.org); - const parsedTx = iface.parseTransaction({ data }); - - if (parsedTx.name === "anchor") { - const encodedProjectUrn = parsedTx.args[0]; - const encodedCommitHash = parsedTx.args[2]; - const id = utils.formatRadicleId( - ethers.utils.arrayify(`${encodedProjectUrn}`), - ); - const byteArray = ethers.utils.arrayify(encodedCommitHash); - const stateHash = utils.formatProjectHash(byteArray); - - return { id, stateHash }; - } - return null; } export const getOrgContract = cache.cached( @@ -425,20 +231,3 @@ export const resolveOrgOwner = cache.cached( }, org => org.address, ); - -export const getPendingProjects = cache.cached( - async ( - owner: string, - client: SafeServiceClient, - ): Promise => { - try { - return await client.getPendingTransactions( - ethers.utils.getAddress(owner), - ); - } catch (e) { - return { count: 0, results: [] }; - } - }, - owner => owner, - { max: 1000, ttl: 5 * 60 * 1000 }, // Cache results for 5 minutes. -); diff --git a/src/base/orgs/Routes.svelte b/src/base/orgs/Routes.svelte deleted file mode 100644 index 7ddfc79e1..000000000 --- a/src/base/orgs/Routes.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - diff --git a/src/base/profiles/AnchorActions.svelte b/src/base/profiles/AnchorActions.svelte deleted file mode 100644 index 354a67506..000000000 --- a/src/base/profiles/AnchorActions.svelte +++ /dev/null @@ -1,267 +0,0 @@ - - - - - - {#if pending > 0} - {pending} - signature(s) pending - {/if} - - -
- {#each anchor.confirmations as signee} - - {/each} -
- - -{#if pending <= 0} - - -{:else if isSigned} - ✓ signed -{:else} - -{/if} - - -{#if state !== State.Idle && action === Action.Sign} - - -
⚓
-
Anchor project
-
- - - {#if state === State.Confirm} - Initiate the transaction... - {:else if state === State.Signing} - Sign the transaction in your wallet... - {:else if state === State.Submitting} - Transaction is being confirmed... - {:else if state === State.Success} - Transaction confirmed. - {:else if state === State.Failed} - Transaction failed - {/if} - - - - {#if state === State.Confirm} -
-
Project
- {anchor.id} -
Hash
- {anchor.anchor.stateHash} -
- {:else if state === State.Failed} -
{error}
- {/if} -
- - - {#if state === State.Confirm} - - - {:else if state === State.Success || state === State.Failed} - - {/if} - -
-{:else if state !== State.Idle && action === Action.Execute} - - -
⚡
-
Execute Safe Transaction
-
- - - {#if state === State.Confirm} - Initiate the transaction... - {:else if state === State.Signing} - Sign the transaction in your wallet... - {:else if state === State.Submitting} - Transaction is being confirmed... - {:else if state === State.Success} - Transaction confirmed. - {:else if state === State.Failed} - Transaction failed - {/if} - - - - {#if state === State.Confirm} -
-
TxHash
- - {utils.formatHash(anchor.safeTxHash)} - -
Quorum
- - {anchor.confirmations.length} of {safe.threshold} - -
- {:else if state === State.Failed} -
{error}
- {/if} -
- - - {#if state === State.Confirm} - - - {:else if state === State.Success || state === State.Failed} - - {/if} - -
-{/if} diff --git a/src/base/profiles/AnchorBadge.svelte b/src/base/profiles/AnchorBadge.svelte deleted file mode 100644 index f48c683f4..000000000 --- a/src/base/profiles/AnchorBadge.svelte +++ /dev/null @@ -1,93 +0,0 @@ - - - - -{#if anchors && head} - - {#if commit === anchors[0] && commit === head} - - - {#if text}latest {/if}🔐 - - - - {:else if commit === anchors[0] && commit !== head} - dispatch("click", head)}> - - {#if text}latest {/if}🔐 - - - - {:else if anchors.includes(commit)} - dispatch("click", anchors[0])}> - - {#if text}stale {/if}🔒 - - - - {:else} - dispatch("click", anchors[0])}> - - {#if text}not anchored {/if}🔓 - - - {/if} -{:else} - - - - {#if text}not anchored {/if}🔓 - - -{/if} diff --git a/src/base/projects/Header.svelte b/src/base/projects/Header.svelte index 1090add32..ea7f1ae82 100644 --- a/src/base/projects/Header.svelte +++ b/src/base/projects/Header.svelte @@ -2,7 +2,6 @@ import type { Writable } from "svelte/store"; import { navigate } from "svelte-routing"; import { Browser, ProjectContent, Project } from "@app/project"; - import AnchorBadge from "@app/base/profiles/AnchorBadge.svelte"; import BranchSelector from "@app/base/projects/BranchSelector.svelte"; import CloneButton from "@app/base/projects/CloneButton.svelte"; import PeerSelector from "@app/base/projects/PeerSelector.svelte"; @@ -12,9 +11,8 @@ export let tree: Tree; export let commit: string; export let browserStore: Writable; - export let noAnchor = false; - const { urn, peers, branches, seed, anchors } = project; + const { urn, peers, branches, seed } = project; $: browser = $browserStore; $: revision = browser.revision || commit; @@ -54,9 +52,6 @@ border-radius: var(--border-radius-small); min-width: max-content; } - .anchor { - display: inline-flex; - } .clickable { cursor: pointer; } @@ -104,16 +99,6 @@ {revision} on:branchChanged={event => updateRevision(event.detail)} /> - {#if !noAnchor} -
- updateRevision(event.detail)} /> -
- {/if} - {#if seed.git.host} {/if} diff --git a/src/base/projects/Project.svelte b/src/base/projects/Project.svelte index 649f2a94e..f56c3dc9f 100644 --- a/src/base/projects/Project.svelte +++ b/src/base/projects/Project.svelte @@ -74,7 +74,7 @@ {#await project.getRoot(revision)} {:then { tree, commit }} -
+
{#if content === proj.ProjectContent.Tree} diff --git a/src/base/projects/Widget.svelte b/src/base/projects/Widget.svelte index cd555e159..14316e66c 100644 --- a/src/base/projects/Widget.svelte +++ b/src/base/projects/Widget.svelte @@ -1,6 +1,5 @@
{#each items as project} - {@const anchor = anchors[project.urn]} - {@const pendingAnchor = pendingAnchors[project.urn]} {#if project.head}
- onClick(project)}> - - {#if profile?.org?.safe && account && anchor} - {#if pendingAnchor} - - loadAnchors()} /> - {/if} - {/if} - - + onClick(project)} />
{/if} {/each} diff --git a/src/base/users/Routes.svelte b/src/base/users/Routes.svelte deleted file mode 100644 index c4e68affb..000000000 --- a/src/base/users/Routes.svelte +++ /dev/null @@ -1,8 +0,0 @@ - - - - - diff --git a/src/base/orgs/TransferOwnership.svelte b/src/components/TransferOwnership.svelte similarity index 98% rename from src/base/orgs/TransferOwnership.svelte rename to src/components/TransferOwnership.svelte index 37d17113c..5f41e828b 100644 --- a/src/base/orgs/TransferOwnership.svelte +++ b/src/components/TransferOwnership.svelte @@ -9,7 +9,7 @@ import Address from "@app/Address.svelte"; import Button from "@app/Button.svelte"; - import type { Org } from "./Org"; + import type { Org } from "@app/base/orgs/Org"; const dispatch = createEventDispatcher(); diff --git a/src/profile.ts b/src/profile.ts index 5a4dbac88..25f335eb0 100644 --- a/src/profile.ts +++ b/src/profile.ts @@ -15,8 +15,6 @@ import { cached } from "@app/cache"; import type { Seed, InvalidSeed } from "@app/base/seeds/Seed"; import { Org } from "@app/base/orgs/Org"; import { NotFoundError, MissingReverseRecord } from "@app/error"; -import { getProjectAnchors } from "@app/anchors"; -import type { Anchor, PendingAnchor } from "@app/project"; export interface IProfile { address: string; @@ -153,63 +151,6 @@ export class Profile { } } - // Get confirmed anchors. - async confirmedAnchors(config: Config): Promise> { - const org = await this.getAnchorsOrg(config); - - if (org) { - const result = await org.getProjects(config); - const anchors: Record = {}; - - for (const anchor of result) { - anchors[anchor.id] = anchor; - } - return anchors; - } else { - return {}; - } - } - - // Get pending anchors. - async pendingAnchors(config: Config): Promise> { - const org = await this.getAnchorsOrg(config); - - if (org) { - const result = await org.getPendingProjects(config); - const anchors: Record = {}; - - for (const anchor of result) { - anchors[anchor.id] = anchor; - } - return anchors; - } else { - return {}; - } - } - - async confirmedProjectAnchors( - urn: string, - config: Config, - ): Promise { - const storage = this.anchorsAccount || this.org?.address; - - if (storage) { - return await getProjectAnchors(urn, storage, config); - } - return []; - } - - // Get the anchors account as an org, or the org, if available. - private async getAnchorsOrg(config: Config): Promise { - if (this.anchorsAccount) { - return await Org.get(this.anchorsAccount, config); - } else if (this.org) { - return this.org; - } else { - return null; - } - } - // Keeping this function private since the desired entrypoint is .get() // All addresses returned from this function should be lowercase. private static async lookupProfile( diff --git a/src/project.ts b/src/project.ts index 926a9b879..ec9317bf4 100644 --- a/src/project.ts +++ b/src/project.ts @@ -22,24 +22,6 @@ export type Delegate = id: PeerId; }; -export interface Anchor { - confirmed: true; - id: string; - anchor: { - stateHash: string; - }; -} - -export interface PendingAnchor { - confirmed: false; - id: string; - safeTxHash: string; // Safe transaction hash. - confirmations: string[]; // Owner addresses who have confirmed. - anchor: { - stateHash: string; - }; -} - // Enumerates the space below the Header component in the projects View component export enum ProjectContent { Tree, @@ -277,7 +259,6 @@ export class Project implements ProjectInfo { peers: Peer[]; branches: Branches; profile: Profile | null; - anchors: string[]; // At the moment we still have seed nodes which won't return neither patches or issues patches?: number; issues?: number; @@ -289,7 +270,6 @@ export class Project implements ProjectInfo { peers: Peer[], branches: Branches, profile: Profile | null, - anchors: string[], ) { this.urn = urn; this.head = info.head; @@ -304,7 +284,6 @@ export class Project implements ProjectInfo { this.patches = info.patches; this.issues = info.issues; this.profile = profile; - this.anchors = anchors; } async getRoot( @@ -480,9 +459,6 @@ export class Project implements ProjectInfo { const info = await Project.getInfo(id, seed.api); const urn = isRadicleId(id) ? id : info.urn; - const anchors = profile - ? await profile.confirmedProjectAnchors(urn, config) - : []; // Older versions of http-api don't include the URN. if (!info.urn) info.urn = urn; @@ -503,7 +479,7 @@ export class Project implements ProjectInfo { } } - return new Project(urn, info, seed, peers, remote.heads, profile, anchors); + return new Project(urn, info, seed, peers, remote.heads, profile); } static async getMulti( diff --git a/vite.config.ts b/vite.config.ts index c32e0a916..2d45fd74a 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,8 +1,8 @@ /// import path from "path"; -import { UserConfig } from "vite"; +import type { UserConfig } from "vite"; import { svelte } from "@sveltejs/vite-plugin-svelte"; -import { ViteDevServer } from "vite"; +import type { ViteDevServer } from "vite"; import IstanbulPlugin from "vite-plugin-istanbul"; import history from "connect-history-api-fallback"; import type { Request, Response } from "express-serve-static-core";