Skip to content

Commit 8f1b4a1

Browse files
committed
Proposal name dialog + top 30 bps during msig proposal
1 parent 8632e9f commit 8f1b4a1

7 files changed

Lines changed: 235 additions & 65 deletions

File tree

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<script lang="ts">
2+
import { getContext } from 'svelte';
3+
import { fade } from 'svelte/transition';
4+
import { createDialog, melt } from '@melt-ui/svelte';
5+
import { Name } from '@wharfkit/antelope';
6+
import { Button, Label, NameInput } from 'unicove-components';
7+
8+
import type { UnicoveContext } from '$lib/state/client.svelte';
9+
10+
const context = getContext<UnicoveContext>('state');
11+
12+
let prompt = $derived(context.wharf.proposalNamePrompt);
13+
let inputValue: Name = $state(Name.from(''));
14+
let valid = $state(false);
15+
16+
const {
17+
elements: { overlay, content, portalled },
18+
states: { open }
19+
} = createDialog({
20+
preventScroll: true,
21+
closeOnOutsideClick: false,
22+
escapeBehavior: 'ignore'
23+
});
24+
25+
$effect(() => {
26+
if (prompt) {
27+
inputValue = Name.from(prompt.defaultName);
28+
$open = true;
29+
} else {
30+
$open = false;
31+
}
32+
});
33+
34+
function submit() {
35+
if (!valid) return;
36+
context.wharf.submitProposalName(String(inputValue));
37+
}
38+
39+
function cancel() {
40+
context.wharf.cancelProposalName();
41+
}
42+
</script>
43+
44+
{#if $open}
45+
<div use:melt={$portalled}>
46+
<div
47+
use:melt={$overlay}
48+
class="bg-scrim/80 fixed inset-0 z-50"
49+
transition:fade={{ duration: 150 }}
50+
></div>
51+
52+
<div class="fixed inset-0 z-50 flex items-center justify-center p-4">
53+
<div
54+
use:melt={$content}
55+
class="bg-surface-container w-full max-w-md rounded-xl p-6 shadow-xl"
56+
transition:fade={{ duration: 150 }}
57+
>
58+
<form
59+
onsubmit={(e) => {
60+
e.preventDefault();
61+
submit();
62+
}}
63+
>
64+
<h2 class="text-on-surface mb-4 text-lg font-semibold">Proposal Name</h2>
65+
<p class="text-on-surface-variant mb-4 text-sm">
66+
Enter a name for this proposal or use the generated default.
67+
</p>
68+
69+
<fieldset class="mb-4 grid gap-2">
70+
<Label for="proposal-name-input">Name</Label>
71+
<NameInput
72+
id="proposal-name-input"
73+
bind:value={inputValue}
74+
bind:valid
75+
placeholder="Proposal name"
76+
/>
77+
</fieldset>
78+
79+
<div class="flex justify-end gap-3">
80+
<Button variant="secondary" onclick={cancel}>Cancel</Button>
81+
<Button variant="primary" disabled={!valid} type="submit">Confirm</Button>
82+
</div>
83+
</form>
84+
</div>
85+
</div>
86+
</div>
87+
{/if}

src/lib/state/client/wharf.svelte.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { type QueuedTransaction, StatusType, queueTransaction } from '$lib/wharf
3131
import { chainMapper } from '$lib/wharf/chains';
3232
import type { SettingsState } from '$lib/state/settings.svelte';
3333
import type { NetworkState } from '$lib/state/network.svelte';
34+
import type { ProducersState } from '$lib/state/producers.svelte';
3435
import { chainDefs, msigTransactPlugins, transactPlugins, walletPlugins } from '$lib/wharf/plugins';
3536

3637
export class WharfState {
@@ -46,8 +47,13 @@ export class WharfState {
4647
public settings: SettingsState = $state() as SettingsState;
4748

4849
public metamaskPlugin?: AccountCreationPluginMetamask;
50+
public producers?: ProducersState;
51+
public proposalNamePrompt: { defaultName: string } | null = $state(null);
52+
private proposalNameResolve?: (name: string) => void;
53+
private proposalNameReject?: (error: Error) => void;
4954

50-
constructor(settings: SettingsState) {
55+
constructor(settings: SettingsState, producers?: ProducersState) {
56+
this.producers = producers;
5157
this.settings = settings;
5258
if (browser) {
5359
this.chainsSession = JSON.parse(localStorage.getItem('chainsSession') || '{}');
@@ -109,6 +115,28 @@ export class WharfState {
109115
}
110116
}
111117

118+
private async promptForProposalName(defaultName: string): Promise<string> {
119+
this.proposalNamePrompt = { defaultName };
120+
try {
121+
return await new Promise<string>((resolve, reject) => {
122+
this.proposalNameResolve = resolve;
123+
this.proposalNameReject = reject;
124+
});
125+
} finally {
126+
this.proposalNamePrompt = null;
127+
this.proposalNameResolve = undefined;
128+
this.proposalNameReject = undefined;
129+
}
130+
}
131+
132+
public submitProposalName(name: string) {
133+
this.proposalNameResolve?.(name);
134+
}
135+
136+
public cancelProposalName() {
137+
this.proposalNameReject?.(new Error('Proposal name entry cancelled.'));
138+
}
139+
112140
public async login(options?: LoginOptions): Promise<Session> {
113141
if (!this.sessionKit) {
114142
throw new Error('User not initialized');
@@ -212,6 +240,19 @@ export class WharfState {
212240
this.transacting = true;
213241

214242
const isMsig = this.session.walletPlugin.id === 'wallet-plugin-multisig';
243+
244+
if (isMsig) {
245+
const { generateRandomName } = await import('$lib/utils/random');
246+
this.session.walletPlugin.data.nextProposalName = await this.promptForProposalName(
247+
generateRandomName()
248+
);
249+
if (this.producers) {
250+
this.session.walletPlugin.data.topProducers = this.producers.allActiveProducers
251+
.slice(0, 30)
252+
.map((p) => String(p.owner));
253+
}
254+
}
255+
215256
const result = await this.session
216257
.transact(args, {
217258
abiCache: this.abiCache,

src/lib/wharf/plugins/multisig.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ export class WalletPluginMultiSig extends AbstractWalletPlugin implements Wallet
105105
const key = String(auth);
106106
if (seen.has(key)) return [];
107107
seen.add(key);
108+
if (auth.actor.equals('eosio.prods') && this.data.topProducers) {
109+
return (this.data.topProducers as string[]).map((name: string) =>
110+
PermissionLevel.from({ actor: name, permission: 'active' })
111+
);
112+
}
108113
const account = await context.client.v1.chain.get_account(auth.actor);
109114
const permission = account.permissions.find((p) => p.perm_name.equals(auth.permission));
110115
if (!permission) return [auth];
@@ -156,11 +161,14 @@ export class WalletPluginMultiSig extends AbstractWalletPlugin implements Wallet
156161
transaction_extensions: []
157162
});
158163

164+
const proposalName = this.data.nextProposalName || generateRandomName();
165+
delete this.data.nextProposalName;
166+
159167
const actions = [
160168
msig.action(
161169
'propose',
162170
{
163-
proposal_name: generateRandomName(),
171+
proposal_name: proposalName,
164172
proposer: session.actor,
165173
requested,
166174
trx

src/locales/en.po

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ msgstr ""
33
"Project-Id-Version: \n"
44
"Report-Msgid-Bugs-To: \n"
55
"POT-Creation-Date: 2025-10-21T07:48:36.657Z\n"
6-
"PO-Revision-Date: 2026-03-21T00:32:28.576Z\n"
6+
"PO-Revision-Date: 2026-03-23T03:31:21.080Z\n"
77
"Last-Translator: \n"
88
"Language: en\n"
99
"Language-Team: \n"
@@ -502,12 +502,12 @@ msgstr "Transfer"
502502
msgid "+ {0} ms (CPU)"
503503
msgstr "+ {0} ms (CPU)"
504504

505-
#. placeholder {0}: data.powup_net
506505
#. placeholder {0}: data.powup_cpu
507-
#. placeholder {0}: key.weight
506+
#. placeholder {0}: data.powup_net
508507
#. placeholder {0}: account.weight
509508
#. placeholder {0}: key.weight
510509
#. placeholder {0}: account.weight
510+
#. placeholder {0}: key.weight
511511
#: src/lib/components/summary/eosio.reserv/powupresult.svelte
512512
#: src/lib/components/summary/eosio.reserv/powupresult.svelte
513513
#: src/lib/components/summary/eosio/newaccount.svelte
@@ -797,8 +797,8 @@ msgstr "Details"
797797
msgid "Network Fees"
798798
msgstr "Network Fees"
799799

800-
#. placeholder {0}: market.network.currency.symbol.code
801800
#. placeholder {0}: data.network.chain.systemToken?.symbol.code || ''
801+
#. placeholder {0}: market.network.currency.symbol.code
802802
#: src/routes/[[locale]]/[network]/(account)/ram/+page.svelte
803803
#: src/routes/[[locale]]/[network]/(account)/ram/+page.svelte
804804
msgid "Market Cap ({0})"
@@ -1722,6 +1722,7 @@ msgid "Delete"
17221722
msgstr "Delete"
17231723

17241724
#: src/lib/components/accountswitch.svelte
1725+
#: src/lib/components/elements/proposalname.svelte
17251726
#: src/lib/components/elements/suspiciousmemo.svelte
17261727
#: src/routes/[[locale]]/[network]/(account)/bidname/components/your-bids.svelte
17271728
#: src/routes/[[locale]]/[network]/(dev)/debug/components/sections/buttons.svelte
@@ -1732,6 +1733,7 @@ msgstr "Delete"
17321733
msgid "Cancel"
17331734
msgstr "Cancel"
17341735

1736+
#: src/lib/components/elements/proposalname.svelte
17351737
#: src/routes/[[locale]]/[network]/(account)/(send)/send/[[contract]]/[[symbol]]/+page.svelte
17361738
#: src/routes/[[locale]]/[network]/(dev)/debug/components/sections/buttons.svelte
17371739
#: src/routes/[[locale]]/[network]/(explorer)/account/[name]/permissions/[permission]/+page.svelte
@@ -2013,10 +2015,10 @@ msgstr "Pill Select"
20132015
msgid "Select a date range"
20142016
msgstr "Select a date range"
20152017

2016-
#. placeholder {0}: JSON.stringify(tokenSelected, null, 2)
2017-
#. placeholder {0}: imageOptionSelected.label
2018-
#. placeholder {0}: selectedFormOption.label
20192018
#. placeholder {0}: selected.label
2019+
#. placeholder {0}: selectedFormOption.label
2020+
#. placeholder {0}: imageOptionSelected.label
2021+
#. placeholder {0}: JSON.stringify(tokenSelected, null, 2)
20202022
#: src/routes/[[locale]]/[network]/(dev)/debug/components/sections/select.svelte
20212023
#: src/routes/[[locale]]/[network]/(dev)/debug/components/sections/select.svelte
20222024
#: src/routes/[[locale]]/[network]/(dev)/debug/components/sections/select.svelte
@@ -4222,7 +4224,7 @@ msgstr "<0>Unicove -</0> The {0} web wallet and block explorer"
42224224

42234225
#. placeholder {0}: network.chain.name
42244226
#. placeholder {0}: networkName
4225-
#. placeholder {0}: networkName
4227+
#. placeholder {0}: network.chain.name
42264228
#: src/routes/+layout.server.ts
42274229
#: src/routes/[[locale]]/[network]/(homepage)/components/hero.svelte
42284230
#: src/routes/[[locale]]/[network]/(homepage)/components/hero.svelte
@@ -4256,8 +4258,8 @@ msgstr "{0} Token Swap has begun!"
42564258
msgid "Swap {0} to {1} at a 1:1 ratio"
42574259
msgstr "Swap {0} to {1} at a 1:1 ratio"
42584260

4259-
#. placeholder {0}: String(data.quote.symbol.name)
42604261
#. placeholder {0}: props.network.token.name
4262+
#. placeholder {0}: String(data.quote.symbol.name)
42614263
#: src/routes/[[locale]]/[network]/(account)/swap/[basecontract]/[basesymbol]/[quotecontract]/[quotesymbol]/+page.svelte
42624264
#: src/routes/[[locale]]/[network]/(homepage)/components/legacy-token-swap.svelte
42634265
msgid "Swap to {0}"
@@ -4276,7 +4278,7 @@ msgstr "Get Tokens"
42764278
#. placeholder {0}: symbol.name
42774279
#. placeholder {0}: symbol.name
42784280
#. placeholder {0}: symbol.name
4279-
#. placeholder {0}: String(network.token.symbol.name)
4281+
#. placeholder {0}: symbol.name
42804282
#: src/routes/[[locale]]/[network]/(account)/(send)/send/[[contract]]/[[symbol]]/+layout.ts
42814283
#: src/routes/[[locale]]/[network]/(account)/(send)/send/[[contract]]/[[symbol]]/+layout.ts
42824284
#: src/routes/[[locale]]/[network]/(account)/(send)/send/[[contract]]/[[symbol]]/+layout.ts
@@ -4299,10 +4301,10 @@ msgstr "One {0} of RAM represents ownership rights over 1000 bytes of the networ
42994301
#. placeholder {1}: quote.name
43004302
#. placeholder {0}: base.name
43014303
#. placeholder {1}: quote.name
4302-
#. placeholder {0}: data.network.token.name
4303-
#. placeholder {1}: data.network.getRamToken().name
4304-
#. placeholder {0}: String(network.chain.systemToken?.symbol.name)
4305-
#. placeholder {1}: String(ramtoken.name)
4304+
#. placeholder {0}: base.name
4305+
#. placeholder {1}: quote.name
4306+
#. placeholder {0}: base.name
4307+
#. placeholder {1}: quote.name
43064308
#: src/routes/[[locale]]/[network]/(account)/swap/[basecontract]/[basesymbol]/[quotecontract]/[quotesymbol]/+page.ts
43074309
#: src/routes/[[locale]]/[network]/(account)/swap/[basecontract]/[basesymbol]/[quotecontract]/[quotesymbol]/+page.ts
43084310
#: src/routes/[[locale]]/[network]/(explorer)/account/[name]/+page.svelte
@@ -5017,6 +5019,7 @@ msgstr "Multisig Details"
50175019
msgid "Proposer"
50185020
msgstr "Proposer"
50195021

5022+
#: src/lib/components/elements/proposalname.svelte
50205023
#: src/routes/[[locale]]/[network]/(explorer)/msig/[proposer]/[proposal]/+page.svelte
50215024
msgid "Proposal Name"
50225025
msgstr "Proposal Name"
@@ -6828,6 +6831,7 @@ msgstr "Place Bid - {0} Premium Names"
68286831
msgid "Place a bid on a premium account name on the {0} network."
68296832
msgstr "Place a bid on a premium account name on the {0} network."
68306833

6834+
#: src/lib/components/elements/proposalname.svelte
68316835
#: src/routes/[[locale]]/[network]/(account)/bidname/(bidding)/refund/+page.svelte
68326836
msgid "Name"
68336837
msgstr "Name"
@@ -6924,8 +6928,8 @@ msgstr "{0}You have {1} available to reclaim."
69246928
msgid "You have been outbid on this name.<0/>"
69256929
msgstr "You have been outbid on this name.<0/>"
69266930

6927-
#. placeholder {0}: String(manager.refundAmount)
69286931
#. placeholder {0}: String(tracked.refund.amount)
6932+
#. placeholder {0}: String(manager.refundAmount)
69296933
#: src/routes/[[locale]]/[network]/(account)/bidname/(bidding)/refund/+page.svelte
69306934
#: src/routes/[[locale]]/[network]/(account)/bidname/components/your-bids.svelte
69316935
msgid "Claim Refund ({0})"
@@ -7577,13 +7581,6 @@ msgstr "Create a new sentiment topic"
75777581
msgid "Before You Create"
75787582
msgstr "Before You Create"
75797583

7580-
#~ msgid ""
7581-
#~ "The creation fee is non-refundable. Fees are sent to the <0/> account, which distributes them through standard network fee channels (RAM, powerup,\n"
7582-
#~ "name bids)."
7583-
#~ msgstr ""
7584-
#~ "The creation fee is non-refundable. Fees are sent to the <0/> account, which distributes them through standard network fee channels (RAM, powerup,\n"
7585-
#~ "name bids)."
7586-
75877584
#: src/routes/[[locale]]/[network]/(explorer)/sentiment/topics/create/+page.svelte
75887585
msgid ""
75897586
"Topics cannot be edited or deleted by the creator once submitted, including the topic\n"
@@ -7611,3 +7608,15 @@ msgid ""
76117608
msgstr ""
76127609
"The creation fee is non-refundable. Fees are sent to the <0/> account, which distributes them through standard network fee channels (RAM, powerup, name\n"
76137610
"bids)."
7611+
7612+
#: src/lib/state/client/wharf.svelte.ts
7613+
msgid "Proposal name entry cancelled."
7614+
msgstr "Proposal name entry cancelled."
7615+
7616+
#: src/lib/components/elements/proposalname.svelte
7617+
msgid "Enter a name for this proposal or use the generated default."
7618+
msgstr "Enter a name for this proposal or use the generated default."
7619+
7620+
#: src/lib/components/elements/proposalname.svelte
7621+
msgid "Proposal name"
7622+
msgstr "Proposal name"

0 commit comments

Comments
 (0)