From c535c59adfeb76b100529d1dfba7437ea40c3518 Mon Sep 17 00:00:00 2001 From: Dean Sallinen <7519573+deansallinen@users.noreply.github.com> Date: Wed, 4 Dec 2024 14:25:40 -0800 Subject: [PATCH] feat: msig page refreshes on action --- .../msig/[proposer]/[proposal]/+page.svelte | 26 +++-- .../[proposer]/[proposal]/manager.svelte.ts | 107 ++++++++++-------- 2 files changed, 73 insertions(+), 60 deletions(-) diff --git a/src/routes/[network]/(explorer)/msig/[proposer]/[proposal]/+page.svelte b/src/routes/[network]/(explorer)/msig/[proposer]/[proposal]/+page.svelte index 40dc5fae..6cb9f098 100644 --- a/src/routes/[network]/(explorer)/msig/[proposer]/[proposal]/+page.svelte +++ b/src/routes/[network]/(explorer)/msig/[proposer]/[proposal]/+page.svelte @@ -8,7 +8,6 @@ import dayjs from 'dayjs'; import relativeTime from 'dayjs/plugin/relativeTime'; import Account from '$lib/components/elements/account.svelte'; - import { percentString } from '$lib/utils'; // import { Check, UserCheck } from 'lucide-svelte'; import { ApprovalManager } from './manager.svelte'; import ActionCard from '$lib/components/elements/action.svelte'; @@ -40,9 +39,8 @@ total_approvals.some((a) => wharf.session && a.equals(wharf.session.permissionLevel)) ); - let userHasApproved = $derived( - accountHasApproved(wharf.session?.permissionLevel) || !!manager.txid - ); + let transacting = $derived(manager.transacting); + let userHasApproved = $derived(manager.approved); // Expiry date let relativeTimeToExpiry = $derived(dayjs(proposal.transaction.expiration.toDate()).fromNow()); @@ -51,7 +49,7 @@ // Approval statistics let totalRequested = $derived(total_approvals.length); let totalApproved = $derived(provided_approvals.length); - let ratioApproved = $derived(totalApproved / totalRequested); + let ratioApproved = $derived((totalApproved / totalRequested) * 100); // Actions const handleApprove = () => manager.approve(); @@ -62,8 +60,11 @@
@@ -139,9 +140,10 @@ {#if userIsApprover} {#if userHasApproved} - + {:else} - + {/if} {/if} @@ -164,13 +166,15 @@ theme(colors.mineShaft.950) 50% ); background-size: 200% 100%; - background-position: var(--bg-pos, 100%); + background-position: var(--bg-pos); + transition: all var(--ease) var(--duration); } #msig-vis > div { background: linear-gradient(to right, theme(colors.green.900) 50%, theme(colors.zinc.400) 50%); background-size: 200% 100%; - background-position: var(--bg-pos, 100%); + background-position: var(--bg-pos); background-clip: text; color: transparent; + transition: all var(--ease) var(--duration); } diff --git a/src/routes/[network]/(explorer)/msig/[proposer]/[proposal]/manager.svelte.ts b/src/routes/[network]/(explorer)/msig/[proposer]/[proposal]/manager.svelte.ts index 6776d155..d400f3dc 100644 --- a/src/routes/[network]/(explorer)/msig/[proposer]/[proposal]/manager.svelte.ts +++ b/src/routes/[network]/(explorer)/msig/[proposer]/[proposal]/manager.svelte.ts @@ -1,11 +1,16 @@ +import { invalidateAll } from '$app/navigation'; import type { WharfState } from '$lib/state/client/wharf.svelte'; import type { NetworkState } from '$lib/state/network.svelte'; -import { Name, type Checksum256 } from '@wharfkit/antelope'; +import { Name, PermissionLevel, type Checksum256 } from '@wharfkit/antelope'; +import type { AnyAction } from '@wharfkit/session'; type Proposal = { proposer: string; name: string; hash: Checksum256; + approvals: { + provided_approvals: PermissionLevel[]; + }; }; export class ApprovalManager { @@ -13,7 +18,8 @@ export class ApprovalManager { wharf: WharfState | undefined = $state(); proposal: Proposal; error?: string = $state(); - txid?: string = $state(); + transacting = $state(false); + approved = $state(false); constructor(network: NetworkState, proposal: Proposal) { this.network = network; @@ -29,78 +35,81 @@ export class ApprovalManager { if (changed) { this.error = ''; - this.txid = ''; } if (wharf !== this.wharf) { this.wharf = wharf; + + if (wharf.session) { + const permissionLevel = wharf.session.permissionLevel; + this.approved = this.proposal.approvals.provided_approvals.some((a: PermissionLevel) => + a.equals(permissionLevel) + ); + } } } - async approve() { + async transact(action: AnyAction) { try { - if (!this.network || !this.wharf || !this.wharf.session) { - throw new Error("Can't sign, data not ready"); + this.transacting = true; + + if (!this.wharf) { + throw new Error("Can't sign, wharf not ready"); } - const action = this.network.contracts.msig.action('approve', { - proposer: Name.from(this.proposal.proposer), - proposal_name: Name.from(this.proposal.name), - level: this.wharf.session.permissionLevel, - proposal_hash: this.proposal.hash - }); const result = await this.wharf.transact({ action }); - this.txid = result.response?.transaction_id; - if (!this.txid) { + const txid = result.response?.transaction_id; + if (!txid) { throw Error('No transaction id'); } } catch (e) { this.error = String(e); + } finally { + this.transacting = false; + invalidateAll(); // Re-runs the load function to refresh table data } } - async unapprove() { - try { - if (!this.network || !this.wharf || !this.wharf.session) { - throw new Error("Can't sign, data not ready"); - } - const action = this.network.contracts.msig.action('unapprove', { - proposer: Name.from(this.proposal.proposer), - proposal_name: Name.from(this.proposal.name), - level: this.wharf.session.permissionLevel - }); + async approve() { + if (!this.network || !this.wharf || !this.wharf.session) { + throw new Error("Can't sign, data not ready"); + } + const action = this.network.contracts.msig.action('approve', { + proposer: Name.from(this.proposal.proposer), + proposal_name: Name.from(this.proposal.name), + level: this.wharf.session.permissionLevel, + proposal_hash: this.proposal.hash + }); - const result = await this.wharf.transact({ action }); + await this.transact(action); + this.approved = true; + } - this.txid = result.response?.transaction_id; - if (!this.txid) { - throw Error('No transaction id'); - } - } catch (e) { - this.error = String(e); + async unapprove() { + if (!this.network || !this.wharf || !this.wharf.session) { + throw new Error("Can't sign, data not ready"); } + const action = this.network.contracts.msig.action('unapprove', { + proposer: Name.from(this.proposal.proposer), + proposal_name: Name.from(this.proposal.name), + level: this.wharf.session.permissionLevel + }); + + await this.transact(action); + this.approved = false; } async execute() { - try { - if (!this.network || !this.wharf || !this.wharf.session) { - throw new Error("Can't sign, data not ready"); - } - const action = this.network.contracts.msig.action('exec', { - proposer: Name.from(this.proposal.proposer), - proposal_name: Name.from(this.proposal.name), - executer: this.wharf.session.actor - }); - - const result = await this.wharf.transact({ action }); - - this.txid = result.response?.transaction_id; - if (!this.txid) { - throw Error('No transaction id'); - } - } catch (e) { - this.error = String(e); + if (!this.network || !this.wharf || !this.wharf.session) { + throw new Error("Can't sign, data not ready"); } + const action = this.network.contracts.msig.action('exec', { + proposer: Name.from(this.proposal.proposer), + proposal_name: Name.from(this.proposal.name), + executer: this.wharf.session.actor + }); + + this.transact(action); } }