-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding support for multisig accounts #384
Changes from 25 commits
1029e2f
d46b7f2
d59678c
92dfc65
c73b731
9afd44a
7030041
c9b63ae
2af3530
e50358c
3aa1ff3
a5ce003
18a3961
0622519
a3a9b3c
0f0fb0c
e7926de
6adc1c9
b758141
60c3295
516a569
0cb57ca
9d64735
e7704df
8f58f89
6cfe7e9
cb69f6f
e692369
5540a00
df68876
41cebc8
7b1ee56
dd5dd02
39af9c9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<script lang="ts"> | ||
import { cn } from '$lib/utils'; | ||
import { type Snippet } from 'svelte'; | ||
import type { HTMLAnchorAttributes } from 'svelte/elements'; | ||
|
||
interface Props extends HTMLAnchorAttributes { | ||
href: string; | ||
children?: Snippet; | ||
text?: string; | ||
} | ||
|
||
let { href, text = '', children, ...props }: Props = $props(); | ||
</script> | ||
|
||
<a | ||
{href} | ||
class={cn( | ||
'inline-flex items-center gap-2 text-skyBlue-500 hover:text-skyBlue-400 focus-visible:outline focus-visible:outline-solar-500 ', | ||
props.class | ||
)} | ||
> | ||
{#if children} | ||
{@render children()} | ||
{:else} | ||
{text} | ||
{/if} | ||
</a> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
<script lang="ts"> | ||
import { cn } from '$lib/utils/style'; | ||
import type { Snippet } from 'svelte'; | ||
import type { HTMLInputAttributes } from 'svelte/elements'; | ||
import Code from '../code.svelte'; | ||
|
||
interface DatetimeInputProps extends HTMLInputAttributes { | ||
date?: Date; | ||
value?: string; | ||
min?: string; | ||
children?: Snippet; | ||
debug?: boolean; | ||
} | ||
|
||
var now = new Date(); | ||
now.setMinutes(now.getMinutes() - now.getTimezoneOffset()); | ||
|
||
function dateToInputString(date: Date) { | ||
return date.toISOString().slice(0, 16); | ||
} | ||
|
||
let { | ||
date = $bindable(), | ||
value = $bindable(), | ||
min = dateToInputString(now), | ||
class: className, | ||
debug = false, | ||
...props | ||
}: DatetimeInputProps = $props(); | ||
|
||
value = undefined; | ||
if (date) { | ||
const utc = new Date(date); | ||
utc.setMinutes(utc.getMinutes() - utc.getTimezoneOffset()); | ||
value = dateToInputString(utc); | ||
} | ||
|
||
/** Set the input value from a parent */ | ||
export function set(date: Date | undefined) { | ||
if (!date) { | ||
value = undefined; | ||
} else { | ||
value = dateToInputString(date); | ||
} | ||
} | ||
|
||
$effect(() => { | ||
if (value) { | ||
date = new Date(`${value}:00.000`); | ||
} else { | ||
date = undefined; | ||
} | ||
}); | ||
</script> | ||
|
||
<div | ||
class={cn( | ||
'relative flex h-12 gap-2 rounded-lg border-2 border-mineShaft-600 px-4 *:content-center focus-within:border-skyBlue-500 focus-within:ring focus-within:ring-1 focus-within:ring-inset focus-within:ring-skyBlue-500', | ||
className | ||
)} | ||
> | ||
<input | ||
class="placeholder:text-muted w-full rounded-lg bg-transparent font-medium focus:outline-none" | ||
type="datetime-local" | ||
{min} | ||
bind:value | ||
{...props} | ||
/> | ||
<div class="text-muted select-none"> | ||
{@render props.children?.()} | ||
</div> | ||
</div> | ||
|
||
{#if debug} | ||
<div class="mt-4"> | ||
<h3>Component State</h3> | ||
<!-- prettier-ignore --> | ||
<Code> | ||
date: {date} | ||
value: {value} | ||
min: {min} | ||
</Code> | ||
</div> | ||
{/if} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,7 @@ | |
|
||
interface Props { | ||
options: ExtendedSelectOption[]; | ||
selected: ExtendedSelectOption; | ||
selected?: ExtendedSelectOption; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IIRC this was required in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll revert this change and force a default option on the settings page then. The select element with a default option ands up triggering the effects on the page, setting the value to whatever the select believes the default option should be. This could override defaults set elsewhere. So there's some funk in here at the moment we should try to figure out how to address. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree, we should address the funk and see if we can make There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Awesome, thanks! |
||
onSelectedChange?: ChangeFn<ExtendedSelectOption | undefined>; | ||
variant?: SelectOptionVariant; | ||
id: string; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,17 @@ | ||
<script lang="ts"> | ||
import { transactions } from '$lib/wharf/transact.svelte'; | ||
import type { Checksum256 } from '@wharfkit/antelope'; | ||
import Transaction from '../elements/transaction.svelte'; | ||
import { Serializer, type Checksum256 } from '@wharfkit/antelope'; | ||
import Transaction from '$lib/components/elements/transaction.svelte'; | ||
import CircleCheckBig from 'lucide-svelte/icons/circle-check-big'; | ||
import ClipboardPen from 'lucide-svelte/icons/clipboard-pen'; | ||
import * as m from '$lib/paraglide/messages'; | ||
import type { UnicoveContext } from '$lib/state/client.svelte'; | ||
import { getContext } from 'svelte'; | ||
|
||
import { Types as MsigTypes } from '$lib/wharf/contracts/msig'; | ||
import Button from '$lib/components/button/button.svelte'; | ||
|
||
const context = getContext<UnicoveContext>('state'); | ||
|
||
interface Props { | ||
transactionId?: Checksum256 | string; | ||
|
@@ -15,15 +23,44 @@ | |
const transaction = $derived( | ||
transactions.find((t) => t.transaction?.id.equals(String(transactionId))) | ||
); | ||
|
||
const proposals = $derived( | ||
transaction?.transaction?.actions | ||
.filter((a) => a.name.equals('propose') && a.account.equals('eosio.msig')) | ||
.map((p) => { | ||
return Serializer.decode({ | ||
data: p.data, | ||
type: MsigTypes.propose | ||
}); | ||
}) | ||
); | ||
</script> | ||
|
||
<div class="space-y-6 rounded-lg" class:hidden> | ||
{#if transaction} | ||
<div class="flex flex-col items-center gap-6"> | ||
<picture class="size-24"> | ||
<CircleCheckBig class="size-full text-green-300" /> | ||
</picture> | ||
<h2 class="h3">{m.common_transaction_complete()}</h2> | ||
{#if proposals && proposals.length} | ||
<picture class="size-24"> | ||
<ClipboardPen class="size-full text-green-300" /> | ||
</picture> | ||
<h3 class="h3">Multi-Sig Proposal Created</h3> | ||
<p class="text-center"> | ||
The multi-sig proposal for this transaction has been created and now needs to be approved. | ||
View the proposal below and share it with the parties who need to sign. | ||
Comment on lines
+48
to
+49
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we be picky about translations at this point? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We probably should get better about this, and have someone in charge of that entire pipeline. Considering we're not 100% translated right now though, I don't know if it should be a barrier? |
||
</p> | ||
{#each proposals as proposal} | ||
<Button href="/{context.network}/msig/{proposal.proposer}/{proposal.proposal_name}"> | ||
View Proposal ({proposal.proposer}/{proposal.proposal_name}) | ||
</Button> | ||
{/each} | ||
{:else} | ||
<picture class="size-24"> | ||
<CircleCheckBig class="size-full text-green-300" /> | ||
</picture> | ||
<h3 class="h3"> | ||
{m.common_transaction_complete()} | ||
</h3> | ||
{/if} | ||
</div> | ||
<!-- <h3 class="h3">{transaction.status}</h3> --> | ||
<table class="table-styles"> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious what this looks like in context with layout, the arrow glyph, and the small text.
Probably should use a translation here too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's what it looks like. I've updated all the translations in the account switcher here: e692369
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might call for a slightly lighter-weight font in the second line, but otherwise looks good.
I'm always hesitant to use glyphs in the font vs an svg because they can become unpredicatable with different fonts, different browser settings, zoom levels, but more importantly: it's decorative, so it shouldn't be included in the text string (which will be translated at some point)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah totally understood. We probably want a "real" design for these elements, since as I worked on this I was just implementing my developer design to make something available.
I'm very open to change with how its displayed.