From c8fdd215ac61bead0f551525e36ccd5f62357d60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bego=C3=B1a=20=C3=81lvarez=20de=20la=20Cruz?= Date: Thu, 17 Feb 2022 17:30:59 +0100 Subject: [PATCH 001/171] feat: make selected wallet the main view (#2179) --- packages/desktop/App.svelte | 1 + .../components/modals/AccountActions.svelte | 7 +- packages/shared/lib/router.ts | 19 +--- packages/shared/lib/typings/routes.ts | 1 + .../shared/routes/dashboard/Dashboard.svelte | 12 ++- .../routes/dashboard/wallet/Wallet.svelte | 100 ++++++++++-------- .../dashboard/wallet/views/Account.svelte | 72 ------------- .../wallet/views/AccountNavigation.svelte | 13 +-- .../wallet/views/CreateAccount.svelte | 5 +- .../wallet/views/ManageAccount.svelte | 12 +-- .../dashboard/wallet/views/Receive.svelte | 5 +- .../routes/dashboard/wallet/views/Send.svelte | 7 +- .../routes/dashboard/wallet/views/index.js | 1 - 13 files changed, 82 insertions(+), 173 deletions(-) delete mode 100644 packages/shared/routes/dashboard/wallet/views/Account.svelte diff --git a/packages/desktop/App.svelte b/packages/desktop/App.svelte index bad3f95189d..ae5bba43d15 100644 --- a/packages/desktop/App.svelte +++ b/packages/desktop/App.svelte @@ -75,6 +75,7 @@ if (get(dashboardRoute) !== Tabs.Wallet) { dashboardRoute.set(Tabs.Wallet) } + // TODO: update to single wallet walletRoute.set(route) }) Electron.onEvent('menu-navigate-settings', () => { diff --git a/packages/shared/components/modals/AccountActions.svelte b/packages/shared/components/modals/AccountActions.svelte index d07db9261c0..c1a03b325f4 100644 --- a/packages/shared/components/modals/AccountActions.svelte +++ b/packages/shared/components/modals/AccountActions.svelte @@ -2,8 +2,8 @@ import { HR, Icon, Modal, Text } from 'shared/components' import { openPopup } from 'shared/lib/popup' import { activeProfile, updateProfile } from 'shared/lib/profile' - import { accountRoute, walletRoute } from 'shared/lib/router' - import { AccountRoutes, WalletRoutes } from 'shared/lib/typings/routes' + import { accountRoute } from 'shared/lib/router' + import { AccountRoutes } from 'shared/lib/typings/routes' import { asyncRemoveWalletAccount, selectedAccountId, selectedMessage } from 'shared/lib/wallet' import { getContext } from 'svelte' import type { Readable } from 'svelte/store' @@ -52,7 +52,6 @@ } selectedAccountId.set(null) selectedMessage.set(null) - walletRoute.set(WalletRoutes.Init) accountRoute.set(AccountRoutes.Init) }, }, @@ -75,7 +74,6 @@ } selectedAccountId.set(null) selectedMessage.set(null) - walletRoute.set(WalletRoutes.Init) accountRoute.set(AccountRoutes.Init) }, }, @@ -91,7 +89,6 @@ } selectedAccountId.set(null) selectedMessage.set(null) - walletRoute.set(WalletRoutes.Init) accountRoute.set(AccountRoutes.Init) } diff --git a/packages/shared/lib/router.ts b/packages/shared/lib/router.ts index 95477cd6e59..86d6f9e26b0 100644 --- a/packages/shared/lib/router.ts +++ b/packages/shared/lib/router.ts @@ -1,15 +1,6 @@ import { cleanupSignup, login, strongholdPassword, walletPin } from 'shared/lib/app' import { activeProfile, profiles } from 'shared/lib/profile' -import { - AccountRoutes, - AppRoute, - LedgerRoutes, - SettingsRoutes, - SetupType, - Tabs, - WalletRoutes, -} from 'shared/lib/typings/routes' -import { selectedAccountId } from 'shared/lib/wallet' +import { AccountRoutes, AppRoute, LedgerRoutes, SettingsRoutes, SetupType, Tabs } from 'shared/lib/typings/routes' import { get, readable, writable } from 'svelte/store' import { deepLinkRequestActive } from './deepLinking/deepLinking' import { closePopup } from './popup' @@ -80,11 +71,6 @@ export const ledgerRoute = writable(LedgerRoutes.LegacyIntro) */ export const ledgerRouteHistory = writable([]) -/** - * Wallet view route - */ -export const walletRoute = writable(WalletRoutes.Init) - /** * Account view route */ @@ -293,7 +279,6 @@ export const resetRouter = (): void => { setRoute(AppRoute.Welcome) } - walletRoute.set(WalletRoutes.Init) accountRoute.set(AccountRoutes.Init) settingsRoute.set(SettingsRoutes.Init) dashboardRoute.set(Tabs.Wallet) @@ -302,9 +287,7 @@ export const resetRouter = (): void => { export const resetWalletRoute = (): void => { dashboardRoute.set(Tabs.Wallet) - walletRoute.set(WalletRoutes.Init) accountRoute.set(AccountRoutes.Init) - selectedAccountId.set(null) } export const resetLedgerRoute = (): void => { diff --git a/packages/shared/lib/typings/routes.ts b/packages/shared/lib/typings/routes.ts index a65b9d4aea2..5b64a83dae4 100644 --- a/packages/shared/lib/typings/routes.ts +++ b/packages/shared/lib/typings/routes.ts @@ -40,6 +40,7 @@ export enum LedgerRoutes { AccountIndex = 'accountIndex', } +// TODO: remove this export enum WalletRoutes { Init = 'init', Account = 'account', diff --git a/packages/shared/routes/dashboard/Dashboard.svelte b/packages/shared/routes/dashboard/Dashboard.svelte index a7398155a3a..1c9dbe17c96 100644 --- a/packages/shared/routes/dashboard/Dashboard.svelte +++ b/packages/shared/routes/dashboard/Dashboard.svelte @@ -19,9 +19,9 @@ } from 'shared/lib/notifications' import { closePopup, openPopup, popupState } from 'shared/lib/popup' import { activeProfile, isLedgerProfile, isSoftwareProfile, updateProfile } from 'shared/lib/profile' - import { accountRoute, dashboardRoute, routerNext, settingsChildRoute, settingsRoute, walletRoute } from 'shared/lib/router' + import { accountRoute, dashboardRoute, routerNext, settingsChildRoute, settingsRoute } from 'shared/lib/router' import type { Locale } from 'shared/lib/typings/i18n' - import { AccountRoutes, AdvancedSettings, SettingsRoutes, Tabs, WalletRoutes } from 'shared/lib/typings/routes' + import { AccountRoutes, AdvancedSettings, SettingsRoutes, Tabs } from 'shared/lib/typings/routes' import { api, isBackgroundSyncing, @@ -110,7 +110,6 @@ if (get(dashboardRoute) !== Tabs.Wallet) { dashboardRoute.set(Tabs.Wallet) } - walletRoute.set(WalletRoutes.Account) accountRoute.set(AccountRoutes.Init) } } @@ -134,7 +133,7 @@ } }) - if ($walletRoute === WalletRoutes.Init && !$accountsLoaded && $loggedIn) { + if (!$accountsLoaded && $loggedIn) { startInit = Date.now() busy = true if (!get(popupState).active) { @@ -260,6 +259,11 @@ $: if ($activeProfile && $isLedgerProfile && !$isPollingLedgerDeviceStatus) { pollLedgerDeviceStatus(false, LEDGER_STATUS_POLL_INTERVAL) } + + // TODO: remove, dev only + $: if(accountsLoaded) { + selectedAccountId.set($accounts?.[0]?.id) + } {#if mobile} diff --git a/packages/shared/routes/dashboard/wallet/Wallet.svelte b/packages/shared/routes/dashboard/wallet/Wallet.svelte index 717a01b6917..17c9d6be912 100644 --- a/packages/shared/routes/dashboard/wallet/Wallet.svelte +++ b/packages/shared/routes/dashboard/wallet/Wallet.svelte @@ -1,5 +1,5 @@ -{#if $walletRoute === WalletRoutes.Account && $selectedAccountId} - -{:else} -
-
- - -
- {#if $walletRoute === WalletRoutes.CreateAccount} - - {:else} - - - - - {/if} -
-
-
- - +{#if $selectedAccount} +
+ + {#key $selectedAccountId} +
+ + + + + + + + -
- - +
+ + - - + +
-
+ {/key} +
{/if} diff --git a/packages/shared/routes/dashboard/wallet/views/Account.svelte b/packages/shared/routes/dashboard/wallet/views/Account.svelte deleted file mode 100644 index 2208eb0826b..00000000000 --- a/packages/shared/routes/dashboard/wallet/views/Account.svelte +++ /dev/null @@ -1,72 +0,0 @@ - - - -{#if $viewableAccounts && $account} -
- - {#key $selectedAccountId} -
- - - - - - - - - -
- - - - - - -
-
- {/key} - -
-{/if} diff --git a/packages/shared/routes/dashboard/wallet/views/AccountNavigation.svelte b/packages/shared/routes/dashboard/wallet/views/AccountNavigation.svelte index e8e35408471..10f33bd62d4 100644 --- a/packages/shared/routes/dashboard/wallet/views/AccountNavigation.svelte +++ b/packages/shared/routes/dashboard/wallet/views/AccountNavigation.svelte @@ -1,11 +1,8 @@ diff --git a/packages/shared/routes/dashboard/wallet/views/ManageAccount.svelte b/packages/shared/routes/dashboard/wallet/views/ManageAccount.svelte index 03b085c939a..80127e00fe3 100644 --- a/packages/shared/routes/dashboard/wallet/views/ManageAccount.svelte +++ b/packages/shared/routes/dashboard/wallet/views/ManageAccount.svelte @@ -1,8 +1,8 @@ diff --git a/packages/shared/routes/dashboard/wallet/views/Send.svelte b/packages/shared/routes/dashboard/wallet/views/Send.svelte index 860161e5066..d447851ec24 100644 --- a/packages/shared/routes/dashboard/wallet/views/Send.svelte +++ b/packages/shared/routes/dashboard/wallet/views/Send.svelte @@ -19,7 +19,7 @@ import { displayNotifications, removeDisplayNotification, showAppNotification } from 'shared/lib/notifications' import { closePopup, openPopup, popupState } from 'shared/lib/popup' import { isLedgerProfile, isSoftwareProfile } from 'shared/lib/profile' - import { accountRoute, walletRoute } from 'shared/lib/router' + import { accountRoute } from 'shared/lib/router' import { CurrencyTypes } from 'shared/lib/typings/currency' import { GeneratingRemainderDepositAddressEvent, @@ -32,7 +32,7 @@ import type { Locale } from 'shared/lib/typings/i18n' import { LedgerDeviceState } from 'shared/lib/typings/ledger' import type { NotificationType } from 'shared/lib/typings/notification' - import { AccountRoutes, WalletRoutes } from 'shared/lib/typings/routes' + import { AccountRoutes } from 'shared/lib/typings/routes' import type { WalletAccount } from 'shared/lib/typings/wallet' import { changeUnits, formatUnitPrecision } from 'shared/lib/units' import { ADDRESS_LENGTH, validateBech32Address } from 'shared/lib/utils' @@ -427,7 +427,8 @@ accountRoute.set(AccountRoutes.Init) if (!$account) { - walletRoute.set(WalletRoutes.Init) + // TODO: handle this case for single wallet view + accountRoute.set(AccountRoutes.Init) } } diff --git a/packages/shared/routes/dashboard/wallet/views/index.js b/packages/shared/routes/dashboard/wallet/views/index.js index c5e25f27182..c677bb7fd97 100644 --- a/packages/shared/routes/dashboard/wallet/views/index.js +++ b/packages/shared/routes/dashboard/wallet/views/index.js @@ -1,6 +1,5 @@ export { default as Receive } from './Receive.svelte' export { default as Send } from './Send.svelte' -export { default as Account } from './Account.svelte' export { default as CreateAccount } from './CreateAccount.svelte' export { default as ManageAccount } from './ManageAccount.svelte' export { default as WalletBalance } from './WalletBalance.svelte' From 40cdd6e2a96ef1c2cf28da1a471c53a5e0ea35da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bego=C3=B1a=20Alvarez?= Date: Thu, 17 Feb 2022 19:10:04 +0100 Subject: [PATCH 002/171] chore: move selectedAccount to global state --- .../shared/components/ActivityDetail.svelte | 1 - .../components/modals/AccountActions.svelte | 20 +++++++++++------- packages/shared/lib/wallet.ts | 5 ++++- .../routes/dashboard/wallet/Wallet.svelte | 4 +--- .../wallet/views/AccountActions.svelte | 10 +++------ .../dashboard/wallet/views/BarChart.svelte | 8 ++----- .../dashboard/wallet/views/LineChart.svelte | 3 +-- .../dashboard/wallet/views/Receive.svelte | 21 +++++++++---------- .../routes/dashboard/wallet/views/Send.svelte | 14 +++++++------ 9 files changed, 41 insertions(+), 45 deletions(-) diff --git a/packages/shared/components/ActivityDetail.svelte b/packages/shared/components/ActivityDetail.svelte index e72bb8325e4..5874351fba5 100644 --- a/packages/shared/components/ActivityDetail.svelte +++ b/packages/shared/components/ActivityDetail.svelte @@ -38,7 +38,6 @@ const txPayload = payload?.type === 'Transaction' ? payload : undefined const accounts = getContext>('walletAccounts') - const account = getContext>('selectedAccount') const explorerLink = getOfficialExplorer($accounts[0].clientOptions.network) let senderAccount: WalletAccount diff --git a/packages/shared/components/modals/AccountActions.svelte b/packages/shared/components/modals/AccountActions.svelte index e6ba1ebc4a3..f0370d405c9 100644 --- a/packages/shared/components/modals/AccountActions.svelte +++ b/packages/shared/components/modals/AccountActions.svelte @@ -4,7 +4,7 @@ import { activeProfile, updateProfile } from 'shared/lib/profile' import { accountRoute } from 'shared/lib/router' import { AccountRoutes } from 'shared/lib/typings/routes' - import { asyncRemoveWalletAccount, selectedAccountId, selectedMessage } from 'shared/lib/wallet' + import { asyncRemoveWalletAccount, selectedAccount, selectedAccountId, selectedMessage } from 'shared/lib/wallet' import { getContext } from 'svelte' import type { Readable } from 'svelte/store' import type { Locale } from 'shared/lib/typings/i18n' @@ -16,14 +16,15 @@ export let isActive - const account = getContext>('selectedAccount') const viewableAccounts = getContext>('viewableAccounts') const allAccounts = getContext>('walletAccounts') const hiddenAccounts = $activeProfile?.hiddenAccounts ?? [] const hidden = hiddenAccounts.includes($selectedAccountId) const canDelete = - $account.index === $allAccounts.length - 1 && $account.rawIotaBalance === 0 && $account.messages.length === 0 + $selectedAccount.index === $allAccounts.length - 1 && + $selectedAccount.rawIotaBalance === 0 && + $selectedAccount.messages.length === 0 const handleCustomiseAccountClick = () => { accountRoute.set(AccountRoutes.Manage) @@ -31,12 +32,12 @@ } const handleViewAddressHistoryClick = () => { - openPopup({ type: 'addressHistory', props: { account } }) + openPopup({ type: 'addressHistory', props: { selectedAccount } }) isActive = false } function handleExportTransactionHistoryClick() { - openPopup({ type: 'exportTransactionHistory', props: { account }, hideClose: false }) + openPopup({ type: 'exportTransactionHistory', props: { selectedAccount }, hideClose: false }) isActive = false } @@ -44,13 +45,14 @@ openPopup({ type: 'hideAccount', props: { - account, + selectedAccount, hasMultipleAccounts: $viewableAccounts.length > 1, hideAccount: (id) => { if (!hiddenAccounts.includes(id)) { hiddenAccounts.push(id) updateProfile('hiddenAccounts', hiddenAccounts) } + // TODO: handle for single wallet view selectedAccountId.set(null) selectedMessage.set(null) accountRoute.set(AccountRoutes.Init) @@ -64,15 +66,16 @@ openPopup({ type: 'deleteAccount', props: { - account, + selectedAccount, hasMultipleAccounts: $viewableAccounts.length > 1, deleteAccount: async (id) => { - await asyncRemoveWalletAccount(get(account).id) + await asyncRemoveWalletAccount(get(selectedAccount).id) if (!hiddenAccounts.includes(id)) { hiddenAccounts.push(id) updateProfile('hiddenAccounts', hiddenAccounts) } + // TODO: handle for single wallet view selectedAccountId.set(null) selectedMessage.set(null) accountRoute.set(AccountRoutes.Init) @@ -88,6 +91,7 @@ hiddenAccounts.splice(idx, 1) updateProfile('hiddenAccounts', hiddenAccounts) } + // TODO: handle for single wallet view selectedAccountId.set(null) selectedMessage.set(null) accountRoute.set(AccountRoutes.Init) diff --git a/packages/shared/lib/wallet.ts b/packages/shared/lib/wallet.ts index 8f505865871..d456531c84e 100644 --- a/packages/shared/lib/wallet.ts +++ b/packages/shared/lib/wallet.ts @@ -1,7 +1,7 @@ import type { ErrorEventPayload, TransferState } from 'shared/lib/typings/events' import type { Payload } from 'shared/lib/typings/message' import { formatUnitBestMatch } from 'shared/lib/units' -import { get, writable } from 'svelte/store' +import { derived, get, writable } from 'svelte/store' import { mnemonic } from './app' import { convertToFiat, currencies, exchangeRates, formatCurrency } from './currency' import { deepCopy } from './helpers' @@ -126,6 +126,9 @@ export const resetWallet = (): void => { } export const selectedAccountId = writable(null) +export const selectedAccount = derived([selectedAccountId, get(wallet).accounts], ([$selectedAccountId, $accounts]) => + $accounts.find((acc) => acc.id === $selectedAccountId) +) export const selectedMessage = writable(null) diff --git a/packages/shared/routes/dashboard/wallet/Wallet.svelte b/packages/shared/routes/dashboard/wallet/Wallet.svelte index 00a2530a7ef..d0b33cea2c5 100644 --- a/packages/shared/routes/dashboard/wallet/Wallet.svelte +++ b/packages/shared/routes/dashboard/wallet/Wallet.svelte @@ -49,6 +49,7 @@ prepareAccountInfo, processMigratedTransactions, removeEventListeners, + selectedAccount, selectedAccountId, transferState, updateBalanceOverview, @@ -78,9 +79,6 @@ const walletBalanceHistory = derived(accountsBalanceHistory, ($accountsBalanceHistory) => getWalletBalanceHistory($accountsBalanceHistory) ) - const selectedAccount = derived([selectedAccountId, accounts], ([$selectedAccountId, $accounts]) => - $accounts.find((acc) => acc.id === $selectedAccountId) - ) const accountTransactions = derived([selectedAccount], ([$selectedAccount]) => $selectedAccount ? getAccountMessages($selectedAccount) : [] ) diff --git a/packages/shared/routes/dashboard/wallet/views/AccountActions.svelte b/packages/shared/routes/dashboard/wallet/views/AccountActions.svelte index 2e48db60a23..95ca46ae10b 100644 --- a/packages/shared/routes/dashboard/wallet/views/AccountActions.svelte +++ b/packages/shared/routes/dashboard/wallet/views/AccountActions.svelte @@ -2,13 +2,10 @@ import { Button, Text } from 'shared/components' import { activeProfile } from 'shared/lib/profile' import { accountRoute } from 'shared/lib/router' + import type { Locale } from 'shared/lib/typings/i18n' import { AccountRoutes } from 'shared/lib/typings/routes' - import { selectedAccountId } from 'shared/lib/wallet' - import { getContext } from 'svelte' - import type { Readable } from 'svelte/store' + import { selectedAccount, selectedAccountId } from 'shared/lib/wallet' import { ManageAccount, Receive, Send } from '.' - import { Locale } from 'shared/lib/typings/i18n' - import { WalletAccount } from 'shared/lib/typings/wallet' export let locale: Locale @@ -20,7 +17,6 @@ const hiddenAccounts = $activeProfile?.hiddenAccounts ?? [] - const account = getContext>('selectedAccount') function handleSendClick() { accountRoute.set(AccountRoutes.Send) } @@ -45,5 +41,5 @@ {:else if $accountRoute === AccountRoutes.Send} {:else if $accountRoute === AccountRoutes.Manage} - + {/if} diff --git a/packages/shared/routes/dashboard/wallet/views/BarChart.svelte b/packages/shared/routes/dashboard/wallet/views/BarChart.svelte index 5cda1592ee8..308c9e7c3cc 100644 --- a/packages/shared/routes/dashboard/wallet/views/BarChart.svelte +++ b/packages/shared/routes/dashboard/wallet/views/BarChart.svelte @@ -1,16 +1,12 @@ -
+
- {#if !$currentAccount} + {#if !$selectedAccount}
{locale('general.receiveFunds')} @@ -45,7 +44,7 @@
- +
@@ -90,12 +89,12 @@ ? `${$activeProfile.settings.networkConfig.network.name} ${locale('general.address')}` : locale('general.myAddress')} - {selectedAccount.depositAddress} + {selectedSendAccount.depositAddress}
diff --git a/packages/shared/routes/dashboard/wallet/views/Send.svelte b/packages/shared/routes/dashboard/wallet/views/Send.svelte index a0f7aae63bc..ffb4ad731ef 100644 --- a/packages/shared/routes/dashboard/wallet/views/Send.svelte +++ b/packages/shared/routes/dashboard/wallet/views/Send.svelte @@ -37,7 +37,7 @@ import type { WalletAccount } from 'shared/lib/typings/wallet' import { changeUnits, formatUnitPrecision } from 'shared/lib/units' import { ADDRESS_LENGTH, validateBech32Address } from 'shared/lib/utils' - import { DUST_THRESHOLD, isTransferring, transferState, wallet } from 'shared/lib/wallet' + import { DUST_THRESHOLD, isTransferring, selectedAccount, transferState, wallet } from 'shared/lib/wallet' import { getContext, onDestroy, onMount } from 'svelte' import type { Readable } from 'svelte/store' import { get } from 'svelte/store' @@ -50,7 +50,6 @@ const { accounts } = $wallet - const account = getContext>('selectedAccount') const liveAccounts = getContext>('liveAccounts') enum SEND_TYPE { @@ -64,7 +63,7 @@ let address = '' let to = undefined let amountError = '' - const addressPrefix = ($account ?? $liveAccounts[0])?.depositAddress?.split('1')?.[0] + const addressPrefix = ($selectedAccount ?? $liveAccounts[0])?.depositAddress?.split('1')?.[0] let addressError = '' let toError = '' let amountRaw @@ -128,7 +127,9 @@ if (from) { from = accountsDropdownItems.find((a) => a.id === from.id) } else { - from = $account ? accountsDropdownItems.find((a) => a.id === $account.id) : accountsDropdownItems[0] + from = $selectedAccount + ? accountsDropdownItems.find((a) => a.id === $selectedAccount.id) + : accountsDropdownItems[0] } if (to) { to = accountsDropdownItems.find((a) => a.id === to.id) @@ -428,7 +429,7 @@ clearSendParams() accountRoute.set(AccountRoutes.Init) - if (!$account) { + if (!$selectedAccount) { // TODO: handle this case for single wallet view accountRoute.set(AccountRoutes.Init) } @@ -532,7 +533,8 @@
- {#if !$account} + + {#if !$selectedAccount}
Date: Fri, 18 Feb 2022 17:00:14 +0100 Subject: [PATCH 003/171] fix: wrong prop name --- packages/shared/components/modals/AccountActions.svelte | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/shared/components/modals/AccountActions.svelte b/packages/shared/components/modals/AccountActions.svelte index f0370d405c9..0162b088218 100644 --- a/packages/shared/components/modals/AccountActions.svelte +++ b/packages/shared/components/modals/AccountActions.svelte @@ -32,12 +32,12 @@ } const handleViewAddressHistoryClick = () => { - openPopup({ type: 'addressHistory', props: { selectedAccount } }) + openPopup({ type: 'addressHistory', props: { account: selectedAccount } }) isActive = false } function handleExportTransactionHistoryClick() { - openPopup({ type: 'exportTransactionHistory', props: { selectedAccount }, hideClose: false }) + openPopup({ type: 'exportTransactionHistory', props: { account: selectedAccount }, hideClose: false }) isActive = false } @@ -45,7 +45,7 @@ openPopup({ type: 'hideAccount', props: { - selectedAccount, + account: selectedAccount, hasMultipleAccounts: $viewableAccounts.length > 1, hideAccount: (id) => { if (!hiddenAccounts.includes(id)) { @@ -66,7 +66,7 @@ openPopup({ type: 'deleteAccount', props: { - selectedAccount, + account: selectedAccount, hasMultipleAccounts: $viewableAccounts.length > 1, deleteAccount: async (id) => { await asyncRemoveWalletAccount(get(selectedAccount).id) From 796dd569cbfc7aec1e43c0cbaad388871e8a3d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bego=C3=B1a=20Alvarez?= Date: Sun, 20 Feb 2022 18:19:40 +0100 Subject: [PATCH 004/171] feat: remove dead contexts --- .../shared/routes/dashboard/wallet/Wallet.svelte | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/shared/routes/dashboard/wallet/Wallet.svelte b/packages/shared/routes/dashboard/wallet/Wallet.svelte index d0b33cea2c5..e90c76ef389 100644 --- a/packages/shared/routes/dashboard/wallet/Wallet.svelte +++ b/packages/shared/routes/dashboard/wallet/Wallet.svelte @@ -79,9 +79,6 @@ const walletBalanceHistory = derived(accountsBalanceHistory, ($accountsBalanceHistory) => getWalletBalanceHistory($accountsBalanceHistory) ) - const accountTransactions = derived([selectedAccount], ([$selectedAccount]) => - $selectedAccount ? getAccountMessages($selectedAccount) : [] - ) $: navAccounts = $selectedAccount ? $viewableAccounts.map(({ id, alias, color }) => ({ id, alias, color, active: $selectedAccount.id === id })) @@ -141,11 +138,8 @@ setContext>('walletAccounts', accounts) setContext>('viewableAccounts', viewableAccounts) setContext>('liveAccounts', liveAccounts) - setContext>('walletAccountsLoaded', accountsLoaded) setContext>('walletTransactions', transactions) - setContext>('selectedAccount', selectedAccount) setContext>('accountsBalanceHistory', accountsBalanceHistory) - setContext>('accountTransactions', accountTransactions) setContext>('walletBalanceHistory', walletBalanceHistory) let isGeneratingAddress = false @@ -544,7 +538,11 @@ - +
From b7e363d1b60b3f2cd4b736394b0514fed0d1a112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bego=C3=B1a=20Alvarez?= Date: Sun, 20 Feb 2022 19:46:53 +0100 Subject: [PATCH 005/171] chore: refactor selectedAccountId with selectedAccount --- .../components/modals/AccountActions.svelte | 9 +++---- .../components/popups/DeleteAccount.svelte | 14 ++++++----- .../components/popups/HideAccount.svelte | 15 ++++++------ packages/shared/lib/wallet.ts | 24 +++++++++++++++---- .../shared/routes/dashboard/Dashboard.svelte | 9 ++----- .../routes/dashboard/wallet/Wallet.svelte | 23 ++++++++++++------ .../wallet/views/AccountActions.svelte | 4 ++-- .../wallet/views/AccountHistory.svelte | 4 ++-- .../wallet/views/AccountNavigation.svelte | 10 ++++---- .../wallet/views/ManageAccount.svelte | 8 +++---- .../wallet/views/WalletActions.svelte | 4 ++-- .../wallet/views/WalletHistory.svelte | 4 ++-- 12 files changed, 73 insertions(+), 55 deletions(-) diff --git a/packages/shared/components/modals/AccountActions.svelte b/packages/shared/components/modals/AccountActions.svelte index 0162b088218..a2f23b705db 100644 --- a/packages/shared/components/modals/AccountActions.svelte +++ b/packages/shared/components/modals/AccountActions.svelte @@ -4,7 +4,7 @@ import { activeProfile, updateProfile } from 'shared/lib/profile' import { accountRoute } from 'shared/lib/router' import { AccountRoutes } from 'shared/lib/typings/routes' - import { asyncRemoveWalletAccount, selectedAccount, selectedAccountId, selectedMessage } from 'shared/lib/wallet' + import { asyncRemoveWalletAccount, selectedAccount, selectedMessage } from 'shared/lib/wallet' import { getContext } from 'svelte' import type { Readable } from 'svelte/store' import type { Locale } from 'shared/lib/typings/i18n' @@ -20,7 +20,7 @@ const allAccounts = getContext>('walletAccounts') const hiddenAccounts = $activeProfile?.hiddenAccounts ?? [] - const hidden = hiddenAccounts.includes($selectedAccountId) + const hidden = hiddenAccounts.includes($selectedAccount?.id) const canDelete = $selectedAccount.index === $allAccounts.length - 1 && $selectedAccount.rawIotaBalance === 0 && @@ -53,7 +53,6 @@ updateProfile('hiddenAccounts', hiddenAccounts) } // TODO: handle for single wallet view - selectedAccountId.set(null) selectedMessage.set(null) accountRoute.set(AccountRoutes.Init) }, @@ -76,7 +75,6 @@ updateProfile('hiddenAccounts', hiddenAccounts) } // TODO: handle for single wallet view - selectedAccountId.set(null) selectedMessage.set(null) accountRoute.set(AccountRoutes.Init) }, @@ -86,13 +84,12 @@ } const handleShowAccountClick = () => { - const idx = hiddenAccounts.indexOf($selectedAccountId) + const idx = hiddenAccounts.indexOf($selectedAccount?.id) if (idx >= 0) { hiddenAccounts.splice(idx, 1) updateProfile('hiddenAccounts', hiddenAccounts) } // TODO: handle for single wallet view - selectedAccountId.set(null) selectedMessage.set(null) accountRoute.set(AccountRoutes.Init) } diff --git a/packages/shared/components/popups/DeleteAccount.svelte b/packages/shared/components/popups/DeleteAccount.svelte index e250377da98..4b91fe52ebf 100644 --- a/packages/shared/components/popups/DeleteAccount.svelte +++ b/packages/shared/components/popups/DeleteAccount.svelte @@ -2,14 +2,16 @@ import { Button, Password, Text } from 'shared/components' import { closePopup } from 'shared/lib/popup' import { isSoftwareProfile } from 'shared/lib/profile' - import { api, selectedAccountId } from 'shared/lib/wallet' - import { AccountIdentifier } from 'shared/lib/typings/account' - import { Locale } from 'shared/lib/typings/i18n' + import type { AccountIdentifier } from 'shared/lib/typings/account' + import type { Locale } from 'shared/lib/typings/i18n' + import type { WalletAccount } from 'shared/lib/typings/wallet' + import { api } from 'shared/lib/wallet' + import type { Writable } from 'svelte/store' export let locale: Locale - export let account - export let deleteAccount = (selectedAccountId: AccountIdentifier): void => {} + export let account: Writable + export let deleteAccount: (id: AccountIdentifier) => void = () => {} export let hasMultipleAccounts let password @@ -42,7 +44,7 @@ function triggerDeleteAccount() { isBusy = false closePopup() - deleteAccount($selectedAccountId) + deleteAccount($account?.id) } diff --git a/packages/shared/components/popups/HideAccount.svelte b/packages/shared/components/popups/HideAccount.svelte index e75c5a833b1..ba9d519ad47 100644 --- a/packages/shared/components/popups/HideAccount.svelte +++ b/packages/shared/components/popups/HideAccount.svelte @@ -4,18 +4,19 @@ import { closePopup } from 'shared/lib/popup' import { isSoftwareProfile } from 'shared/lib/profile' import { accountRoute } from 'shared/lib/router' + import type { AccountIdentifier } from 'shared/lib/typings/account' + import type { Locale } from 'shared/lib/typings/i18n' import { AccountRoutes } from 'shared/lib/typings/routes' - import { api, selectedAccountId } from 'shared/lib/wallet' - import { AccountIdentifier } from 'shared/lib/typings/account' - import { Locale } from 'shared/lib/typings/i18n' - import { WalletAccount } from 'shared/lib/typings/wallet' + import type { WalletAccount } from 'shared/lib/typings/wallet' + import { api } from 'shared/lib/wallet' + import type { Writable } from 'svelte/store' export let locale: Locale - export let account: WalletAccount + export let account: Writable export let hasMultipleAccounts - export let hideAccount = (selectedAccountId: AccountIdentifier): void => {} + export let hideAccount: (id: AccountIdentifier) => void = () => {} let canDelete $: canDelete = $account ? $account.rawIotaBalance === 0 : false @@ -54,7 +55,7 @@ function triggerHideAccount() { isBusy = false closePopup() - hideAccount($selectedAccountId) + hideAccount($account?.id) } diff --git a/packages/shared/lib/wallet.ts b/packages/shared/lib/wallet.ts index d456531c84e..79665ce924d 100644 --- a/packages/shared/lib/wallet.ts +++ b/packages/shared/lib/wallet.ts @@ -19,7 +19,14 @@ import { openPopup } from './popup' import { activeProfile, isLedgerProfile, isStrongholdLocked, updateProfile } from './profile' import { walletSetupType } from './router' import { WALLET, WalletApi } from './shell/walletApi' -import type { Account, Account as BaseAccount, SignerType, SyncAccountOptions, SyncedAccount } from './typings/account' +import type { + Account, + Account as BaseAccount, + AccountIdentifier, + SignerType, + SyncAccountOptions, + SyncedAccount, +} from './typings/account' import type { Address } from './typings/address' import type { IActorHandler } from './typings/bridge' import { CurrencyTypes } from './typings/currency' @@ -113,7 +120,7 @@ export const resetWallet = (): void => { accounts.set([]) accountsLoaded.set(false) internalTransfersInProgress.set({}) - selectedAccountId.set(null) + setSelectedAccount(null) selectedMessage.set(null) isTransferring.set(false) transferState.set(null) @@ -125,10 +132,17 @@ export const resetWallet = (): void => { walletSetupType.set(null) } -export const selectedAccountId = writable(null) -export const selectedAccount = derived([selectedAccountId, get(wallet).accounts], ([$selectedAccountId, $accounts]) => - $accounts.find((acc) => acc.id === $selectedAccountId) +// used to make selectedAccount reactive to changes in the wallet +const _selectedAccountId = writable(null) + +export const selectedAccount = derived([_selectedAccountId, get(wallet).accounts], ([$_selectedAccountId, $accounts]) => + $accounts.find((acc) => acc.id === $_selectedAccountId) ) +export const setSelectedAccount = (id: AccountIdentifier): void => _selectedAccountId.set(id) +export const getAccountById = (id: AccountIdentifier): WalletAccount | null => { + const accounts = get(wallet)?.accounts + return get(accounts)?.find((account) => account.id === id) || null +} export const selectedMessage = writable(null) diff --git a/packages/shared/routes/dashboard/Dashboard.svelte b/packages/shared/routes/dashboard/Dashboard.svelte index 646486ba92f..5a815565284 100644 --- a/packages/shared/routes/dashboard/Dashboard.svelte +++ b/packages/shared/routes/dashboard/Dashboard.svelte @@ -24,7 +24,7 @@ import { api, isBackgroundSyncing, - selectedAccountId, + setSelectedAccount, STRONGHOLD_PASSWORD_CLEAR_INTERVAL_SECS, wallet, } from 'shared/lib/wallet' @@ -104,7 +104,7 @@ contextData.type === 'valueTx') && contextData.accountId ) { - selectedAccountId.set(contextData.accountId) + setSelectedAccount(contextData.accountId) if (get(dashboardRoute) !== Tabs.Wallet) { dashboardRoute.set(Tabs.Wallet) } @@ -273,11 +273,6 @@ $: if ($activeProfile && $isLedgerProfile && !$isPollingLedgerDeviceStatus) { pollLedgerDeviceStatus(false, LEDGER_STATUS_POLL_INTERVAL) } - - // TODO: remove, dev only - $: if (accountsLoaded) { - selectedAccountId.set($accounts?.[0]?.id) - } diff --git a/packages/shared/routes/dashboard/wallet/Wallet.svelte b/packages/shared/routes/dashboard/wallet/Wallet.svelte index e90c76ef389..35d57332041 100644 --- a/packages/shared/routes/dashboard/wallet/Wallet.svelte +++ b/packages/shared/routes/dashboard/wallet/Wallet.svelte @@ -50,7 +50,7 @@ processMigratedTransactions, removeEventListeners, selectedAccount, - selectedAccountId, + setSelectedAccount, transferState, updateBalanceOverview, wallet, @@ -80,9 +80,12 @@ getWalletBalanceHistory($accountsBalanceHistory) ) - $: navAccounts = $selectedAccount - ? $viewableAccounts.map(({ id, alias, color }) => ({ id, alias, color, active: $selectedAccount.id === id })) - : [] + $: navAccounts = $viewableAccounts?.map(({ id, alias, color }) => ({ + id, + alias, + color, + active: $selectedAccount?.id === id, + })) const viewableAccounts: Readable = derived( [activeProfile, accounts], @@ -146,7 +149,8 @@ // If account changes force regeneration of Ledger receive address $: { - $selectedAccountId + // TODO: fix this, selectedAccount changes triggers too many times + selectedAccount?.id if ($isLedgerProfile) { hasGeneratedALedgerReceiveAddress.set(false) } @@ -480,6 +484,11 @@ drawer.open() } + $: if ($accountsLoaded && $viewableAccounts.length) { + // TODO: persist last selected account + setSelectedAccount($viewableAccounts[0]?.id) + } + onMount(() => { // If we are in settings when logged out the router reset // switches back to the wallet, but there is no longer @@ -516,12 +525,12 @@ {#if $selectedAccount}
- {#key $selectedAccountId} + {#key $selectedAccount?.id}
- {#if hiddenAccounts.includes($selectedAccountId)} + {#if hiddenAccounts.includes($selectedAccount?.id)} {locale('general.accountRemoved')} {:else} -
- -
- {/if} {#if $isLedgerProfile && !$hasGeneratedALedgerReceiveAddress}
- +
@@ -87,12 +54,12 @@ ? `${$activeProfile.settings.networkConfig.network.name} ${localize('general.address')}` : localize('general.myAddress')} - {selectedSendAccount.depositAddress} + {$selectedAccount.depositAddress}
diff --git a/packages/shared/routes/dashboard/wallet/views/Send.svelte b/packages/shared/routes/dashboard/wallet/views/Send.svelte index 263f3a2b82a..0500707b24e 100644 --- a/packages/shared/routes/dashboard/wallet/views/Send.svelte +++ b/packages/shared/routes/dashboard/wallet/views/Send.svelte @@ -118,17 +118,8 @@ } let accountsDropdownItems - let from $: { accountsDropdownItems = $liveAccounts.map((acc) => format(acc)) - - if (from) { - from = accountsDropdownItems.find((a) => a.id === from.id) - } else { - from = $selectedAccount - ? accountsDropdownItems.find((a) => a.id === $selectedAccount.id) - : accountsDropdownItems[0] - } if (to) { to = accountsDropdownItems.find((a) => a.id === to.id) } @@ -277,8 +268,6 @@ } } - let _ledgerDeviceState - $: _ledgerDeviceState = $ledgerDeviceState $: { checkLedgerDeviceState($ledgerDeviceState, 'warning', true) } @@ -294,19 +283,8 @@ clearErrors() } - const handleFromSelect = (item) => { - from = item - if (to === from) { - to = $liveAccounts.length === 2 ? accountsDropdownItems[from.id === $liveAccounts[0].id ? 1 : 0] : undefined - } - clearErrors() - } - const handleToSelect = (item) => { to = item - if (from === to) { - from = undefined - } clearErrors() } @@ -320,10 +298,11 @@ const isFiat = isFiatCurrency(unit) const isMaxAmount = - amount === convertToFiat(from.balance, $currencies[CurrencyTypes.USD], $exchangeRates[unit]).toString() - const hasDustRemaining = Math.abs(from.balance - _amount) < DUST_THRESHOLD + amount === + convertToFiat($selectedAccount.balance, $currencies[CurrencyTypes.USD], $exchangeRates[unit]).toString() + const hasDustRemaining = Math.abs($selectedAccount.balance - _amount) < DUST_THRESHOLD - return isFiat && isMaxAmount && hasDustRemaining ? from.balance : _amount + return isFiat && isMaxAmount && hasDustRemaining ? $selectedAccount.balance : _amount } const handleSendClick = () => { @@ -362,7 +341,7 @@ : changeUnits(amountAsFloat, unit, Unit.i) amountRaw = ensureMaxAmount(amountRaw) - if (amountRaw > from.balance) { + if (amountRaw > $selectedAccount.balance) { amountError = localize('error.send.amountTooHigh') } else if (amountRaw <= 0) { amountError = localize('error.send.amountZero') @@ -392,7 +371,7 @@ openPopup({ type: 'transaction', props: { - accountId: from.id, + accountId: $selectedAccount.id, internal: internal || accountAlias, amount: amountRaw, unit, @@ -413,8 +392,8 @@ * in another account. Send parameters are reset once the transfer completes. */ isInternal - ? onInternalTransfer(from.id, to.id, amountRaw, selectedSendType === SEND_TYPE.INTERNAL) - : onSend(from.id, address, amountRaw) + ? onInternalTransfer($selectedAccount.id, to.id, amountRaw, selectedSendType === SEND_TYPE.INTERNAL) + : onSend($selectedAccount.id, address, amountRaw) if ($isSoftwareProfile) { _send(isInternal) @@ -425,12 +404,7 @@ const handleBackClick = () => { clearSendParams() - accountRoute.set(AccountRoutes.Init) - if (!$selectedAccount) { - // TODO: handle this case for single wallet view - accountRoute.set(AccountRoutes.Init) - } } const format = (account: WalletAccount) => ({ @@ -441,8 +415,10 @@ const handleMaxClick = () => { amount = isFiatCurrency(unit) - ? formatNumber(convertToFiat(from.balance, $currencies[CurrencyTypes.USD], $exchangeRates[unit])) - : formatUnitPrecision(from.balance, unit, false) + ? formatNumber( + convertToFiat($selectedAccount.balance, $currencies[CurrencyTypes.USD], $exchangeRates[unit]) + ) + : formatUnitPrecision($selectedAccount.balance, unit, false) } const updateFromSendParams = (sendParams) => { @@ -451,8 +427,11 @@ const rawAmount = changeUnits(sendParams.amount, unit, Unit.i) amount = sendParams.amount === 0 ? '' : formatUnitPrecision(rawAmount, unit, false) address = sendParams.address - if (from && accountsDropdownItems) { - to = $liveAccounts.length === 2 ? accountsDropdownItems[from.id === $liveAccounts[0].id ? 1 : 0] : to + if (accountsDropdownItems) { + to = + $liveAccounts.length === 2 + ? accountsDropdownItems[$selectedAccount.id === $liveAccounts[0].id ? 1 : 0] + : to } } @@ -531,26 +510,13 @@
- - {#if !$selectedAccount} -
- -
- {/if}
{#if selectedSendType === SEND_TYPE.INTERNAL} from && a.id !== from.id)} + items={accountsDropdownItems.filter((a) => a.id !== $selectedAccount.id)} onSelect={handleToSelect} disabled={$isTransferring || $liveAccounts.length === 2} error={toError} @@ -573,7 +539,6 @@ bind:amount bind:unit onMaxClick={handleMaxClick} - {locale} disabled={$isTransferring} autofocus={selectedSendType === SEND_TYPE.INTERNAL && $liveAccounts.length === 2} /> From d8743b4f642cbe237125fc6c0124230f5407f8c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bego=C3=B1a=20Alvarez?= Date: Mon, 21 Feb 2022 15:16:09 +0100 Subject: [PATCH 009/171] chore: remove unnecessary files --- .../wallet/views/AccountHistory.svelte | 20 +- .../wallet/views/WalletActions.svelte | 142 --------------- .../wallet/views/WalletBalance.svelte | 84 --------- .../wallet/views/WalletHistory.svelte | 172 ------------------ .../routes/dashboard/wallet/views/index.js | 3 - 5 files changed, 19 insertions(+), 402 deletions(-) delete mode 100644 packages/shared/routes/dashboard/wallet/views/WalletActions.svelte delete mode 100644 packages/shared/routes/dashboard/wallet/views/WalletBalance.svelte delete mode 100644 packages/shared/routes/dashboard/wallet/views/WalletHistory.svelte diff --git a/packages/shared/routes/dashboard/wallet/views/AccountHistory.svelte b/packages/shared/routes/dashboard/wallet/views/AccountHistory.svelte index f313f890462..7c91ffdde74 100644 --- a/packages/shared/routes/dashboard/wallet/views/AccountHistory.svelte +++ b/packages/shared/routes/dashboard/wallet/views/AccountHistory.svelte @@ -12,6 +12,7 @@ import { api, getIncomingFlag, + isFirstSessionSync, isSyncing, receiverAddressesFromTransactionPayload, selectedAccount, @@ -133,6 +134,21 @@ } else { queryTransactions = filteredTransactions } + + function shouldShowFirstSync(): boolean { + /** + * NOTE: The following conditions must be satisfied + * for the "syncing history, ..." message to show: + * + * 1. It must be the first sync of the user's session + * 2. The wallet setup type must exist (a null value indicates an existing profile) + * 3. The wallet setup type cannot be new (if it's new then there's no tx history to sync) + * 4. Account must have no transactions (the length of $transactions must be zero) + */ + return ( + $isFirstSessionSync && $walletSetupType && $walletSetupType !== SetupType.New && $transactions.length === 0 + ) + }
@@ -199,7 +215,9 @@ {:else}
- {#if queryTransactions.length} + {#if $isSyncing && shouldShowFirstSync()} + {localize('general.firstSync')} + {:else if queryTransactions.length} {#each queryTransactions as transaction} handleTransactionClick(transaction)} {...transaction} {color} /> {/each} diff --git a/packages/shared/routes/dashboard/wallet/views/WalletActions.svelte b/packages/shared/routes/dashboard/wallet/views/WalletActions.svelte deleted file mode 100644 index ef0fee3e4fd..00000000000 --- a/packages/shared/routes/dashboard/wallet/views/WalletActions.svelte +++ /dev/null @@ -1,142 +0,0 @@ - - -{#if $mobile} - {#if $walletRoute === WalletRoutes.Init || $walletRoute === WalletRoutes.Send || $walletRoute === WalletRoutes.Receive || $walletRoute === WalletRoutes.CreateAccount} -
-
-
- -
- {#if $viewableAccounts.length > 0} -
- {#each $viewableAccounts as account} -
- {:else} - {locale('general.noAccounts')} - {/if} -
-
- walletRoute.set(WalletRoutes.Init)}> - {#if $walletRoute === WalletRoutes.Send} - - {:else if $walletRoute === WalletRoutes.Receive} - - {/if} - - {/if} -{:else if $walletRoute === WalletRoutes.Init} -
-
-
- {locale('general.myAccounts')} - -
- {#if $viewableAccounts.length > 0} -
- {#each $viewableAccounts as account} -
- {:else} - {locale('general.noAccounts')} - {/if} -
-
-{:else if $walletRoute === WalletRoutes.Send} - -{:else if $walletRoute === WalletRoutes.Receive} - -{/if} - - diff --git a/packages/shared/routes/dashboard/wallet/views/WalletBalance.svelte b/packages/shared/routes/dashboard/wallet/views/WalletBalance.svelte deleted file mode 100644 index 2ff801c3277..00000000000 --- a/packages/shared/routes/dashboard/wallet/views/WalletBalance.svelte +++ /dev/null @@ -1,84 +0,0 @@ - - - -
- {#if !$mobile} -

{locale('general.balance')}

- {/if} - -
- - {#if $walletRoute === WalletRoutes.Init || $mobile} - {#if $accounts.length > 0 || $mobile} - -
- - -
- {/if} - {/if} -
- - diff --git a/packages/shared/routes/dashboard/wallet/views/WalletHistory.svelte b/packages/shared/routes/dashboard/wallet/views/WalletHistory.svelte deleted file mode 100644 index e12ebeb279c..00000000000 --- a/packages/shared/routes/dashboard/wallet/views/WalletHistory.svelte +++ /dev/null @@ -1,172 +0,0 @@ - - -{#if $mobile} -
- - {#if $isSyncing && shouldShowFirstSync()} - {locale('general.firstSync')} - {:else if $transactions?.length} - handleTransactionClick(transaction)} - color={$accounts.find((acc) => acc.index === transaction.account)?.color} - {locale} - includeFullSender - /> - {:else} - {locale('general.noRecentHistory')} - {/if} - -
- - -
- Transaction -
- Reference - For the pizza -
-
- Input Address - iota1qq2hdmvm9k3z5uvq6atreclgy6gc98dpshj3nd872jgqyn3dstzdvkx9crx -
-
- Receive Address - iota1qq2hdmvm9k3z5uvq6atreclgy6gc98dpshj3nd872jgqyn3dstzdvkx9crx -
-
- -
-{:else} -
-
- {locale('general.latestTransactions')} - -
-
- {#if $isSyncing && shouldShowFirstSync()} -
- {locale('general.firstSync')} -
- {:else if $transactions?.length} - {#each $transactions as transaction} - handleTransactionClick(transaction)} - color={$accounts.find((acc) => acc.index === transaction.account)?.color} - {locale} - includeFullSender - /> - {/each} - {:else} -
- {locale('general.noRecentHistory')} -
- {/if} -
-
-{/if} diff --git a/packages/shared/routes/dashboard/wallet/views/index.js b/packages/shared/routes/dashboard/wallet/views/index.js index c677bb7fd97..1c708238bab 100644 --- a/packages/shared/routes/dashboard/wallet/views/index.js +++ b/packages/shared/routes/dashboard/wallet/views/index.js @@ -2,11 +2,8 @@ export { default as Receive } from './Receive.svelte' export { default as Send } from './Send.svelte' export { default as CreateAccount } from './CreateAccount.svelte' export { default as ManageAccount } from './ManageAccount.svelte' -export { default as WalletBalance } from './WalletBalance.svelte' -export { default as WalletActions } from './WalletActions.svelte' export { default as LineChart } from './LineChart.svelte' export { default as BarChart } from './BarChart.svelte' -export { default as WalletHistory } from './WalletHistory.svelte' export { default as Security } from './Security.svelte' export { default as AccountNavigation } from './AccountNavigation.svelte' export { default as AccountBalance } from './AccountBalance.svelte' From 5c6d922829b0edacb5a16f3e34ccfd7a83b13d21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bego=C3=B1a=20Alvarez?= Date: Mon, 21 Feb 2022 15:31:57 +0100 Subject: [PATCH 010/171] fix: missing import on prev commit --- .../routes/dashboard/wallet/views/AccountHistory.svelte | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/shared/routes/dashboard/wallet/views/AccountHistory.svelte b/packages/shared/routes/dashboard/wallet/views/AccountHistory.svelte index 7c91ffdde74..14e7a19480e 100644 --- a/packages/shared/routes/dashboard/wallet/views/AccountHistory.svelte +++ b/packages/shared/routes/dashboard/wallet/views/AccountHistory.svelte @@ -5,7 +5,9 @@ import { showAppNotification } from 'shared/lib/notifications' import { openPopup } from 'shared/lib/popup' import { isLedgerProfile, isSoftwareProfile } from 'shared/lib/profile' + import { walletSetupType } from 'shared/lib/router' import type { Transaction } from 'shared/lib/typings/message' + import { SetupType } from 'shared/lib/typings/routes' import type { AccountMessage } from 'shared/lib/typings/wallet' import { formatUnitBestMatch } from 'shared/lib/units' import { debounce, isValueInUnitRange, unitToValue } from 'shared/lib/utils' @@ -146,7 +148,7 @@ * 4. Account must have no transactions (the length of $transactions must be zero) */ return ( - $isFirstSessionSync && $walletSetupType && $walletSetupType !== SetupType.New && $transactions.length === 0 + $isFirstSessionSync && $walletSetupType && $walletSetupType !== SetupType.New && transactions.length === 0 ) } From beb8d4a7e90c7bde6cc74c94a9c01f59a2fe7882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bego=C3=B1a=20Alvarez?= Date: Mon, 21 Feb 2022 15:53:21 +0100 Subject: [PATCH 011/171] chore: remove unnecessary code around wallet contexts --- .../shared/components/ActivityDetail.svelte | 7 +- packages/shared/components/ActivityRow.svelte | 9 +- .../components/modals/AccountActions.svelte | 7 +- packages/shared/lib/chart.ts | 5 - packages/shared/lib/typings/wallet.ts | 4 - packages/shared/lib/wallet.ts | 194 +++++------------- .../routes/dashboard/wallet/Wallet.svelte | 35 +--- .../dashboard/wallet/views/LineChart.svelte | 121 ++++------- .../routes/dashboard/wallet/views/Send.svelte | 18 +- 9 files changed, 121 insertions(+), 279 deletions(-) diff --git a/packages/shared/components/ActivityDetail.svelte b/packages/shared/components/ActivityDetail.svelte index 42bd9bfeeae..44fc70359f4 100644 --- a/packages/shared/components/ActivityDetail.svelte +++ b/packages/shared/components/ActivityDetail.svelte @@ -18,23 +18,22 @@ getMilestoneMessageValue, receiverAddressesFromTransactionPayload, sendAddressFromTransactionPayload, + wallet, } from 'shared/lib/wallet' - import { getContext } from 'svelte' - import type { Writable } from 'svelte/store' export let id: string export let timestamp: string export let confirmed: boolean export let payload: Payload export let balance: number // migration tx - export let onBackClick = (): void => {} + const { accounts } = $wallet + const cachedMigrationTx = !payload const milestonePayload = payload?.type === 'Milestone' ? payload : undefined const txPayload = payload?.type === 'Transaction' ? payload : undefined - const accounts = getContext>('walletAccounts') const explorerLink = getOfficialExplorer($accounts[0].clientOptions.network) let senderAccount: WalletAccount diff --git a/packages/shared/components/ActivityRow.svelte b/packages/shared/components/ActivityRow.svelte index 5dc75414116..cc856852b71 100644 --- a/packages/shared/components/ActivityRow.svelte +++ b/packages/shared/components/ActivityRow.svelte @@ -5,7 +5,6 @@ import { ParticipationAction } from 'shared/lib/participation/types' import { activeProfile, getColor } from 'shared/lib/profile' import type { Payload } from 'shared/lib/typings/message' - import type { WalletAccount } from 'shared/lib/typings/wallet' import { formatUnitBestMatch } from 'shared/lib/units' import { findAccountWithAddress, @@ -16,9 +15,8 @@ isParticipationPayload, receiverAddressesFromTransactionPayload, sendAddressFromTransactionPayload, + wallet, } from 'shared/lib/wallet' - import { getContext } from 'svelte' - import type { Writable } from 'svelte/store' export let timestamp export let confirmed @@ -26,9 +24,10 @@ export let includeFullSender export let payload: Payload export let balance // migration tx - export let onClick = (): void => {} + const { accounts } = $wallet + let messageValue = '' $: hasCachedMigrationTx = !payload @@ -49,8 +48,6 @@ }${formatUnitBestMatch(txPayload.data.essence.data.value, true, 2)}` } - const accounts = getContext>('walletAccounts') - $: senderAddress = sendAddressFromTransactionPayload(payload) $: receiverAddresses = receiverAddressesFromTransactionPayload(payload) diff --git a/packages/shared/components/modals/AccountActions.svelte b/packages/shared/components/modals/AccountActions.svelte index 58f384d489f..0c71ec8ecaa 100644 --- a/packages/shared/components/modals/AccountActions.svelte +++ b/packages/shared/components/modals/AccountActions.svelte @@ -7,20 +7,21 @@ import { SettingsIcons } from 'shared/lib/typings/icons' import { AccountRoutes } from 'shared/lib/typings/routes' import type { WalletAccount } from 'shared/lib/typings/wallet' - import { asyncRemoveWalletAccount, selectedAccount, selectedMessage } from 'shared/lib/wallet' + import { asyncRemoveWalletAccount, selectedAccount, selectedMessage, wallet } from 'shared/lib/wallet' import { getContext } from 'svelte' import type { Readable } from 'svelte/store' import { get } from 'svelte/store' export let isActive + const { accounts } = $wallet + const viewableAccounts = getContext>('viewableAccounts') - const allAccounts = getContext>('walletAccounts') const hiddenAccounts = $activeProfile?.hiddenAccounts ?? [] const hidden = hiddenAccounts.includes($selectedAccount?.id) const canDelete = - $selectedAccount.index === $allAccounts.length - 1 && + $selectedAccount.index === $accounts.length - 1 && $selectedAccount.rawIotaBalance === 0 && $selectedAccount.messages.length === 0 diff --git a/packages/shared/lib/chart.ts b/packages/shared/lib/chart.ts index 15f9ed56d7c..f60f53e54dd 100644 --- a/packages/shared/lib/chart.ts +++ b/packages/shared/lib/chart.ts @@ -41,11 +41,6 @@ const fiatHistoryData = derived([priceData, activeProfile], ([$priceData, $activ } }) -const walletBalance = derived(wallet, ($wallet) => { - const { balanceOverview } = $wallet - return get(balanceOverview)?.balanceRaw -}) - export function getChartDataFromBalanceHistory({ balanceHistory, currentBalance, diff --git a/packages/shared/lib/typings/wallet.ts b/packages/shared/lib/typings/wallet.ts index 478916f90e9..5de5495b2ea 100644 --- a/packages/shared/lib/typings/wallet.ts +++ b/packages/shared/lib/typings/wallet.ts @@ -54,10 +54,6 @@ export type BalanceHistory = { [HistoryDataProps.ONE_MONTH]: BalanceTimestamp[] } -export type AccountsBalanceHistory = { - [accountIndex: number]: BalanceHistory -} - export interface StrongholdStatus { snapshot: { status: 'Locked' | 'Unlocked' diff --git a/packages/shared/lib/wallet.ts b/packages/shared/lib/wallet.ts index 79665ce924d..a7f02e48cb7 100644 --- a/packages/shared/lib/wallet.ts +++ b/packages/shared/lib/wallet.ts @@ -36,14 +36,7 @@ import type { RecoveryPhrase } from './typings/mnemonic' import type { NodeAuth, NodeInfo } from './typings/node' import { ProfileType } from './typings/profile' import { SetupType } from './typings/routes' -import type { - AccountMessage, - AccountsBalanceHistory, - BalanceHistory, - BalanceOverview, - WalletAccount, - WalletState, -} from './typings/wallet' +import type { AccountMessage, BalanceHistory, BalanceOverview, WalletAccount, WalletState } from './typings/wallet' import type { IWalletApi } from './typings/walletApi' import resolveConfig from 'tailwindcss/resolveConfig' import tailwindConfig from 'shared/tailwind.config.js' @@ -1090,44 +1083,6 @@ export const getAccountMessages = (account: WalletAccount): AccountMessage[] => }) } -/** - * Gets a slice of all transactions (on all accounts). Appends account index and sort the message list. - * - * @method getTransactions - * - * @param {WalletAccount} accounts - * @param {number} [count] - * - * @returns {AccountMessage[]} - */ -export const getTransactions = (accounts: WalletAccount[], count = 10): AccountMessage[] => { - const messages: { - [key: string]: AccountMessage - } = {} - - accounts.forEach((account) => { - account.messages.forEach((message) => { - let extraId = '' - if (message.payload?.type === 'Transaction') { - extraId = getIncomingFlag(message.payload) ? 'in' : 'out' - } - messages[account.index + message.id + extraId] = { - ...message, - account: account.index, - } - }) - }) - - return Object.values(messages) - .sort((a, b) => { - if (a.id === b.id && a.payload.type == 'Transaction') { - return getIncomingFlag(a.payload) ? -1 : 1 - } - return new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime() - }) - .slice(0, count) -} - /** * Updates balance overview * @@ -1319,113 +1274,78 @@ export const updateAccountsBalanceEquiv = (): void => { /** * Gets balance history for each account in market data timestamps * - * @method getAccountsBalanceHistory + * @method getAccountBalanceHistory * * @param {Account} accounts * @param {number} balanceRaw * @param {PriceData} [priceData] * */ -export const getAccountsBalanceHistory = (accounts: WalletAccount[], priceData: PriceData): AccountsBalanceHistory => { - const balanceHistory: AccountsBalanceHistory = {} - if (priceData && accounts) { - accounts.forEach((account) => { - const accountBalanceHistory: BalanceHistory = { - [HistoryDataProps.ONE_HOUR]: [], - [HistoryDataProps.TWENTY_FOUR_HOURS]: [], - [HistoryDataProps.SEVEN_DAYS]: [], - [HistoryDataProps.ONE_MONTH]: [], - } - const messages: Message[] = - account?.messages - ?.slice() - ?.filter((message) => message.payload && !isSelfTransaction(message.payload, account)) // Remove self transactions and messages with no payload - ?.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()) ?? [] // Sort messages from last to newest - // Calculate the variations for each account - let trackedBalance = account.rawIotaBalance - const accountBalanceVariations = [{ balance: trackedBalance, timestamp: new Date().toString() }] - messages.forEach((message) => { - const essence = message.payload.type === 'Transaction' && message.payload.data.essence.data - - if (essence && essence.incoming) { - trackedBalance -= essence.value || 0 - } else { - trackedBalance += essence.value || 0 - } - accountBalanceVariations.push({ balance: trackedBalance, timestamp: message.timestamp }) - }) - // Calculate the balance in each market data timestamp - let balanceHistoryInTimeframe = [] - Object.entries(priceData[CurrencyTypes.USD]).forEach(([timeframe, data]) => { - // sort market data from newest to last - const sortedData = data.slice().sort((a, b) => b[0] - a[0]) - balanceHistoryInTimeframe = [] - // if there are no balance variations - if (accountBalanceVariations.length === 1) { - balanceHistoryInTimeframe = sortedData.map((_data) => ({ - timestamp: _data[0], - balance: trackedBalance, - })) - } else { - let i = 0 - sortedData.forEach((data) => { - const marketTimestamp = new Date(data[0] * 1000).getTime() - // find balance for each market data timepstamp - for (i; i < accountBalanceVariations.length - 1; i++) { - const currentBalanceTimestamp = new Date(accountBalanceVariations[i].timestamp).getTime() - const nextBalanceTimestamp = new Date(accountBalanceVariations[i + 1].timestamp).getTime() - if (marketTimestamp > nextBalanceTimestamp && marketTimestamp <= currentBalanceTimestamp) { - balanceHistoryInTimeframe.push({ - timestamp: data[0], - balance: accountBalanceVariations[i].balance, - }) - return - } else if ( - marketTimestamp <= nextBalanceTimestamp && - i === accountBalanceVariations.length - 2 - ) { - balanceHistoryInTimeframe.push({ timestamp: data[0], balance: 0 }) - return - } - } - }) - } - accountBalanceHistory[timeframe] = balanceHistoryInTimeframe.reverse() - }) - balanceHistory[account.index] = accountBalanceHistory - }) - } - return balanceHistory -} - -/** - * Gets balance history for all accounts combined in market data timestamps - * - * @method getWalletBalanceHistory - * - * @param {Account} accounts - * @param {PriceData} [priceData] - * - */ -export const getWalletBalanceHistory = (accountsBalanceHistory: AccountsBalanceHistory): BalanceHistory => { +export const getAccountBalanceHistory = (account: WalletAccount, priceData: PriceData): BalanceHistory => { const balanceHistory: BalanceHistory = { [HistoryDataProps.ONE_HOUR]: [], [HistoryDataProps.TWENTY_FOUR_HOURS]: [], [HistoryDataProps.SEVEN_DAYS]: [], [HistoryDataProps.ONE_MONTH]: [], } - Object.values(accountsBalanceHistory).forEach((accBalanceHistory) => { - Object.entries(accBalanceHistory).forEach(([timeframe, data]) => { - if (!balanceHistory[timeframe].length) { - balanceHistory[timeframe] = data + if (priceData) { + const messages: Message[] = + account?.messages + ?.slice() + ?.filter((message) => message.payload && !isSelfTransaction(message.payload, account)) // Remove self transactions and messages with no payload + ?.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()) ?? [] // Sort messages from last to newest + // Calculate the variations for each account + let trackedBalance = account.rawIotaBalance + const accountBalanceVariations = [{ balance: trackedBalance, timestamp: new Date().toString() }] + messages.forEach((message) => { + const essence = message.payload.type === 'Transaction' && message.payload.data.essence.data + + if (essence && essence.incoming) { + trackedBalance -= essence.value || 0 } else { - balanceHistory[timeframe] = balanceHistory[timeframe].map(({ balance, timestamp }, index) => ({ - timestamp, - balance: balance + data[index].balance, + trackedBalance += essence.value || 0 + } + accountBalanceVariations.push({ balance: trackedBalance, timestamp: message.timestamp }) + }) + // Calculate the balance in each market data timestamp + let balanceHistoryInTimeframe = [] + Object.entries(priceData[CurrencyTypes.USD]).forEach(([timeframe, data]) => { + // sort market data from newest to last + const sortedData = data.slice().sort((a, b) => b[0] - a[0]) + balanceHistoryInTimeframe = [] + // if there are no balance variations + if (accountBalanceVariations.length === 1) { + balanceHistoryInTimeframe = sortedData.map((_data) => ({ + timestamp: _data[0], + balance: trackedBalance, })) + } else { + let i = 0 + sortedData.forEach((data) => { + const marketTimestamp = new Date(data[0] * 1000).getTime() + // find balance for each market data timepstamp + for (i; i < accountBalanceVariations.length - 1; i++) { + const currentBalanceTimestamp = new Date(accountBalanceVariations[i].timestamp).getTime() + const nextBalanceTimestamp = new Date(accountBalanceVariations[i + 1].timestamp).getTime() + if (marketTimestamp > nextBalanceTimestamp && marketTimestamp <= currentBalanceTimestamp) { + balanceHistoryInTimeframe.push({ + timestamp: data[0], + balance: accountBalanceVariations[i].balance, + }) + return + } else if ( + marketTimestamp <= nextBalanceTimestamp && + i === accountBalanceVariations.length - 2 + ) { + balanceHistoryInTimeframe.push({ timestamp: data[0], balance: 0 }) + return + } + } + }) } + balanceHistory[timeframe] = balanceHistoryInTimeframe.reverse() }) - }) + } return balanceHistory } diff --git a/packages/shared/routes/dashboard/wallet/Wallet.svelte b/packages/shared/routes/dashboard/wallet/Wallet.svelte index d3b9ba20f39..b3bec00ad22 100644 --- a/packages/shared/routes/dashboard/wallet/Wallet.svelte +++ b/packages/shared/routes/dashboard/wallet/Wallet.svelte @@ -5,7 +5,7 @@ import { deepCopy } from 'shared/lib/helpers' import { localize } from 'shared/lib/i18n' import { displayNotificationForLedgerProfile, promptUserToConnectLedger } from 'shared/lib/ledger' - import { addProfileCurrencyPriceData, priceData } from 'shared/lib/market' + import { addProfileCurrencyPriceData } from 'shared/lib/market' import { showAppNotification } from 'shared/lib/notifications' import { closePopup, openPopup } from 'shared/lib/popup' import { @@ -21,15 +21,8 @@ import { AccountIdentifier } from 'shared/lib/typings/account' import { LedgerErrorType, TransferProgressEventType } from 'shared/lib/typings/events' import type { Message, Transaction } from 'shared/lib/typings/message' - import type { MigratedTransaction } from 'shared/lib/typings/profile' import { AccountRoutes, WalletRoutes } from 'shared/lib/typings/routes' - import type { - AccountMessage, - AccountsBalanceHistory, - BalanceHistory, - BalanceOverview, - WalletAccount, - } from 'shared/lib/typings/wallet' + import type { WalletAccount } from 'shared/lib/typings/wallet' import { addMessagesPair, api, @@ -38,10 +31,7 @@ asyncSyncAccounts, getAccountMessages, getAccountMeta, - getAccountsBalanceHistory, getSyncAccountOptions, - getTransactions, - getWalletBalanceHistory, hasGeneratedALedgerReceiveAddress, initialiseListeners, isFirstSessionSync, @@ -56,12 +46,12 @@ wallet, } from 'shared/lib/wallet' import { onMount, setContext } from 'svelte' - import { derived, Readable, Writable } from 'svelte/store' + import { derived, Readable } from 'svelte/store' import { AccountActions, AccountBalance, AccountHistory, AccountNavigation, BarChart, LineChart } from './views/' let drawer: Drawer - const { accounts, balanceOverview, accountsLoaded, internalTransfersInProgress } = $wallet + const { accounts, accountsLoaded, internalTransfersInProgress } = $wallet let showActionsModal = false @@ -71,12 +61,6 @@ deepLinkRequestActive.set(false) } } - const accountsBalanceHistory = derived([accounts, priceData], ([$accounts, $priceData]) => - getAccountsBalanceHistory($accounts, $priceData) - ) - const walletBalanceHistory = derived(accountsBalanceHistory, ($accountsBalanceHistory) => - getWalletBalanceHistory($accountsBalanceHistory) - ) const viewableAccounts: Readable = derived( [activeProfile, accounts], @@ -122,19 +106,8 @@ } ) - const transactions = derived([viewableAccounts, activeProfile], ([$viewableAccounts, $activeProfile]) => { - const _migratedTransactions = $activeProfile?.migratedTransactions || [] - - return [..._migratedTransactions, ...getTransactions($viewableAccounts)] - }) - - setContext>('walletBalance', balanceOverview) - setContext>('walletAccounts', accounts) setContext>('viewableAccounts', viewableAccounts) setContext>('liveAccounts', liveAccounts) - setContext>('walletTransactions', transactions) - setContext>('accountsBalanceHistory', accountsBalanceHistory) - setContext>('walletBalanceHistory', walletBalanceHistory) let isGeneratingAddress = false diff --git a/packages/shared/routes/dashboard/wallet/views/LineChart.svelte b/packages/shared/routes/dashboard/wallet/views/LineChart.svelte index b4903fab811..303c03909d8 100644 --- a/packages/shared/routes/dashboard/wallet/views/LineChart.svelte +++ b/packages/shared/routes/dashboard/wallet/views/LineChart.svelte @@ -1,25 +1,19 @@ + + + + + diff --git a/packages/shared/components/ActivityDetail.svelte b/packages/shared/components/ActivityDetail.svelte index 44fc70359f4..84e171482ce 100644 --- a/packages/shared/components/ActivityDetail.svelte +++ b/packages/shared/components/ActivityDetail.svelte @@ -156,7 +156,7 @@ {/if}
-
+
{localize('general.status')} {localize(`general.${confirmed ? 'confirmed' : 'pending'}`)} diff --git a/packages/shared/components/Sidebar.svelte b/packages/shared/components/Sidebar.svelte index f4bdafed8c8..ee82ddaa266 100644 --- a/packages/shared/components/Sidebar.svelte +++ b/packages/shared/components/Sidebar.svelte @@ -96,7 +96,7 @@ {:else} {/if} - - diff --git a/packages/shared/routes/dashboard/governance/views/GovernanceHeader.svelte b/packages/shared/routes/dashboard/governance/views/GovernanceHeader.svelte deleted file mode 100644 index 38e7c511618..00000000000 --- a/packages/shared/routes/dashboard/governance/views/GovernanceHeader.svelte +++ /dev/null @@ -1,8 +0,0 @@ - - -
- {localize('views.governance.title')} -
diff --git a/packages/shared/routes/dashboard/governance/views/GovernanceInfo.svelte b/packages/shared/routes/dashboard/governance/views/GovernanceInfo.svelte index fb63e5efda6..66bd5034993 100644 --- a/packages/shared/routes/dashboard/governance/views/GovernanceInfo.svelte +++ b/packages/shared/routes/dashboard/governance/views/GovernanceInfo.svelte @@ -1,25 +1,22 @@
-
+
- {localize('views.governance.info.title')} - {localize('views.governance.info.title')} + {localize('views.governance.info.description')}
- Electron.openUrl('https://iotatreasury.org/how-voting-works.html')} +
diff --git a/packages/shared/routes/dashboard/governance/views/GovernanceVotingPower.svelte b/packages/shared/routes/dashboard/governance/views/GovernanceVotingPower.svelte index 3255f59a269..a9a30e39c94 100644 --- a/packages/shared/routes/dashboard/governance/views/GovernanceVotingPower.svelte +++ b/packages/shared/routes/dashboard/governance/views/GovernanceVotingPower.svelte @@ -7,10 +7,10 @@ export let account: WalletAccount -
openPopup({ type: 'governanceVotingPowerInfo' })}> - +
openPopup({ type: 'governanceVotingPowerInfo' })}> + {localize('views.governance.votingPower.title')} - +
-{account?.balance} +{account?.balance} diff --git a/packages/shared/routes/dashboard/governance/views/index.js b/packages/shared/routes/dashboard/governance/views/index.js index b91f970d69e..073f38c0c32 100644 --- a/packages/shared/routes/dashboard/governance/views/index.js +++ b/packages/shared/routes/dashboard/governance/views/index.js @@ -1,4 +1,3 @@ -export { default as GovernanceHeader } from './GovernanceHeader.svelte' export { default as GovernanceVotingPower } from './GovernanceVotingPower.svelte' export { default as GovernanceInfo } from './GovernanceInfo.svelte' export { default as GovernanceEvents } from './GovernanceEvents.svelte' From b3baabf1cd718bbbf90fffe76e3c762b56e5263e Mon Sep 17 00:00:00 2001 From: Jean Ribeiro Date: Wed, 13 Apr 2022 19:55:26 -0300 Subject: [PATCH 068/171] fix: adds empty object fallback to fix errors --- packages/shared/components/popups/Transaction.svelte | 2 +- packages/shared/lib/participation/account.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/shared/components/popups/Transaction.svelte b/packages/shared/components/popups/Transaction.svelte index 34c51527fad..0bb313a2906 100644 --- a/packages/shared/components/popups/Transaction.svelte +++ b/packages/shared/components/popups/Transaction.svelte @@ -28,7 +28,7 @@ } $: isAccountVoting = - Object.values($selectedAccountParticipationOverview?.trackedParticipations)?.find((tp) => + Object.values($selectedAccountParticipationOverview?.trackedParticipations || {})?.find((tp) => tp?.find((p) => p?.endMilestoneIndex === 0) )?.length > 0 ?? false diff --git a/packages/shared/lib/participation/account.ts b/packages/shared/lib/participation/account.ts index 1b06fe5cac6..cea6bba6e79 100644 --- a/packages/shared/lib/participation/account.ts +++ b/packages/shared/lib/participation/account.ts @@ -20,8 +20,8 @@ import { ASSEMBLY_REWARD_MULTIPLIER, SHIMMER_REWARD_MULTIPLIER } from './constan export const selectedAccountParticipationOverview = derived( [participationOverview, selectedAccount], ([$participationOverview, $selectedAccount]) => - $participationOverview?.find(({ accountIndex }) => accountIndex === $selectedAccount?.index) ?? null -) + $participationOverview?.find(({ accountIndex }) => accountIndex === $selectedAccount?.index) ?? {} +) as Readable /** * The amount of funds that are currently staked on the selected account. This amount may differ From 8f570d9c972c3c7deb92cd7b13bc0797f2f01d3a Mon Sep 17 00:00:00 2001 From: Jean Ribeiro Date: Thu, 21 Apr 2022 08:20:01 -0300 Subject: [PATCH 069/171] feat: adds voting tx locale/icon (#2620) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [wip] feat: adds voting tx locale/icon * feat: adds unvoted and unstaked actions * fix: refactoring * fix: code review * fix: persist participationHistory Co-authored-by: Begoña Alvarez Co-authored-by: Charlie Varley --- packages/shared/components/ActivityRow.svelte | 64 +++++++++++-------- packages/shared/components/icon/icons.js | 2 +- packages/shared/lib/participation/api.ts | 24 ++++++- .../shared/lib/participation/participation.ts | 32 +++++++++- packages/shared/lib/participation/stores.ts | 11 ++-- packages/shared/lib/participation/types.ts | 9 ++- packages/shared/locales/en.json | 5 ++ 7 files changed, 113 insertions(+), 34 deletions(-) diff --git a/packages/shared/components/ActivityRow.svelte b/packages/shared/components/ActivityRow.svelte index 7396b5094fc..c29e33b6ab2 100644 --- a/packages/shared/components/ActivityRow.svelte +++ b/packages/shared/components/ActivityRow.svelte @@ -16,17 +16,24 @@ sendAddressFromTransactionPayload, wallet, } from 'shared/lib/wallet' + import { Transaction } from 'shared/lib/typings/message' + import { getMessageParticipationAction } from 'shared/lib/participation' - export let timestamp - export let confirmed + export let id: string + export let timestamp: string + export let confirmed: boolean export let payload: Payload export let balance // migration tx export let onClick = (): void => {} const { accounts } = $wallet + let accountAlias = '' + let direction: string let messageValue = '' let date = localize('error.invalidDate') + let txPayload: Transaction + $: { try { date = formatDate(new Date(timestamp), { @@ -40,27 +47,13 @@ date = localize('error.invalidDate') } } - $: hasCachedMigrationTx = !payload $: milestonePayload = payload?.type === 'Milestone' ? payload : undefined $: txPayload = payload?.type === 'Transaction' ? payload : undefined $: hasCachedMigrationTx, milestonePayload, txPayload, (messageValue = getMessageValue()) - - const getMessageValue = () => { - if (hasCachedMigrationTx) { - return formatUnitBestMatch(balance, true, 3) - } - if (milestonePayload) { - return formatUnitBestMatch(getMilestoneMessageValue(milestonePayload, $accounts), true, 3) - } - - return `${ - !txPayload.data.essence.data.incoming && !isParticipationPayload(txPayload) ? '-' : '' - }${formatUnitBestMatch(txPayload.data.essence.data.value, true, 2)}` - } - $: senderAddress = sendAddressFromTransactionPayload(payload) $: receiverAddresses = receiverAddressesFromTransactionPayload(payload) + $: participationAction = getMessageParticipationAction(id) // There can only be one sender address $: senderAccount = findAccountWithAddress(senderAddress) @@ -72,9 +65,6 @@ getIncomingFlag(txPayload) || getInternalFlag(txPayload) ? findAccountWithAnyAddress(receiverAddresses, senderAccount) : null - - let accountAlias = '' - $: { if (txPayload) { const acc = txPayload.data.essence.data.incoming ? senderAccount : receiverAccount @@ -93,8 +83,6 @@ } } } - - let direction: string $: { if (txPayload) { if (isParticipationPayload(txPayload)) { @@ -119,6 +107,18 @@ } } + function getMessageValue(): string { + if (hasCachedMigrationTx) { + return formatUnitBestMatch(balance, true, 3) + } + if (milestonePayload) { + return formatUnitBestMatch(getMilestoneMessageValue(milestonePayload, $accounts), true, 3) + } + return `${ + !txPayload.data.essence.data.incoming && !isParticipationPayload(txPayload) ? '-' : '' + }${formatUnitBestMatch(txPayload.data.essence.data.value, true, 2)}` + } + let icon: string let iconColor: string $: { @@ -126,7 +126,7 @@ icon = 'double-chevron-right' iconColor = 'gray-600' } else if (isParticipationPayload(txPayload)) { - icon = getParticipationIcon(ParticipationAction.Stake) + icon = getParticipationIcon(participationAction) iconColor = 'gray-600' } else if (txPayload.data.essence.data.internal) { icon = 'transfer' @@ -149,7 +149,21 @@ case ParticipationAction.Unvote: return 'voting' default: - return '' + return 'participation' + } + } + function getParticipationActionLocaleKey(action: ParticipationAction): string { + switch (action) { + case ParticipationAction.Stake: + return 'stakingTransaction' + case ParticipationAction.Vote: + return 'votingTransaction' + case ParticipationAction.Unstake: + return 'unstakingTransaction' + case ParticipationAction.Unvote: + return 'unvotingTransaction' + default: + return 'participationTransaction' } } @@ -171,7 +185,7 @@ {#if hasCachedMigrationTx || milestonePayload} {localize('general.fundMigration')} {:else if isParticipationPayload(txPayload)} - {localize('general.stakingTransaction')} + {localize(`general.${getParticipationActionLocaleKey(participationAction)}`)} {:else}{localize(direction, { values: { account: accountAlias } })}{/if}

{date}

diff --git a/packages/shared/components/icon/icons.js b/packages/shared/components/icon/icons.js index bfbc0169943..9b9dfcccfe2 100644 --- a/packages/shared/components/icon/icons.js +++ b/packages/shared/components/icon/icons.js @@ -1110,7 +1110,7 @@ export const icons = { }, ], }, - staking: { + participation: { width: 24, height: 24, path: [ diff --git a/packages/shared/lib/participation/api.ts b/packages/shared/lib/participation/api.ts index c6b1c3bfd8f..8001c541bfa 100644 --- a/packages/shared/lib/participation/api.ts +++ b/packages/shared/lib/participation/api.ts @@ -3,13 +3,14 @@ import { localize } from '@core/i18n' import { Event } from '../typings/events' import { showAppNotification } from '../notifications' import { api, saveNewMessage } from '../wallet' -import { addNewPendingParticipation, participationEvents, participationOverview } from './stores' +import { addNewPendingParticipation, participationEvents, participationOverview, participationHistory } from './stores' import { ParticipationAction, ParticipateResponsePayload, Participation, ParticipationEvent, ParticipationOverviewResponse, + ParticipationHistoryItem, } from './types' export function getParticipationOverview(assemblyEventId: string): Promise { @@ -46,6 +47,21 @@ export function getParticipationEvents(): Promise { }) } +function updateParticipationHistoryFromPayload( + payload: ParticipateResponsePayload, + accountId: string, + action: ParticipationAction, + eventIds: string[] +): void { + const participationHistoryItems: ParticipationHistoryItem[] = payload.map((message, index) => ({ + messageId: message.id, + accountId, + action, + eventId: eventIds[index], + })) + participationHistory.update((_participationHistory) => [..._participationHistory, ...participationHistoryItems]) +} + export function participate( accountId: string, participations: Participation[], @@ -65,6 +81,10 @@ export function participate( response.payload.forEach((message) => saveNewMessage(accountId, message)) addNewPendingParticipation(response.payload, accountId, action) + + const eventIds = participations.map((participation) => participation.eventId) + updateParticipationHistoryFromPayload(response.payload, accountId, action, eventIds) + resolve(response.payload.map((message) => message.id)) }, onError(error) { @@ -97,6 +117,8 @@ export function stopParticipating( addNewPendingParticipation(response.payload, accountId, action) + updateParticipationHistoryFromPayload(response.payload, accountId, action, eventIds) + resolve(response.payload.map((message) => message.id)) }, onError(error) { diff --git a/packages/shared/lib/participation/participation.ts b/packages/shared/lib/participation/participation.ts index 221ff6f7c2f..f3aaaa07416 100644 --- a/packages/shared/lib/participation/participation.ts +++ b/packages/shared/lib/participation/participation.ts @@ -9,8 +9,11 @@ import { participationEvents, participationOverview, pendingParticipations, + participationHistory, } from './stores' -import { AccountParticipationAbility, ParticipationEventState, StakingAirdrop } from './types' +import { AccountParticipationAbility, ParticipationAction, ParticipationEventState, StakingAirdrop } from './types' +import { get } from 'svelte/store' +import { ASSEMBLY_EVENT_ID, SHIMMER_EVENT_ID } from './constants' let participationPollInterval @@ -83,7 +86,7 @@ export const canParticipate = (eventState: ParticipationEventState): boolean => * * @param {WalletAccount} account * - * @returns {boolean} + * @returns {AccountParticipationAbility} */ export const getAccountParticipationAbility = (account: WalletAccount): AccountParticipationAbility => { if (account?.rawIotaBalance < DUST_THRESHOLD) { @@ -96,3 +99,28 @@ export const getAccountParticipationAbility = (account: WalletAccount): AccountP return AccountParticipationAbility.Ok } } + +/** + * Returns ParticipationAction for transaction message + * + * @method getMessageParticipationAction + * + * @param {WalletAccount} account + * + * @returns {ParticipationAction} + */ +export const getMessageParticipationAction = (messageId: string): ParticipationAction => { + const matchedHistoryItem = get(participationHistory)?.find((item) => item.messageId === messageId) + if (matchedHistoryItem?.action) { + return matchedHistoryItem.action + } + const stakingEndMilestoneIndexes = get(participationEvents) + ?.filter((event) => event.eventId === ASSEMBLY_EVENT_ID || event.eventId === SHIMMER_EVENT_ID) + ?.map((event) => event.information?.milestoneIndexEnd) + const lastMilestoneBeforeTreasuryEvent = 0 // TODO: add real milestone + if (stakingEndMilestoneIndexes?.find((milestone) => milestone > lastMilestoneBeforeTreasuryEvent)) { + return ParticipationAction.Stake + } else if (stakingEndMilestoneIndexes?.length) { + return ParticipationAction.Vote + } +} diff --git a/packages/shared/lib/participation/stores.ts b/packages/shared/lib/participation/stores.ts index 087e162c029..09458ba5d56 100644 --- a/packages/shared/lib/participation/stores.ts +++ b/packages/shared/lib/participation/stores.ts @@ -1,22 +1,23 @@ +import { getStakingEventFromAirdrop } from '@lib/participation/staking' +import { NetworkStatus } from '@lib/typings/network' +import { persistent } from 'shared/lib/helpers' import { derived, get, Readable, writable } from 'svelte/store' import { networkStatus } from '../networkStatus' import { MILLISECONDS_PER_SECOND, SECONDS_PER_MILESTONE } from '../time' import { NodePlugin } from '../typings/node' -import { wallet } from '../wallet' import { WalletAccount } from '../typings/wallet' - +import { wallet } from '../wallet' import { ASSEMBLY_EVENT_ID, SHIMMER_EVENT_ID } from './constants' import { ParticipateResponsePayload, ParticipationAction, ParticipationEvent, ParticipationEventState, + ParticipationHistoryItem, ParticipationOverview, PendingParticipation, StakingAirdrop, } from './types' -import { NetworkStatus } from '@lib/typings/network' -import { getStakingEventFromAirdrop } from '@lib/participation/staking' /** * The store for keeping track of pending participations. @@ -232,3 +233,5 @@ export const getPendingParticipation = (id: string): PendingParticipation | unde */ export const hasPendingParticipation = (id: string): boolean => get(pendingParticipations).some((participation) => participation.messageId === id) + +export const participationHistory = persistent('participationHistory', []) diff --git a/packages/shared/lib/participation/types.ts b/packages/shared/lib/participation/types.ts index 64148c1c975..cccc4682b15 100644 --- a/packages/shared/lib/participation/types.ts +++ b/packages/shared/lib/participation/types.ts @@ -196,7 +196,7 @@ export type ParticipationOverviewResponse = { * Pending participations type, useful for distinguishing between participations * that have or have not been confirmed yet. */ -export interface PendingParticipation { +export type PendingParticipation = { messageId: string accountId: string action: ParticipationAction @@ -246,3 +246,10 @@ export type StakingPeriod = { totalPeriodRewards: number rewards: StakingPeriodRewards } + +export type ParticipationHistoryItem = { + accountId: string + action: ParticipationAction + eventId: string + messageId: string +} diff --git a/packages/shared/locales/en.json b/packages/shared/locales/en.json index 793faedfb8e..97d06367323 100644 --- a/packages/shared/locales/en.json +++ b/packages/shared/locales/en.json @@ -1125,6 +1125,9 @@ "unvotedFor": "Unvoted for {account}", "stakingTransaction": "Staking Transaction", "unstakingTransaction": "Unstaking Transaction", + "votingTransaction": "Voting Transaction", + "unvotingTransaction": "Unvoting Transaction", + "participationTransaction": "Participation Transaction", "receiving": "Receiving", "sending": "Sending", "legacyNetwork": "Legacy Network", @@ -1134,7 +1137,9 @@ "unknown": "Unknown", "none": "None", "staked": "Staked", + "voted": "Voted", "unstaked": "Unstaked", + "unvoted": "Unvoted", "staking": "Staking", "unstaking": "Unstaking", "notStaked": "Not staked", From 4a4b6493a9fb6412d4b9e841a8c218b71af83dde Mon Sep 17 00:00:00 2001 From: Jean Ribeiro Date: Thu, 21 Apr 2022 08:23:06 -0300 Subject: [PATCH 070/171] feat: adds voting info tooltips (#2890) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: refactors GovernanceEventDetails to code guidelines * feat: adds GovernanceInfoTooltip component * feat: implements tooltip in event details Co-authored-by: Begoña Alvarez --- .../components/GovernanceInfoTooltip.svelte | 129 +++++++++++++++ packages/shared/components/index.js | 1 + packages/shared/locales/en.json | 18 ++- .../views/GovernanceEventDetails.svelte | 148 +++++++++++------- 4 files changed, 239 insertions(+), 57 deletions(-) create mode 100644 packages/shared/components/GovernanceInfoTooltip.svelte diff --git a/packages/shared/components/GovernanceInfoTooltip.svelte b/packages/shared/components/GovernanceInfoTooltip.svelte new file mode 100644 index 00000000000..30f22d88c2c --- /dev/null +++ b/packages/shared/components/GovernanceInfoTooltip.svelte @@ -0,0 +1,129 @@ + + + + {#if type === GovernanceInfoType.StatusTimeline} +
    +
  • 0}> + + {localize('views.governance.info.tooltip.eventStatusTimeline.announcement')} + +
  • +
  • 1}> + + {formatDate(milestoneToDate(event?.information?.milestoneIndexCommence), dateFormat)} + + + {localize('views.governance.info.tooltip.eventStatusTimeline.votingOpen')} + +
  • +
  • 2}> + + {formatDate(milestoneToDate(event?.information?.milestoneIndexStart), dateFormat)} + + + {localize('views.governance.info.tooltip.eventStatusTimeline.countingStarts')} + +
  • +
  • 3}> + + {formatDate(milestoneToDate(event?.information?.milestoneIndexEnd), dateFormat)} + + + {localize('views.governance.info.tooltip.eventStatusTimeline.countingStops')} + +
  • +
+ {:else if type === GovernanceInfoType.VotingRate} + {localize('views.governance.info.tooltip.votingRate.title')} + + {localize('views.governance.info.tooltip.votingRate.body', { + values: { + amount: formatUnitBestMatch(lastTrackedParticipationItem?.amount), + votesPerMinute, + }, + })} + + {:else if type === GovernanceInfoType.CountedVotes} + {localize('views.governance.info.tooltip.countedVotes.title')} + {localize('views.governance.info.tooltip.countedVotes.body')} + {/if} +
+ + diff --git a/packages/shared/components/index.js b/packages/shared/components/index.js index a5e96afb4c7..b3fed102208 100644 --- a/packages/shared/components/index.js +++ b/packages/shared/components/index.js @@ -63,6 +63,7 @@ export { default as AccountSwitcher } from './AccountSwitcher.svelte' export { default as SidebarTab } from './SidebarTab.svelte' export { default as Chip } from './Chip.svelte' export { default as PingingBadge } from './PingingBadge.svelte' +export { default as GovernanceInfoTooltip } from './GovernanceInfoTooltip.svelte' export * from './modals' // Charts diff --git a/packages/shared/locales/en.json b/packages/shared/locales/en.json index 97d06367323..758a49ed51e 100644 --- a/packages/shared/locales/en.json +++ b/packages/shared/locales/en.json @@ -572,7 +572,23 @@ "info": { "title": "Governance info", "description": "The IOTA community together with the IOTA Foundation, has developed the technology that makes it possible to use your IOTA tokens in governance decisions here in the secure environment of the Firefly Wallet.", - "link": "Learn about voting with Firefly" + "link": "Learn about voting with Firefly", + "tooltip": { + "eventStatusTimeline": { + "announcement": "Announcement", + "votingOpen": "Voting open", + "countingStarts": "Counting starts", + "countingStops": "Counting stops" + }, + "votingRate": { + "title": "Voting rate", + "body": "{amount} achieves {votesPerMinute} votes per minute" + }, + "countedVotes": { + "title": "Counted votes", + "body": "You must keep voting for the remaining period to reach your full voting power" + } + } }, "events": { "status": { diff --git a/packages/shared/routes/dashboard/governance/views/GovernanceEventDetails.svelte b/packages/shared/routes/dashboard/governance/views/GovernanceEventDetails.svelte index 874cccd3e8a..2f63fb5b51b 100644 --- a/packages/shared/routes/dashboard/governance/views/GovernanceEventDetails.svelte +++ b/packages/shared/routes/dashboard/governance/views/GovernanceEventDetails.svelte @@ -1,30 +1,30 @@
@@ -171,7 +173,19 @@ bold overrideColor>{localize(`views.governance.events.status.${event?.status?.status}`)} - + + {#if tooltip.statusTimeline.show} +
toggleTooltip(['statusTimeline'])}> + +
+ {/if}
{event?.information?.name} {event?.information?.additionalInfo} @@ -252,7 +266,7 @@
-
+
{localize('views.governance.votingPower.title')} @@ -287,7 +301,7 @@
{/if} {#if event?.status?.status === ParticipationEventState.Holding || event?.status?.status === ParticipationEventState.Ended} -
+
{localize('views.governance.eventDetails.votesCounted')} @@ -301,7 +315,29 @@
{/if}
- + + {#if tooltip.votingRate.show} +
toggleTooltip(['votingRate'])}> + +
+ {/if} + {#if tooltip.countedVotes.show} +
toggleTooltip(['countedVotes'])}> + +
+ {/if}
{#if event?.status?.status === ParticipationEventState.Holding || event?.status?.status === ParticipationEventState.Ended} From 0ad8588ce1b9d79a3df1d1e8665c8f07be233458 Mon Sep 17 00:00:00 2001 From: Charlie Varley Date: Thu, 21 Apr 2022 12:33:22 +0100 Subject: [PATCH 071/171] fix: duplicate constant imports --- packages/shared/lib/participation/participation.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/shared/lib/participation/participation.ts b/packages/shared/lib/participation/participation.ts index f3aaaa07416..03a614777ae 100644 --- a/packages/shared/lib/participation/participation.ts +++ b/packages/shared/lib/participation/participation.ts @@ -1,19 +1,18 @@ +import { get } from 'svelte/store' import { WalletAccount } from '../typings/wallet' import { DUST_THRESHOLD, hasValidPendingTransactions } from '../wallet' import { canAccountReachMinimumAirdrop } from './account' import { getParticipationOverview } from './api' -import { ASSEMBLY_EVENT_ID, PARTICIPATION_POLL_DURATION } from './constants' +import { ASSEMBLY_EVENT_ID, PARTICIPATION_POLL_DURATION, SHIMMER_EVENT_ID } from './constants' import { isPerformingParticipation, participationAction, participationEvents, + participationHistory, participationOverview, pendingParticipations, - participationHistory, } from './stores' import { AccountParticipationAbility, ParticipationAction, ParticipationEventState, StakingAirdrop } from './types' -import { get } from 'svelte/store' -import { ASSEMBLY_EVENT_ID, SHIMMER_EVENT_ID } from './constants' let participationPollInterval From 9572e3698b965b3f3682a30ea84a776dd100eeed Mon Sep 17 00:00:00 2001 From: Charlie Varley Date: Thu, 21 Apr 2022 16:07:07 +0100 Subject: [PATCH 072/171] fix: reset governance router on logout (#3005) Co-authored-by: Charlie Varley --- packages/shared/lib/core/router/helper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shared/lib/core/router/helper.ts b/packages/shared/lib/core/router/helper.ts index 2f169ba5133..1a4842ffa05 100644 --- a/packages/shared/lib/core/router/helper.ts +++ b/packages/shared/lib/core/router/helper.ts @@ -27,7 +27,7 @@ export const resetRouters = (): void => { get(dashboardRouter).reset() get(accountRouter).reset() get(settingsRouter).reset() - get(settingsRouter).reset() + get(governanceRouter).reset() isDeepLinkRequestActive.set(false) } From 406d89f71244a5b6e02359ed7f6c1ea3591100b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bego=C3=B1a=20=C3=81lvarez=20de=20la=20Cruz?= Date: Fri, 22 Apr 2022 22:46:48 +0200 Subject: [PATCH 073/171] feat: polish event detail tooltips (#2999) * feat: polish event detail tooltips * feat: improve spacings * fix: crash when event ended --- .../views/GovernanceEventDetails.svelte | 209 +++++++++--------- 1 file changed, 104 insertions(+), 105 deletions(-) diff --git a/packages/shared/routes/dashboard/governance/views/GovernanceEventDetails.svelte b/packages/shared/routes/dashboard/governance/views/GovernanceEventDetails.svelte index 2f63fb5b51b..911fc87c43d 100644 --- a/packages/shared/routes/dashboard/governance/views/GovernanceEventDetails.svelte +++ b/packages/shared/routes/dashboard/governance/views/GovernanceEventDetails.svelte @@ -1,21 +1,18 @@ @@ -171,21 +165,17 @@ classes="px-2 py-1 text-blue-500 bg-blue-100 dark:bg-gray-900 rounded-lg" smaller bold - overrideColor>{localize(`views.governance.events.status.${event?.status?.status}`)} + {localize(`views.governance.events.status.${event?.status?.status}`)} + + - {#if tooltip.statusTimeline.show} -
toggleTooltip(['statusTimeline'])}> - -
- {/if}
{event?.information?.name} {event?.information?.additionalInfo} @@ -242,8 +232,10 @@ classes="mb-2 text-left {isWinnerAnswer(answer?.value) ? 'text-white' : 'text-gray-800 dark:text-white'}" - overrideColor>{answer?.text} + {answer?.text} +
-
- {localize('views.governance.votingPower.title')} - {account?.balance} +
+
+ + {localize('views.governance.votingPower.title')} + + +
+ {account?.balance}
{#if event?.status?.status === ParticipationEventState.Upcoming}
- {localize('views.governance.eventDetails.votingOpens')} - {milestoneToDate(event?.information?.milestoneIndexCommence).toString()} + + {localize('views.governance.eventDetails.votingOpens')} + + + {milestoneToDate(event?.information?.milestoneIndexCommence).toString()} +
{/if} {#if event?.status?.status === ParticipationEventState.Upcoming || event?.status?.status === ParticipationEventState.Commencing}
- {localize('views.governance.eventDetails.countingStarts')} - {milestoneToDate(event?.information?.milestoneIndexStart).toString()} + + {localize('views.governance.eventDetails.countingStarts')} + + + {milestoneToDate(event?.information?.milestoneIndexStart).toString()} +
{/if} {#if event?.status?.status === ParticipationEventState.Commencing}
- {localize('views.governance.eventDetails.countingLength')} + + {localize('views.governance.eventDetails.countingLength')} + {getBestTimeDuration(length)}
{/if} {#if event?.status?.status === ParticipationEventState.Holding || event?.status?.status === ParticipationEventState.Ended} -
- {localize('views.governance.eventDetails.votesCounted')} +
+
+ + {localize('views.governance.eventDetails.votesCounted')} + + +
{formatUnitBestMatch(accountVotes)}
- {localize('views.governance.eventDetails.votingProgress')} + + {localize('views.governance.eventDetails.votingProgress')} + {getDurationString(progress)}
{/if}
- - {#if tooltip.votingRate.show} -
toggleTooltip(['votingRate'])}> - -
- {/if} - {#if tooltip.countedVotes.show} -
toggleTooltip(['countedVotes'])}> - -
- {/if}
{#if event?.status?.status === ParticipationEventState.Holding || event?.status?.status === ParticipationEventState.Ended} - {localize('views.governance.eventDetails.currentResults')} + + {localize('views.governance.eventDetails.currentResults')} +
{#each results || [] as result, i}
@@ -354,16 +343,16 @@ ?.relativePercentage}; background-color: {Object.values(AccountColors)[i]};" />
- {event?.information?.payload?.questions[0]?.answers[i]?.text?.split(' ')[0]} - {displayedPercentages[i].percentage} + + {event?.information?.payload?.questions[0]?.answers[i]?.text?.split(' ')[0]} + + + {displayedPercentages[i].percentage} +
- {formatUnitBestMatch(result?.accumulated)} + + {formatUnitBestMatch(result?.accumulated)} +
{/each}
@@ -371,6 +360,16 @@ {/if}
+{#if tooltip.votingRate.show} + +{/if} +{#if tooltip.countedVotes.show} + +{/if} +{#if tooltip.statusTimeline.show} + +{/if} + diff --git a/packages/shared/routes/dashboard/staking/views/StakingSummary.svelte b/packages/shared/routes/dashboard/staking/views/StakingSummary.svelte index 8c9778ee832..6df551b373c 100644 --- a/packages/shared/routes/dashboard/staking/views/StakingSummary.svelte +++ b/packages/shared/routes/dashboard/staking/views/StakingSummary.svelte @@ -29,6 +29,9 @@ $: isPartiallyStakedAndCanParticipate = $isPartiallyStaked && canParticipateInEvent + let spinnerMessage: string + $: showSpinner, (spinnerMessage = getSpinnerMessage()) + let canParticipateWithNode = false $: $networkStatus, (canParticipateWithNode = hasNodePlugin(NodePlugin.Participation)) @@ -63,10 +66,14 @@ } function getSpinnerMessage(): string { - if ($participationAction) { - return $participationAction === ParticipationAction.Stake ? 'general.staking' : 'general.unstaking' + if ( + $participationAction === ParticipationAction.Stake || + $participationAction === ParticipationAction.Unstake + ) { + const locale = $participationAction === ParticipationAction.Stake ? 'general.staking' : 'general.unstaking' + return localize(locale) } else if ($isSyncing) { - return 'general.syncingAccounts' + return localize('general.syncingAccounts') } } @@ -107,7 +114,7 @@ })} > {#if showSpinner} - + {:else}{localize(`actions.${isStakedAndCanParticipate ? 'manageStake' : 'stakeFunds'}`)}{/if}
From 39ed469324506becef35d8af73b63bd1251c7445 Mon Sep 17 00:00:00 2001 From: Matthew Maxwell <44885822+maxwellmattryan@users.noreply.github.com> Date: Wed, 4 May 2022 20:31:34 -0500 Subject: [PATCH 087/171] refactor: change syncing to per account (#3082) * refactor: add account metadata type * refactor: rename some code * refactor: cleanup logic for updating accounts * refactor: cleanup code for loading in wallet dashboard * refactor: implement syncing queue when loading accounts * enhancement: implement priority when switching accounts * fix: use dedicate store for current syncing account to smoothen UX * refactor: cleanup code around syncing API wrappers * fix: make balance finder account for syncing on open * chore: rename function Co-authored-by: Charlie Varley --- packages/backend/bindings/node/index.ts | 4 +- packages/mobile/capacitor/walletPluginApi.ts | 4 +- .../shared/components/AccountSwitcher.svelte | 4 +- .../shared/components/StakingAssetTile.svelte | 6 +- .../components/modals/AccountActions.svelte | 25 +- .../components/modals/AccountSwitcher.svelte | 19 +- .../components/popups/BalanceFinder.svelte | 38 +- .../NewStakingPeriodNotification.svelte | 4 +- .../popups/StakingConfirmation.svelte | 8 +- .../components/popups/StakingManager.svelte | 28 +- packages/shared/lib/assets.ts | 4 +- packages/shared/lib/errors.ts | 17 + packages/shared/lib/networkStatus.ts | 15 - packages/shared/lib/participation/staking.ts | 4 +- packages/shared/lib/participation/stores.ts | 8 +- packages/shared/lib/profile.ts | 4 +- packages/shared/lib/typings/account.ts | 13 +- packages/shared/lib/typings/walletApi.ts | 8 +- packages/shared/lib/wallet.ts | 543 +++++++++++------- packages/shared/lib/walletApiListeners.ts | 12 +- .../shared/routes/dashboard/Dashboard.svelte | 4 +- .../staking/views/StakingInfo.svelte | 4 +- .../staking/views/StakingSummary.svelte | 4 +- .../routes/dashboard/wallet/Wallet.svelte | 132 ++--- .../wallet/views/AccountBalance.svelte | 8 +- .../wallet/views/AccountHistory.svelte | 23 +- .../dashboard/wallet/views/BarChart.svelte | 6 +- .../dashboard/wallet/views/LineChart.svelte | 16 +- .../wallet/views/ManageAccount.svelte | 8 +- .../dashboard/wallet/views/Receive.svelte | 10 +- .../routes/dashboard/wallet/views/Send.svelte | 37 +- 31 files changed, 559 insertions(+), 461 deletions(-) diff --git a/packages/backend/bindings/node/index.ts b/packages/backend/bindings/node/index.ts index 7c33019321d..abdcecd9c59 100644 --- a/packages/backend/bindings/node/index.ts +++ b/packages/backend/bindings/node/index.ts @@ -3,7 +3,7 @@ import { AccountToCreate, AccountIdentifier, ListMessagesFilter, - SyncAccountOptions, + AccountSyncOptions, createAccount as _createAccount, removeAccount as _removeAccount, getAccount as _getAccount, @@ -214,7 +214,7 @@ export const api = { }, syncAccount: function ( accountId: AccountIdentifier, - options?: SyncAccountOptions + options?: AccountSyncOptions ): (__ids: CommunicationIds) => Promise { return (__ids: CommunicationIds) => _syncAccount(sendMessage, __ids, accountId, options) }, diff --git a/packages/mobile/capacitor/walletPluginApi.ts b/packages/mobile/capacitor/walletPluginApi.ts index 61169830ce2..03d8701d624 100644 --- a/packages/mobile/capacitor/walletPluginApi.ts +++ b/packages/mobile/capacitor/walletPluginApi.ts @@ -21,7 +21,7 @@ import { startBackgroundSync as _startBackgroundSync, stopBackgroundSync as _stopBackgroundSync, syncAccount as _syncAccount, - SyncAccountOptions, + AccountSyncOptions, syncAccounts as _syncAccounts, } from '@lib/typings/account' import { BridgeMessage, CommunicationIds, MessageResponse } from '@lib/typings/bridge' @@ -188,7 +188,7 @@ export const api = { (__ids) => _latestAddress(sendMessage, __ids, accountId), syncAccount: - (accountId: AccountIdentifier, options?: SyncAccountOptions): Api => + (accountId: AccountIdentifier, options?: AccountSyncOptions): Api => (__ids) => _syncAccount(sendMessage, __ids, accountId, options), isLatestAddressUnused: diff --git a/packages/shared/components/AccountSwitcher.svelte b/packages/shared/components/AccountSwitcher.svelte index be8fcea1f72..68a19360148 100644 --- a/packages/shared/components/AccountSwitcher.svelte +++ b/packages/shared/components/AccountSwitcher.svelte @@ -1,7 +1,7 @@ -{#if $selectedAccount} +{#if $selectedAccountStore}
- {#key $selectedAccount?.id} + {#key $selectedAccountStore?.id}
{#if $accountRoute !== AccountRoute.Manage} {/if} - {#if $activeProfile?.hiddenAccounts?.includes($selectedAccount?.id)} + {#if $activeProfile?.hiddenAccounts?.includes($selectedAccountStore?.id)}
{localize('general.accountRemoved')}
@@ -413,12 +371,12 @@ {:else if $accountRoute === AccountRoute.Receive} {:else if $accountRoute === AccountRoute.Manage} - + {/if}
- +
diff --git a/packages/shared/routes/dashboard/wallet/views/AccountBalance.svelte b/packages/shared/routes/dashboard/wallet/views/AccountBalance.svelte index 2b5e8761b33..fde020cef34 100644 --- a/packages/shared/routes/dashboard/wallet/views/AccountBalance.svelte +++ b/packages/shared/routes/dashboard/wallet/views/AccountBalance.svelte @@ -6,7 +6,7 @@ import { accountRoute, accountRouter } from '@core/router' import { AccountRoute } from '@core/router/enums' import { formatUnitBestMatch, formatUnitPrecision } from 'shared/lib/units' - import { selectedAccount } from 'shared/lib/wallet' + import { selectedAccountStore } from 'shared/lib/wallet' export let classes = '' @@ -42,12 +42,12 @@

{showPreciseBalance - ? formatUnitPrecision($selectedAccount?.rawIotaBalance, Unit.Mi) - : formatUnitBestMatch($selectedAccount?.rawIotaBalance, true, 3)} + ? formatUnitPrecision($selectedAccountStore?.rawIotaBalance, Unit.Mi) + : formatUnitBestMatch($selectedAccountStore?.rawIotaBalance, true, 3)}

- {$selectedAccount?.balanceEquiv} + {$selectedAccountStore?.balanceEquiv}
diff --git a/packages/shared/routes/dashboard/wallet/views/AccountHistory.svelte b/packages/shared/routes/dashboard/wallet/views/AccountHistory.svelte index 4cc4f8f4335..3323ff0b761 100644 --- a/packages/shared/routes/dashboard/wallet/views/AccountHistory.svelte +++ b/packages/shared/routes/dashboard/wallet/views/AccountHistory.svelte @@ -10,11 +10,14 @@ isSyncing, getIncomingFlag, isFirstSessionSync, - selectedAccount, + selectedAccountStore, selectedMessage, sendAddressFromTransactionPayload, receiverAddressesFromTransactionPayload, walletSetupType, + accountSyncingQueueStore, + selectedAccountIdStore, + currentSyncingAccountStore, } from 'shared/lib/wallet' import { Transaction } from 'shared/lib/typings/message' import { SetupType } from 'shared/lib/typings/setup' @@ -32,11 +35,13 @@ selectedMessage.set(null) } + $: isSelectedAccountSyncing = $currentSyncingAccountStore?.id === $selectedAccountIdStore || $isSyncing + const handleSyncAccountClick = () => { if (!$isSyncing) { const _syncAccount = () => { $isSyncing = true - api.syncAccount($selectedAccount?.id, { + api.syncAccount($selectedAccountStore?.id, { onSuccess() { $isSyncing = false }, @@ -165,14 +170,12 @@ {localize('general.transactions')} • {queryTransactions.length} - {#if !$selectedMessage} - - {/if} +
    diff --git a/packages/shared/routes/dashboard/wallet/views/BarChart.svelte b/packages/shared/routes/dashboard/wallet/views/BarChart.svelte index ec13ae044bc..ad1e33eecae 100644 --- a/packages/shared/routes/dashboard/wallet/views/BarChart.svelte +++ b/packages/shared/routes/dashboard/wallet/views/BarChart.svelte @@ -2,7 +2,7 @@ import { Chart, Text } from 'shared/components' import { getAccountActivityData } from 'shared/lib/chart' import { localize } from '@core/i18n' - import { selectedAccount } from 'shared/lib/wallet' + import { selectedAccountStore } from 'shared/lib/wallet' let chartData = { incoming: {}, @@ -14,8 +14,8 @@ $: labels = chartData.labels $: { - if (localize || $selectedAccount) { - chartData = getAccountActivityData($selectedAccount) + if (localize || $selectedAccountStore) { + chartData = getAccountActivityData($selectedAccountStore) } } diff --git a/packages/shared/routes/dashboard/wallet/views/LineChart.svelte b/packages/shared/routes/dashboard/wallet/views/LineChart.svelte index 3a090ec5bbf..314ac4d49bf 100644 --- a/packages/shared/routes/dashboard/wallet/views/LineChart.svelte +++ b/packages/shared/routes/dashboard/wallet/views/LineChart.svelte @@ -14,11 +14,11 @@ import { BalanceHistory } from 'shared/lib/typings/wallet' import { AvailableExchangeRates, CurrencyTypes } from 'shared/lib/typings/currency' import { HistoryDataProps } from 'shared/lib/typings/market' - import { getAccountBalanceHistory, selectedAccount } from 'shared/lib/wallet' + import { getAccountBalanceHistory, selectedAccountStore } from 'shared/lib/wallet' import { onMount } from 'svelte' let balanceHistory: BalanceHistory - $: $selectedAccount, $priceData, (balanceHistory = getAccountBalanceHistory($selectedAccount, $priceData)) + $: $selectedAccountStore, $priceData, (balanceHistory = getAccountBalanceHistory($selectedAccountStore, $priceData)) let chartData: ChartData = { labels: [], data: [], tooltips: [] } const chartTypeDropdownItems: { value: string; label: string }[] = [] @@ -39,14 +39,14 @@ /** Chart data */ $: { - if (localize || $selectedDashboardChart || $activeProfile?.settings.chartSelectors || $selectedAccount) { + if (localize || $selectedDashboardChart || $activeProfile?.settings.chartSelectors || $selectedAccountStore) { if ($activeProfile?.settings) { // Account value chart switch ($selectedWalletChart) { case WalletChartType.HOLDINGS: chartData = getChartDataFromBalanceHistory({ balanceHistory, - currentBalance: $selectedAccount.rawIotaBalance, + currentBalance: $selectedAccountStore.rawIotaBalance, tokenType: CurrencyTypes.IOTA.toLocaleLowerCase(), convertToSelectedCurrency: false, }) @@ -54,7 +54,7 @@ case WalletChartType.PORTFOLIO: chartData = getChartDataFromBalanceHistory({ balanceHistory, - currentBalance: $selectedAccount.rawIotaBalance, + currentBalance: $selectedAccountStore.rawIotaBalance, tokenType: CurrencyTypes.IOTA.toLocaleLowerCase(), convertToSelectedCurrency: true, }) @@ -117,7 +117,7 @@ function formatYAxis(value) { return formatCurrencyValue( value, - $selectedAccount && $selectedWalletChart === WalletChartType.HOLDINGS + $selectedAccountStore && $selectedWalletChart === WalletChartType.HOLDINGS ? CurrencyTypes.IOTA : $activeProfile?.settings.chartSelectors.currency ? $activeProfile?.settings.chartSelectors.currency @@ -184,11 +184,11 @@
diff --git a/packages/shared/routes/dashboard/wallet/views/ManageAccount.svelte b/packages/shared/routes/dashboard/wallet/views/ManageAccount.svelte index dac8cd1913c..e18ac6fb61d 100644 --- a/packages/shared/routes/dashboard/wallet/views/ManageAccount.svelte +++ b/packages/shared/routes/dashboard/wallet/views/ManageAccount.svelte @@ -3,7 +3,7 @@ import { getTrimmedLength } from 'shared/lib/helpers' import { localize } from '@core/i18n' import { activeProfile, getColor, setProfileAccount } from 'shared/lib/profile' - import { api, MAX_ACCOUNT_NAME_LENGTH, selectedAccount, wallet } from 'shared/lib/wallet' + import { api, MAX_ACCOUNT_NAME_LENGTH, selectedAccountStore, wallet } from 'shared/lib/wallet' import { accountRouter, AccountRoute } from '@core/router' import { WalletAccount } from 'shared/lib/typings/wallet' @@ -21,7 +21,7 @@ $: accountAlias, (error = '') const handleSaveClick = () => { - setProfileAccount($activeProfile, { id: $selectedAccount?.id, color }) + setProfileAccount($activeProfile, { id: $selectedAccountStore?.id, color }) const trimmedAccountAlias = accountAlias.trim() if (trimmedAccountAlias === alias) { $accountRouter.goTo(AccountRoute.Init) @@ -40,11 +40,11 @@ return (error = localize('error.account.duplicate')) } isBusy = true - api.setAlias($selectedAccount?.id, trimmedAccountAlias, { + api.setAlias($selectedAccountStore?.id, trimmedAccountAlias, { onSuccess() { accounts.update((_accounts) => _accounts.map((account) => { - if (account.id === $selectedAccount?.id) { + if (account.id === $selectedAccountStore?.id) { return Object.assign>( {} as WalletAccount, account, diff --git a/packages/shared/routes/dashboard/wallet/views/Receive.svelte b/packages/shared/routes/dashboard/wallet/views/Receive.svelte index f9884d20d95..2b823957d09 100644 --- a/packages/shared/routes/dashboard/wallet/views/Receive.svelte +++ b/packages/shared/routes/dashboard/wallet/views/Receive.svelte @@ -4,14 +4,14 @@ import { localize } from '@core/i18n' import { activeProfile, isLedgerProfile } from 'shared/lib/profile' import { setClipboard } from 'shared/lib/utils' - import { hasGeneratedALedgerReceiveAddress, isSyncing, selectedAccount } from 'shared/lib/wallet' + import { hasGeneratedALedgerReceiveAddress, isSyncing, selectedAccountStore } from 'shared/lib/wallet' export let isGeneratingAddress = false export let onGenerateAddress: (id: string) => void = () => {} const generateNewAddress = (): void => { - onGenerateAddress($selectedAccount.id) + onGenerateAddress($selectedAccountStore.id) } const handleCloseClick = (): void => { @@ -48,7 +48,7 @@
{:else}
- +
@@ -56,12 +56,12 @@ ? `${$activeProfile.settings.networkConfig.network.name} ${localize('general.address')}` : localize('general.myAddress')} - {$selectedAccount.depositAddress} + {$selectedAccountStore.depositAddress}
diff --git a/packages/shared/routes/dashboard/wallet/views/Send.svelte b/packages/shared/routes/dashboard/wallet/views/Send.svelte index 084540e330e..645a072ad62 100644 --- a/packages/shared/routes/dashboard/wallet/views/Send.svelte +++ b/packages/shared/routes/dashboard/wallet/views/Send.svelte @@ -36,7 +36,7 @@ import { LedgerDeviceState } from 'shared/lib/typings/ledger' import { changeUnits, formatUnitPrecision } from 'shared/lib/units' import { ADDRESS_LENGTH, validateBech32Address } from 'shared/lib/utils' - import { DUST_THRESHOLD, isTransferring, selectedAccount, transferState, wallet } from 'shared/lib/wallet' + import { DUST_THRESHOLD, isTransferring, selectedAccountStore, transferState, wallet } from 'shared/lib/wallet' import { mobile } from 'shared/lib/app' import { NotificationType } from 'shared/lib/typings/notification' import { SendParams } from 'shared/lib/typings/sendParams' @@ -49,7 +49,7 @@ const { accounts } = $wallet const liveAccounts = getContext>('liveAccounts') - const addressPrefix = ($selectedAccount ?? $liveAccounts[0])?.depositAddress?.split('1')?.[0] + const addressPrefix = ($selectedAccountStore ?? $liveAccounts[0])?.depositAddress?.split('1')?.[0] enum SEND_TYPE { EXTERNAL = 'sendPayment', @@ -301,11 +301,11 @@ * amounts to 1 MI to compare them. */ const amountAsMi = changeUnits(amountAsIota, Unit.i, Unit.Mi) - const balanceAsMi = changeUnits($selectedAccount.rawIotaBalance, Unit.i, Unit.Mi) + const balanceAsMi = changeUnits($selectedAccountStore.rawIotaBalance, Unit.i, Unit.Mi) const isMaxAmount = Math.round(amountAsMi) === Math.round(balanceAsMi) - const hasDustRemaining = Math.abs($selectedAccount.rawIotaBalance - amountAsIota) < DUST_THRESHOLD - return isMaxAmount && isFiat && hasDustRemaining ? $selectedAccount.rawIotaBalance : amountAsIota + const hasDustRemaining = Math.abs($selectedAccountStore.rawIotaBalance - amountAsIota) < DUST_THRESHOLD + return isMaxAmount && isFiat && hasDustRemaining ? $selectedAccountStore.rawIotaBalance : amountAsIota } const handleSendClick = (): void => { @@ -340,7 +340,7 @@ } else { amountRaw = setRawAmount(amountAsFloat) - if (amountRaw > $selectedAccount.rawIotaBalance) { + if (amountRaw > $selectedAccountStore.rawIotaBalance) { amountError = localize('error.send.amountTooHigh') } else if (amountRaw <= 0) { amountError = localize('error.send.amountZero') @@ -370,7 +370,7 @@ openPopup({ type: 'transaction', props: { - accountId: $selectedAccount.id, + accountId: $selectedAccountStore.id, internal: internal || accountAlias, amount: amountRaw, unit, @@ -391,8 +391,13 @@ * in another account. Send parameters are reset once the transfer completes. */ isInternal - ? onInternalTransfer($selectedAccount.id, to.id, amountRaw, selectedSendType === SEND_TYPE.INTERNAL) - : onSend($selectedAccount.id, address, amountRaw) + ? onInternalTransfer( + $selectedAccountStore.id, + to.id, + amountRaw, + selectedSendType === SEND_TYPE.INTERNAL + ) + : onSend($selectedAccountStore.id, address, amountRaw) if ($isSoftwareProfile) { _send(isInternal) @@ -415,9 +420,13 @@ const handleMaxClick = (): void => { amount = isFiatCurrency(unit) ? formatNumber( - convertToFiat($selectedAccount.rawIotaBalance, $currencies[CurrencyTypes.USD], $exchangeRates[unit]) + convertToFiat( + $selectedAccountStore.rawIotaBalance, + $currencies[CurrencyTypes.USD], + $exchangeRates[unit] + ) ) - : formatUnitPrecision($selectedAccount.rawIotaBalance, unit, false) + : formatUnitPrecision($selectedAccountStore.rawIotaBalance, unit, false) } const updateFromSendParams = (sendParams: SendParams): void => { @@ -425,11 +434,11 @@ unit = sendParams.unit ?? (Number(sendParams.amount) === 0 ? Unit.Mi : Unit.i) amount = sendParams.amount !== undefined ? String(sendParams.amount) : '' address = sendParams.address - to = sendParams?.toWalletAccount?.id !== $selectedAccount.id ? sendParams?.toWalletAccount : undefined + to = sendParams?.toWalletAccount?.id !== $selectedAccountStore.id ? sendParams?.toWalletAccount : undefined if (accountsDropdownItems) { to = $liveAccounts.length === 2 - ? accountsDropdownItems[$selectedAccount.id === $liveAccounts[0].id ? 1 : 0] + ? accountsDropdownItems[$selectedAccountStore.id === $liveAccounts[0].id ? 1 : 0] : to } } @@ -529,7 +538,7 @@ value={to?.label || null} label={localize('general.to')} placeholder={localize('general.to')} - items={accountsDropdownItems.filter((a) => a.id !== $selectedAccount.id)} + items={accountsDropdownItems.filter((a) => a.id !== $selectedAccountStore.id)} onSelect={handleToSelect} disabled={$isTransferring || $liveAccounts.length === 2} error={toError} From 2063f6549115385aa514e6297b3e74948656d232 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bego=C3=B1a=20=C3=81lvarez=20de=20la=20Cruz?= Date: Thu, 5 May 2022 03:40:52 +0200 Subject: [PATCH 088/171] fix: pending participation subscription (#3119) * feat: move participation subscription from popup manager to dashboard and properly unsubscribe * chore: fix variable name * feat: remove participation subscription from staking manager * feat: rename function Co-authored-by: Charlie Varley --- .../components/popups/StakingManager.svelte | 83 ++++--------------- packages/shared/lib/participation/stores.ts | 13 ++- .../shared/routes/dashboard/Dashboard.svelte | 10 +++ 3 files changed, 35 insertions(+), 71 deletions(-) diff --git a/packages/shared/components/popups/StakingManager.svelte b/packages/shared/components/popups/StakingManager.svelte index 3f3e2dc0631..5aa8d15638b 100644 --- a/packages/shared/components/popups/StakingManager.svelte +++ b/packages/shared/components/popups/StakingManager.svelte @@ -19,11 +19,10 @@ isPerformingParticipation, isPartiallyStaked, participationAction, - participationOverview, - pendingParticipations, stakedAccounts, assemblyStakingEventState, shimmerStakingEventState, + resetPerformingParticipation, } from 'shared/lib/participation/stores' import { AccountParticipationAbility, @@ -38,45 +37,19 @@ import { NodePlugin } from 'shared/lib/typings/node' import { WalletAccount } from 'shared/lib/typings/wallet' import { formatUnitBestMatch } from 'shared/lib/units' - import { selectedAccountStore, selectedAccountIdStore, transferState, wallet } from 'shared/lib/wallet' + import { selectedAccountStore } from 'shared/lib/wallet' import { localize } from '@core/i18n' export let shouldParticipateOnMount = false export let participations: Participation[] = [] - let pendingParticipationIds: string[] = [] - let previousPendingParticipationsLength = 0 - let { accounts } = $wallet - $: participationAbility = getAccountParticipationAbility($selectedAccountStore) $: canStake = canParticipate($assemblyStakingEventState) || canParticipate($shimmerStakingEventState) - $: $participationOverview, resetAccounts() $: $stakedAccounts, $selectedAccountStore, async () => getParticipationOverview(ASSEMBLY_EVENT_ID) $: isCurrentAccountStaked = isAccountStaked($selectedAccountStore?.id) - function resetAccounts(): void { - /** - * NOTE: This is necessary for the page - * to be re-rendered because updating arrays - * in place will not update the UI (requires - * variable re-assignment). - */ - accounts = accounts - } - - function resetView(): void { - if (!isSoftwareProfile) { - transferState.set(null) - } - - isPerformingParticipation.set(false) - participationAction.set(undefined) - - resetAccounts() - } - function displayErrorNotification(error): void { showAppNotification({ type: 'error', @@ -96,11 +69,6 @@ isPerformingParticipation.set(true) - const _sync = (messageIds: string[]) => { - messageIds.forEach((id) => pendingParticipationIds.push(id)) - previousPendingParticipationsLength = messageIds.length - } - const hasParticipationPlugin = $networkStatus.nodePlugins.includes(NodePlugin.Participation) if (!hasParticipationPlugin) { showAppNotification({ @@ -110,32 +78,28 @@ }), }) - resetView() + resetPerformingParticipation() return } switch ($participationAction) { case ParticipationAction.Stake: { - await participate($selectedAccountStore?.id, participations) - .then((messageIds) => _sync(messageIds)) - .catch((err) => { - console.error(err) + await participate($selectedAccountStore?.id, participations).catch((err) => { + console.error(err) - displayErrorNotification(err) - resetView() - }) + displayErrorNotification(err) + resetPerformingParticipation() + }) break } case ParticipationAction.Unstake: - await stopParticipating($selectedAccountStore?.id, STAKING_EVENT_IDS) - .then((messageIds) => _sync(messageIds)) - .catch((err) => { - console.error(err) + await stopParticipating($selectedAccountStore?.id, STAKING_EVENT_IDS).catch((err) => { + console.error(err) - displayErrorNotification(err) - resetView() - }) + displayErrorNotification(err) + resetPerformingParticipation() + }) break default: break @@ -189,7 +153,7 @@ }), }) - resetView() + resetPerformingParticipation() return } @@ -204,25 +168,6 @@ if (shouldParticipateOnMount) { await handleParticipationAction() } - - const usubscribe = pendingParticipations.subscribe((participations) => { - const currentParticipationsLength = participations.length - - if (currentParticipationsLength < previousPendingParticipationsLength) { - const latestParticipationIds = participations.map((participation) => participation.messageId) - - if (latestParticipationIds.length === 0) { - resetView() - } - - pendingParticipationIds = latestParticipationIds - previousPendingParticipationsLength = currentParticipationsLength - } - }) - - return () => { - usubscribe() - } }) let showTooltip = false diff --git a/packages/shared/lib/participation/stores.ts b/packages/shared/lib/participation/stores.ts index 42325d7f9ae..11a28dab465 100644 --- a/packages/shared/lib/participation/stores.ts +++ b/packages/shared/lib/participation/stores.ts @@ -2,7 +2,7 @@ import { derived, get, Readable, writable } from 'svelte/store' import { networkStatus } from '../networkStatus' import { NodePlugin } from '../typings/node' import { MILLISECONDS_PER_SECOND, SECONDS_PER_MILESTONE } from '../time' -import { selectedAccountStore, selectedAccountIdStore, wallet } from '../wallet' +import { selectedAccountStore, selectedAccountIdStore, transferState, wallet } from '../wallet' import { WalletAccount } from '../typings/wallet' import { ASSEMBLY_EVENT_ID, SHIMMER_EVENT_ID } from './constants' @@ -18,7 +18,7 @@ import { } from './types' import { NetworkStatus } from '@lib/typings/network' import { getStakingEventFromAirdrop, isAirdropAvailable } from '@lib/participation/staking' -import { activeProfile } from '@lib/profile' +import { activeProfile, isSoftwareProfile } from '@lib/profile' /** * The store for keeping track of pending participations. @@ -394,3 +394,12 @@ export const hasPendingParticipation = (id: string): boolean => */ export const getPendingParticipation = (id: string): PendingParticipation | undefined => get(pendingParticipations).find((participation) => participation.messageId === id) + +export const resetPerformingParticipation = (): void => { + if (!get(isSoftwareProfile)) { + transferState.set(null) + } + + isPerformingParticipation.set(false) + participationAction.set(undefined) +} diff --git a/packages/shared/routes/dashboard/Dashboard.svelte b/packages/shared/routes/dashboard/Dashboard.svelte index 808eea4c3f9..0f9e520d4e0 100644 --- a/packages/shared/routes/dashboard/Dashboard.svelte +++ b/packages/shared/routes/dashboard/Dashboard.svelte @@ -54,6 +54,7 @@ LAST_ASSEMBLY_STAKING_PERIOD, LAST_SHIMMER_STAKING_PERIOD, } from '@lib/participation/constants' + import { pendingParticipations, resetParticipation } from 'shared/lib/participation/stores' export let locale: Locale @@ -89,6 +90,14 @@ } }) + let previousPendingParticipationsLength = 0 + const unsubscribePendingParticipations = pendingParticipations.subscribe((participations) => { + if (participations?.length < previousPendingParticipationsLength && participations?.length === 0) { + resetParticipation() + } + previousPendingParticipationsLength = participations?.length ?? 0 + }) + $: if (!$isSyncing && $isFirstSessionSync && $accountsLoaded) { void updateStakingPeriodCache() } @@ -213,6 +222,7 @@ onDestroy(() => { unsubscribeAccountsLoaded() unsubscribeOngoingSnapshot() + unsubscribePendingParticipations() Platform.DeepLinkManager.clearDeepLinkRequest() Platform.removeListenersForEvent('deep-link-params') From 5382b1ba1ca2b2d054732c85206548e82f5bb0c5 Mon Sep 17 00:00:00 2001 From: Charlie Varley Date: Thu, 5 May 2022 22:14:15 +0100 Subject: [PATCH 089/171] fix: vote totals calculation and display and other bug fixes (#3142) * fix: dashboard reset participation * fix: maximum vote calculation and display * fix: voting rate tooltip formatting * enhancement: update wallet-rs revision * fix: partial merge store logic * enhancement: update wallet-rs revision --- packages/backend/Cargo.toml | 2 +- .../backend/bindings/node/native/Cargo.lock | 2 +- .../components/GovernanceInfoTooltip.svelte | 6 +- packages/shared/lib/participation/account.ts | 28 +++++---- .../shared/routes/dashboard/Dashboard.svelte | 58 +++++++++---------- .../views/GovernanceEventDetails.svelte | 21 ++++--- 6 files changed, 62 insertions(+), 55 deletions(-) diff --git a/packages/backend/Cargo.toml b/packages/backend/Cargo.toml index 88a785fb6b9..4797fed9289 100644 --- a/packages/backend/Cargo.toml +++ b/packages/backend/Cargo.toml @@ -8,7 +8,7 @@ exclude = ["/bindings", "/api-wrapper"] [dependencies] tokio = { version = "1.12.0", default-features = false } once_cell = { version = "1.8.0", default-features = false } -iota-wallet = { git = "https://github.com/iotaledger/wallet.rs", rev = "a084002da15c072f0f7256c74403b05dad3c7d8b", default-features = false, features = ["stronghold", "ledger-nano", "ledger-nano-simulator", "participation"] } +iota-wallet = { git = "https://github.com/iotaledger/wallet.rs", rev = "d9a74bc6f8996160c7c86097963d8082b21b1bc8", default-features = false, features = ["stronghold", "ledger-nano", "ledger-nano-simulator", "participation"] } serde = { version = "1.0.130", default-features = false, features = ["derive"] } serde_json = { version = "1.0.68", default-features = false } riker = "0.4.2" diff --git a/packages/backend/bindings/node/native/Cargo.lock b/packages/backend/bindings/node/native/Cargo.lock index 1620db826af..b752ed0813a 100644 --- a/packages/backend/bindings/node/native/Cargo.lock +++ b/packages/backend/bindings/node/native/Cargo.lock @@ -1628,7 +1628,7 @@ dependencies = [ [[package]] name = "iota-wallet" version = "0.2.0" -source = "git+https://github.com/iotaledger/wallet.rs?rev=a084002da15c072f0f7256c74403b05dad3c7d8b#a084002da15c072f0f7256c74403b05dad3c7d8b" +source = "git+https://github.com/iotaledger/wallet.rs?rev=d9a74bc6f8996160c7c86097963d8082b21b1bc8#d9a74bc6f8996160c7c86097963d8082b21b1bc8" dependencies = [ "async-trait", "backtrace", diff --git a/packages/shared/components/GovernanceInfoTooltip.svelte b/packages/shared/components/GovernanceInfoTooltip.svelte index 9ea0486e556..cc33b95eb1b 100644 --- a/packages/shared/components/GovernanceInfoTooltip.svelte +++ b/packages/shared/components/GovernanceInfoTooltip.svelte @@ -43,11 +43,7 @@ break } - $: votesPerMilestone = formatNumber( - ($selectedAccountStore?.rawIotaBalance / 1000) * SECONDS_PER_MILESTONE || 0, - 0, - 0 - ) + $: votesPerMilestone = formatNumber($selectedAccountStore?.rawIotaBalance / 1000 || 0, 0, 0, 2, true) diff --git a/packages/shared/lib/participation/account.ts b/packages/shared/lib/participation/account.ts index e3687581c8a..198e02b82bf 100644 --- a/packages/shared/lib/participation/account.ts +++ b/packages/shared/lib/participation/account.ts @@ -109,13 +109,21 @@ export const currentAccountTreasuryVoteValue = derived( } ) +export const currentTreasuryParticipation = derived( + selectedAccountParticipationOverview, + ($selectedAccountParticipationOverview) => { + const latestParticipation = $selectedAccountParticipationOverview?.trackedParticipations?.[ + TREASURY_VOTE_EVENT_ID + ]?.reduce((max, current) => (max.startMilestoneIndex > current.startMilestoneIndex ? max : current)) + return latestParticipation?.endMilestoneIndex === 0 ? latestParticipation : null + } +) + export const hasCurrentAccountReceivedFundsSinceLastTreasuryVote = derived( - [selectedAccountParticipationOverview, selectedAccountStore], - ([$selectedAccountParticipationOverview, $selectedAccountStore]) => { - const currentParticipation = - $selectedAccountParticipationOverview?.trackedParticipations?.[TREASURY_VOTE_EVENT_ID]?.slice(-1)?.[0] - const { amount } = currentParticipation ?? {} - return $selectedAccountStore && amount !== $selectedAccountStore.rawIotaBalance + selectedAccountStore, + ($selectedAccountStore) => { + const { amount } = get(currentTreasuryParticipation) ?? {} + return $selectedAccountStore && amount && amount !== $selectedAccountStore.rawIotaBalance } ) @@ -124,11 +132,9 @@ export const hasCurrentAccountReceivedFundsSinceLastTreasuryVote = derived( * the selected account. */ export const currentAccountTreasuryVotePartiallyUnvotedAmount = derived( - [selectedAccountParticipationOverview, selectedAccountStore], - ([$selectedAccountParticipationOverview, $selectedAccountStore]) => { - const currentParticipation = - $selectedAccountParticipationOverview?.trackedParticipations?.[TREASURY_VOTE_EVENT_ID]?.slice(-1)?.[0] - const { amount } = currentParticipation ?? {} + selectedAccountStore, + ($selectedAccountStore) => { + const { amount } = get(currentTreasuryParticipation) ?? {} const accountBalance = $selectedAccountStore?.rawIotaBalance ?? 0 return amount < accountBalance ? accountBalance - amount : 0 } diff --git a/packages/shared/routes/dashboard/Dashboard.svelte b/packages/shared/routes/dashboard/Dashboard.svelte index 1d72353472b..d9dbc4abea8 100644 --- a/packages/shared/routes/dashboard/Dashboard.svelte +++ b/packages/shared/routes/dashboard/Dashboard.svelte @@ -1,12 +1,29 @@
{/if} - {#if event?.status?.status === ParticipationEventState.Holding && accountVotes > 0} + {#if event?.status?.status === ParticipationEventState.Holding && $currentTreasuryParticipation}
From b3c4d516efe315403e1c18999d4206431e42cf73 Mon Sep 17 00:00:00 2001 From: Jean Ribeiro Date: Thu, 5 May 2022 20:44:21 -0300 Subject: [PATCH 090/171] fix: refactors getColor (#3086) * fix: refactors getColor * fix: adds fallback to not found color * fix: changes AccountColors to AccountColor * fix: adds last selected account back * fix: moves AccountColor to a new file "color.ts" * chore: update variable name * fix: account switcher modal colours Co-authored-by: Charlie Varley --- .../shared/components/AccountSwitcher.svelte | 4 ++-- .../shared/components/ActivityDetail.svelte | 6 ++--- packages/shared/components/ColorPicker.svelte | 10 ++++---- packages/shared/components/WalletPill.svelte | 4 ++-- packages/shared/components/charts/Bar.svelte | 4 ++-- packages/shared/components/charts/Line.svelte | 8 +++---- .../components/modals/AccountSwitcher.svelte | 4 ++-- .../components/popups/CreateAccount.svelte | 15 ++++++------ packages/shared/lib/chart.ts | 5 ++-- packages/shared/lib/profile.ts | 24 +++++++------------ packages/shared/lib/typings/chart.ts | 4 ++-- packages/shared/lib/typings/color.ts | 16 +++++++++++++ packages/shared/lib/wallet.ts | 16 ------------- .../wallet/views/ManageAccount.svelte | 8 +++---- 14 files changed, 62 insertions(+), 66 deletions(-) create mode 100644 packages/shared/lib/typings/color.ts diff --git a/packages/shared/components/AccountSwitcher.svelte b/packages/shared/components/AccountSwitcher.svelte index 68a19360148..f19318636bf 100644 --- a/packages/shared/components/AccountSwitcher.svelte +++ b/packages/shared/components/AccountSwitcher.svelte @@ -1,6 +1,6 @@
diff --git a/packages/shared/components/ColorPicker.svelte b/packages/shared/components/ColorPicker.svelte index 3a1b49db3c5..dcf9393d96e 100644 --- a/packages/shared/components/ColorPicker.svelte +++ b/packages/shared/components/ColorPicker.svelte @@ -1,15 +1,15 @@ diff --git a/packages/shared/components/charts/Bar.svelte b/packages/shared/components/charts/Bar.svelte index 3d7a3d60d44..fc29cf58493 100644 --- a/packages/shared/components/charts/Bar.svelte +++ b/packages/shared/components/charts/Bar.svelte @@ -1,13 +1,13 @@
From e5cc979eaa6eb8b6137e37c741e1f67dfdddb014 Mon Sep 17 00:00:00 2001 From: Charlie Varley Date: Fri, 6 May 2022 02:18:12 +0100 Subject: [PATCH 091/171] fix: account color declaration --- .../dashboard/governance/views/GovernanceEventDetails.svelte | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/shared/routes/dashboard/governance/views/GovernanceEventDetails.svelte b/packages/shared/routes/dashboard/governance/views/GovernanceEventDetails.svelte index 139e228083f..39e4440af9b 100644 --- a/packages/shared/routes/dashboard/governance/views/GovernanceEventDetails.svelte +++ b/packages/shared/routes/dashboard/governance/views/GovernanceEventDetails.svelte @@ -14,10 +14,11 @@ import { closePopup, openPopup } from '@lib/popup' import { isSoftwareProfile } from '@lib/profile' import { getDurationString, milestoneToDate } from '@lib/time' + import { AccountColor } from '@lib/typings/color' import { TransferProgressEventData, TransferProgressEventType, TransferState } from '@lib/typings/events' import { WalletAccount } from '@lib/typings/wallet' import { formatUnitBestMatch } from '@lib/units' - import { AccountColors, handleTransactionEventData, selectedAccountStore, transferState } from '@lib/wallet' + import { handleTransactionEventData, selectedAccountStore, transferState } from '@lib/wallet' import { Button, DashboardPane, GovernanceInfoTooltip, Icon, Text, Tooltip } from 'shared/components' import { participationAction } from 'shared/lib/participation/stores' import { popupState } from 'shared/lib/popup' @@ -438,7 +439,7 @@
From 81681bee05c6c0778f5c366b6c226dcc1d007a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bego=C3=B1a=20Alvarez?= Date: Tue, 10 May 2022 18:02:34 +0200 Subject: [PATCH 092/171] fix: receive qr responsiveness --- .../dashboard/wallet/views/Receive.svelte | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/shared/routes/dashboard/wallet/views/Receive.svelte b/packages/shared/routes/dashboard/wallet/views/Receive.svelte index f9884d20d95..ac34aaab41b 100644 --- a/packages/shared/routes/dashboard/wallet/views/Receive.svelte +++ b/packages/shared/routes/dashboard/wallet/views/Receive.svelte @@ -1,15 +1,20 @@ -
+
{localize('general.receiveFunds')} @@ -48,7 +57,7 @@
{:else}
- +
From ea041d0c2e796d87319e42273b8b36998d14b8c0 Mon Sep 17 00:00:00 2001 From: Charlie Varley Date: Tue, 10 May 2022 18:01:58 +0100 Subject: [PATCH 093/171] fix: voting polish and performance (#3154) * fix: close popup on participation success * fix: reset governance router on tab click * fix: unnecessary import * fix: set accounts loaded store after completing processing * chore: rename voting power route * fix: limit calls to get participation info to poll cycle only * enhancement: adjust participation poll logic * enhancement: add loading states to voting and staking --- packages/shared/components/Sidebar.svelte | 31 +++++------ .../components/popups/StakingManager.svelte | 7 +-- packages/shared/lib/networkStatus.ts | 2 +- .../shared/lib/participation/participation.ts | 52 ++++++++++++++----- packages/shared/lib/participation/stores.ts | 5 ++ packages/shared/lib/walletApiListeners.ts | 7 ++- packages/shared/locales/en.json | 6 ++- .../shared/routes/dashboard/Dashboard.svelte | 15 ++---- .../dashboard/governance/Governance.svelte | 6 --- .../views/GovernanceDashboard.svelte | 4 +- .../governance/views/GovernanceEvents.svelte | 33 +++++++----- ...r.svelte => GovernanceVotingWeight.svelte} | 0 .../dashboard/governance/views/index.js | 2 +- .../routes/dashboard/staking/Staking.svelte | 6 +-- .../staking/views/StakingInfo.svelte | 41 ++++++++++----- .../routes/dashboard/wallet/Wallet.svelte | 2 +- 16 files changed, 132 insertions(+), 87 deletions(-) rename packages/shared/routes/dashboard/governance/views/{GovernanceVotingPower.svelte => GovernanceVotingWeight.svelte} (100%) diff --git a/packages/shared/components/Sidebar.svelte b/packages/shared/components/Sidebar.svelte index f8cdcbd06a5..4e76d4edec1 100644 --- a/packages/shared/components/Sidebar.svelte +++ b/packages/shared/components/Sidebar.svelte @@ -1,34 +1,34 @@ diff --git a/packages/shared/components/popups/StakingManager.svelte b/packages/shared/components/popups/StakingManager.svelte index 0a25ddd2335..96490d76064 100644 --- a/packages/shared/components/popups/StakingManager.svelte +++ b/packages/shared/components/popups/StakingManager.svelte @@ -13,12 +13,11 @@ isAccountStaked, getIotasUntilMinimumAirdropReward, } from 'shared/lib/participation' - import { getParticipationOverview, participate, stopParticipating } from 'shared/lib/participation/api' - import { ASSEMBLY_EVENT_ID, STAKING_EVENT_IDS } from 'shared/lib/participation/constants' + import { participate, stopParticipating } from 'shared/lib/participation/api' + import { STAKING_EVENT_IDS } from 'shared/lib/participation/constants' import { isPerformingParticipation, participationAction, - stakedAccounts, assemblyStakingEventState, shimmerStakingEventState, resetPerformingParticipation, @@ -46,8 +45,6 @@ $: participationAbility = getAccountParticipationAbility($selectedAccountStore) $: canStake = canParticipate($assemblyStakingEventState) || canParticipate($shimmerStakingEventState) - $: $stakedAccounts, $selectedAccountStore, async () => getParticipationOverview(ASSEMBLY_EVENT_ID) - $: isCurrentAccountStaked = isAccountStaked($selectedAccountStore?.id) function displayErrorNotification(error): void { diff --git a/packages/shared/lib/networkStatus.ts b/packages/shared/lib/networkStatus.ts index ea783bcb207..92fab378bd9 100644 --- a/packages/shared/lib/networkStatus.ts +++ b/packages/shared/lib/networkStatus.ts @@ -38,7 +38,7 @@ export async function pollNetworkStatus(): Promise { pollInterval = setInterval(async () => pollNetworkStatusInternal(), DEFAULT_NETWORK_STATUS_POLL_INTERVAL) } -export function clearPollNetworkInterval(): void { +export function stopNetworkPoll(): void { clearInterval(pollInterval) } diff --git a/packages/shared/lib/participation/participation.ts b/packages/shared/lib/participation/participation.ts index 1048e74417d..5510a96de15 100644 --- a/packages/shared/lib/participation/participation.ts +++ b/packages/shared/lib/participation/participation.ts @@ -11,44 +11,71 @@ import { participationHistory, participationOverview, pendingParticipations, + isFetchingParticipationInfo, } from './stores' import { AccountParticipationAbility, ParticipationAction, ParticipationEventState, StakingAirdrop } from './types' -let participationPollInterval +let shouldPollParticipation = true +let participationPollTimeout /** - * Begins polling of the participation events. + * Get participation overview data and latest events. + * + * @method fetchParticipationInfo + * + * @returns {Promise} + */ +export async function fetchParticipationInfo(): Promise { + isFetchingParticipationInfo.set(true) + await Promise.all([getParticipationOverview(ASSEMBLY_EVENT_ID), getParticipationEvents()]) + isFetchingParticipationInfo.set(false) +} + +/** + * Polls participation events 10s after the last poll completes. * * @method pollParticipation * * @returns {Promise} */ export async function pollParticipation(): Promise { - clearPollParticipationOverviewInterval() try { - await getParticipationOverview(ASSEMBLY_EVENT_ID) - await getParticipationEvents() + if (get(isFetchingParticipationInfo) || !shouldPollParticipation) return + await fetchParticipationInfo() /* eslint-disable @typescript-eslint/no-misused-promises */ - participationPollInterval = setInterval(async () => { - await getParticipationOverview(ASSEMBLY_EVENT_ID) - await getParticipationEvents() + participationPollTimeout = setTimeout(async () => { + await pollParticipation() }, PARTICIPATION_POLL_DURATION) } catch (error) { + isFetchingParticipationInfo.set(false) if (error && error?.error.includes('pluginNotFound')) { - clearPollParticipationOverviewInterval() + stopParticipationPoll() } } } +/** + * Begins polling of the participation events. + * + * @method startParticipationPoll + * + * @returns {void} + */ +export function startParticipationPoll(): void { + shouldPollParticipation = true + pollParticipation() +} + /** * Clears the polling interval for the participation overview. * - * @method clearPollParticipationOverviewInterval + * @method clearPollParticipationTimeout * * @returns {void} */ -export function clearPollParticipationOverviewInterval(): void { - clearInterval(participationPollInterval) +export function stopParticipationPoll(): void { + shouldPollParticipation = false + clearTimeout(participationPollTimeout) } /** @@ -59,6 +86,7 @@ export function clearPollParticipationOverviewInterval(): void { * @returns {void} */ export const resetParticipation = (): void => { + isFetchingParticipationInfo.set(false) isPerformingParticipation.set(false) participationAction.set(null) participationEvents.set([]) diff --git a/packages/shared/lib/participation/stores.ts b/packages/shared/lib/participation/stores.ts index cac15641c1e..114f104c4f8 100644 --- a/packages/shared/lib/participation/stores.ts +++ b/packages/shared/lib/participation/stores.ts @@ -44,6 +44,11 @@ export const participationOverview = writable([]) */ export const isPerformingParticipation = writable(false) +/** + * Whether participation overview and events are being fetched + */ +export const isFetchingParticipationInfo = writable(false) + /** * The store for accounts that are currently staked. This is NOT to hold accounts * that have been selected for staking / unstaking or have staked in the past. diff --git a/packages/shared/lib/walletApiListeners.ts b/packages/shared/lib/walletApiListeners.ts index 98089a497dc..961b38dd604 100644 --- a/packages/shared/lib/walletApiListeners.ts +++ b/packages/shared/lib/walletApiListeners.ts @@ -18,7 +18,7 @@ import { getParticipationOverview } from './participation/api' import { getPendingParticipation, hasPendingParticipation, removePendingParticipations } from './participation/stores' // PARTICIPATION import { ParticipationAction, PendingParticipation } from './participation/types' -import { openPopup } from './popup' +import { closePopup, openPopup, popupState } from './popup' import { isStrongholdLocked, updateProfile } from './profile' import type { Message } from './typings/message' import type { WalletAccount } from './typings/wallet' @@ -112,8 +112,11 @@ export const initialiseListeners = (): void => { // Instantly pull in latest participation overview. await getParticipationOverview(ASSEMBLY_EVENT_ID) - // If it is a message related to any participation event, display a notification + // If it is a message related to any participation event, display a notification and close any open participation popup displayParticipationNotification(getPendingParticipation(message.id)) + if (get(popupState).type === 'governanceManager' || get(popupState).type === 'stakingManager') { + closePopup() + } // Remove the pending participation from local store removePendingParticipations([message.id]) diff --git a/packages/shared/locales/en.json b/packages/shared/locales/en.json index cd10e7bbe96..9bfa390f85c 100644 --- a/packages/shared/locales/en.json +++ b/packages/shared/locales/en.json @@ -521,7 +521,8 @@ "commencing": "Pre-staking is open", "holding": "{duration} of staking left", "ended": "Staking has now ended", - "inactive": "No staking events detected" + "inactive": "No staking events detected", + "fetching": "Fetching staking event info..." }, "bodies": { "upcoming": "Stake your {token} tokens to automatically receive rewards every 10 seconds once staking starts on {date}.", @@ -614,7 +615,8 @@ "title": "Unable to load Community Treasury vote", "subtitle": "Please connect to a node that supports this proposal", "buttonConnect": "Connect to default node", - "buttonSettings": "View node settings" + "buttonSettings": "View node settings", + "fetching": "Fetching governance event info..." } } }, diff --git a/packages/shared/routes/dashboard/Dashboard.svelte b/packages/shared/routes/dashboard/Dashboard.svelte index d9dbc4abea8..245232abe68 100644 --- a/packages/shared/routes/dashboard/Dashboard.svelte +++ b/packages/shared/routes/dashboard/Dashboard.svelte @@ -24,17 +24,13 @@ import { appSettings } from 'shared/lib/appSettings' import { isPollingLedgerDeviceStatus, pollLedgerDeviceStatus, stopPollingLedgerStatus } from 'shared/lib/ledger' import { ongoingSnapshot, openSnapshotPopup } from 'shared/lib/migration' - import { clearPollNetworkInterval, pollNetworkStatus } from 'shared/lib/networkStatus' + import { stopNetworkPoll, pollNetworkStatus } from 'shared/lib/networkStatus' import { NOTIFICATION_TIMEOUT_NEVER, removeDisplayNotification, showAppNotification, } from 'shared/lib/notifications' - import { - clearPollParticipationOverviewInterval, - pollParticipation, - updateStakingPeriodCache, - } from 'shared/lib/participation' + import { stopParticipationPoll, startParticipationPoll, updateStakingPeriodCache } from 'shared/lib/participation' import { pendingParticipations, resetPerformingParticipation } from 'shared/lib/participation/stores' import { Platform } from 'shared/lib/platform' import { closePopup, openPopup, popupState } from 'shared/lib/popup' @@ -77,10 +73,7 @@ const unsubscribeAccountsLoaded = accountsLoaded.subscribe((val) => { if (val) { void pollNetworkStatus() - void pollParticipation() - } else { - clearPollNetworkInterval() - clearPollParticipationOverviewInterval() + void startParticipationPoll() } }) @@ -221,6 +214,8 @@ unsubscribeAccountsLoaded() unsubscribeOngoingSnapshot() unsubscribePendingParticipations() + stopNetworkPoll() + stopParticipationPoll() Platform.DeepLinkManager.clearDeepLinkRequest() Platform.removeListenersForEvent('deep-link-params') diff --git a/packages/shared/routes/dashboard/governance/Governance.svelte b/packages/shared/routes/dashboard/governance/Governance.svelte index fe9fef55cc5..8ca19802858 100644 --- a/packages/shared/routes/dashboard/governance/Governance.svelte +++ b/packages/shared/routes/dashboard/governance/Governance.svelte @@ -1,11 +1,9 @@
diff --git a/packages/shared/routes/dashboard/governance/views/GovernanceDashboard.svelte b/packages/shared/routes/dashboard/governance/views/GovernanceDashboard.svelte index cdf6f54d772..d10fc6084c4 100644 --- a/packages/shared/routes/dashboard/governance/views/GovernanceDashboard.svelte +++ b/packages/shared/routes/dashboard/governance/views/GovernanceDashboard.svelte @@ -1,6 +1,6 @@
- {#if animation} -
- + {#if $isFetchingParticipationInfo && !getStakingEventFromAirdrop(StakingAirdrop.Assembly)} + + + {:else} + {#if animation} +
+ +
+ {/if} +
+ {header} + {body} + {localize('actions.readMore')}
{/if} -
- {header} - {body} - {localize('actions.readMore')} -
diff --git a/packages/shared/routes/dashboard/governance/views/GovernanceEventInfo.svelte b/packages/shared/routes/dashboard/governance/views/GovernanceEventInfo.svelte new file mode 100644 index 00000000000..b56cde5211a --- /dev/null +++ b/packages/shared/routes/dashboard/governance/views/GovernanceEventInfo.svelte @@ -0,0 +1,246 @@ + + + +
+ + {localize(`views.governance.events.status.${event?.status?.status}`)} + + + {#if tooltip.statusTimeline.show} + + {/if} +
+ {event?.information?.name} + {event?.information?.additionalInfo} +
+ {event?.information?.payload?.questions[0]?.text} + {event?.information?.payload?.questions[0]?.additionalInfo} +
+ {#each event?.information?.payload?.questions[0]?.answers || [] as answer} + + {/each} +
+ + diff --git a/packages/shared/routes/dashboard/governance/views/GovernanceEventResults.svelte b/packages/shared/routes/dashboard/governance/views/GovernanceEventResults.svelte new file mode 100644 index 00000000000..3c6d2945185 --- /dev/null +++ b/packages/shared/routes/dashboard/governance/views/GovernanceEventResults.svelte @@ -0,0 +1,58 @@ + + + + + {localize( + `views.governance.eventDetails.${ + event?.status?.status === ParticipationEventState.Ended ? 'finalResult' : 'currentResult' + }` + )} + +
+ {#each results || [] as result, i} +
+
+
+ + {event?.information?.payload?.questions[0]?.answers[i]?.text?.split(' ')[0]} + + + {displayedPercentages[i].percentage} + +
+ + {formatNumber(result?.accumulated, 0, 0, 2, true)} + +
+ {/each} +
+ diff --git a/packages/shared/routes/dashboard/governance/views/GovernanceEventStats.svelte b/packages/shared/routes/dashboard/governance/views/GovernanceEventStats.svelte new file mode 100644 index 00000000000..bc6ab6ce0de --- /dev/null +++ b/packages/shared/routes/dashboard/governance/views/GovernanceEventStats.svelte @@ -0,0 +1,182 @@ + + + +
+ {#if accountVotes <= 0 && event?.status?.status !== ParticipationEventState.Ended} +
+
+ + {localize('views.governance.votingPower.info.title')} + + {#if $selectedAccountStore?.rawIotaBalance > 0} + + {#if tooltip.votingRate.show} + + {/if} + {/if} +
+ {$selectedAccountStore?.balance} +
+ {/if} + {#if event?.status?.status === ParticipationEventState.Upcoming} +
+ + {localize('views.governance.eventDetails.votingOpens')} + + + {formatDate(milestoneToDate(event?.information?.milestoneIndexCommence), dateFormat)} + +
+ {/if} + {#if event?.status?.status === ParticipationEventState.Upcoming || event?.status?.status === ParticipationEventState.Commencing} +
+ + {localize('views.governance.eventDetails.countingStarts')} + + + {formatDate(milestoneToDate(event?.information?.milestoneIndexStart), dateFormat)} + +
+ {/if} + {#if (event?.status?.status === ParticipationEventState.Holding && accountVotes > 0) || event?.status?.status === ParticipationEventState.Ended} +
+
+ + {localize('views.governance.eventDetails.votesCounted')} + + {#if event?.status?.status === ParticipationEventState.Holding} + + {#if tooltip.countedVotes.show} + + {/if} + {/if} +
+ + {formatNumber(accountVotes, 0, 0, 2, true)} + +
+ {/if} + {#if event?.status?.status === ParticipationEventState.Holding && $currentTreasuryParticipation} +
+
+ + {localize('views.governance.eventDetails.maximumVotes')} + + + {#if tooltip.maximumVotes.show} + + {/if} +
+ + {formatNumber(maximumVotes, 0, 0, 2, true)} + +
+ {/if} + {#if event?.status?.status === ParticipationEventState.Holding || event?.status?.status === ParticipationEventState.Ended} +
+ + {localize('views.governance.eventDetails.votingProgress')} + + {getDurationString(progress)} +
+ {/if} +
+
diff --git a/packages/shared/routes/dashboard/governance/views/index.js b/packages/shared/routes/dashboard/governance/views/index.js index 438fabb5e62..2a836aa4a4f 100644 --- a/packages/shared/routes/dashboard/governance/views/index.js +++ b/packages/shared/routes/dashboard/governance/views/index.js @@ -1,5 +1,8 @@ -export { default as GovernanceVotingWeight } from './GovernanceVotingWeight.svelte' -export { default as GovernanceInfo } from './GovernanceInfo.svelte' -export { default as GovernanceEvents } from './GovernanceEvents.svelte' export { default as GovernanceDashboard } from './GovernanceDashboard.svelte' export { default as GovernanceEventDetails } from './GovernanceEventDetails.svelte' +export { default as GovernanceEventInfo } from './GovernanceEventInfo.svelte' +export { default as GovernanceEventResults } from './GovernanceEventResults.svelte' +export { default as GovernanceEvents } from './GovernanceEvents.svelte' +export { default as GovernanceEventStats } from './GovernanceEventStats.svelte' +export { default as GovernanceInfo } from './GovernanceInfo.svelte' +export { default as GovernanceVotingWeight } from './GovernanceVotingWeight.svelte' From 978478acdf92275e0e8579874a12b6bc2ee8fff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bego=C3=B1a=20=C3=81lvarez=20de=20la=20Cruz?= Date: Wed, 18 May 2022 20:22:09 +0200 Subject: [PATCH 109/171] Feat: polish governance init UI (#3224) * feat: split governance event details code into multiple files * feat: update voting icon * fix: pane bottom shadow cut off * fix: treasury bg image cutting off buttons on wide screens Co-authored-by: Charlie Varley --- .../shared/components/Illustration.svelte | 32 +++++++++---- packages/shared/components/Sidebar.svelte | 2 +- packages/shared/components/icon/icons.js | 48 ++++--------------- .../dashboard/governance/Governance.svelte | 2 +- .../views/GovernanceDashboard.svelte | 2 +- .../views/GovernanceEventDetails.svelte | 2 +- .../governance/views/GovernanceEvents.svelte | 20 ++++++-- .../routes/dashboard/staking/Staking.svelte | 2 +- 8 files changed, 54 insertions(+), 56 deletions(-) diff --git a/packages/shared/components/Illustration.svelte b/packages/shared/components/Illustration.svelte index c1c891d3c16..bdb333b4eca 100644 --- a/packages/shared/components/Illustration.svelte +++ b/packages/shared/components/Illustration.svelte @@ -4,6 +4,9 @@ export let illustration = undefined export let width = undefined export let height = undefined + // when set "background" to true, the illustration will be displayed as a background image of a div + // and a numeric height must be defined + export let background = false export let classes = '' $: darkModeEnabled = $appSettings.darkMode @@ -96,14 +99,27 @@ {#if selected} - + {#if background} +
+ {:else} + + {/if} {:else}
{/if} + + diff --git a/packages/shared/components/Sidebar.svelte b/packages/shared/components/Sidebar.svelte index 76317a692ab..076b7f8fae7 100644 --- a/packages/shared/components/Sidebar.svelte +++ b/packages/shared/components/Sidebar.svelte @@ -94,7 +94,7 @@ onClick: openStaking, }, { - icon: 'policy', + icon: 'voting', label: 'governance', route: DashboardRoute.Governance, onClick: openGovernance, diff --git a/packages/shared/components/icon/icons.js b/packages/shared/components/icon/icons.js index fffe1ddac6d..6f4adea1629 100644 --- a/packages/shared/components/icon/icons.js +++ b/packages/shared/components/icon/icons.js @@ -1127,25 +1127,24 @@ export const icons = { height: 24, path: [ { - d: 'M4.99999 2H15.0001C17.7615 2 20.0001 4.23858 20.0001 7V17H18.0001V7C18.0001 5.34315 16.6569 4 15.0001 4H7.00001L7.00005 17C7.00005 18.6569 8.3432 20 10.0001 20H12.4376V22H10.0001C7.23863 22 5.00005 19.7614 5.00005 17L4.99999 2Z', - fillRule: 'evenodd', - clipRule: 'evenodd', + d: 'M5 12.8069C5.55228 12.8069 6 13.2546 6 13.8069L6 19.8069C6 20.3592 5.55228 20.8069 5 20.8069V20.8069C4.44772 20.8069 4 20.3592 4 19.8069L4 13.8069C4 13.2546 4.44772 12.8069 5 12.8069V12.8069Z', }, { - d: 'M9 20C9.32719 20 9.61768 19.8429 9.80012 19.5999C9.92563 19.4328 10 19.2251 10 19C10 18.4477 9.55228 18 9 18V16H19.5C21.1569 16 22.5 17.3431 22.5 19C22.5 20.6569 21.1569 22 19.5 22H10.0001L9 20ZM11.8293 20H19.5C20.0523 20 20.5 19.5523 20.5 19C20.5 18.4477 20.0523 18 19.5 18H11.8293C11.9398 18.3128 12 18.6494 12 19C12 19.3506 11.9398 19.6872 11.8293 20Z', - fillRule: 'evenodd', - clipRule: 'evenodd', + d: 'M22 20.8069C22 21.3592 21.5523 21.8069 21 21.8069L3 21.8069C2.44772 21.8069 2 21.3592 2 20.8069V20.8069C2 20.2546 2.44772 19.8069 3 19.8069L21 19.8069C21.5523 19.8069 22 20.2546 22 20.8069V20.8069Z', }, { - d: 'M4 6H5V4H4C3.44772 4 3 4.44772 3 5C3 5.55228 3.44772 6 4 6ZM7 8L7 2L4 2C2.34315 2 1 3.34315 1 5C1 6.65685 2.34315 8 4 8L7 8Z', - fillRule: 'evenodd', - clipRule: 'evenodd', + d: 'M9 12.8069C9.55229 12.8069 10 13.2546 10 13.8069L10 19.8069C10 20.3592 9.55228 20.8069 9 20.8069V20.8069C8.44772 20.8069 8 20.3592 8 19.8069L8 13.8069C8 13.2546 8.44772 12.8069 9 12.8069V12.8069Z', }, { - d: 'M9 7H16V9H9V7Z', + d: 'M15 12.8069C15.5523 12.8069 16 13.2546 16 13.8069L16 19.8069C16 20.3592 15.5523 20.8069 15 20.8069V20.8069C14.4477 20.8069 14 20.3592 14 19.8069L14 13.8069C14 13.2546 14.4477 12.8069 15 12.8069V12.8069Z', }, { - d: 'M9 11H14V13H9V11Z', + d: 'M19 12.8069C19.5523 12.8069 20 13.2546 20 13.8069L20 19.8069C20 20.3592 19.5523 20.8069 19 20.8069V20.8069C18.4477 20.8069 18 20.3592 18 19.8069L18 13.8069C18 13.2546 18.4477 12.8069 19 12.8069V12.8069Z', + }, + { + d: 'M20 9.80683V8.6L12 5L4 8.6V9.80683H20ZM3.17927 6.77616C2.46157 7.09912 2 7.81298 2 8.6V9.80683C2 10.9114 2.89543 11.8068 4 11.8068H20C21.1046 11.8068 22 10.9114 22 9.80683V8.6C22 7.81298 21.5384 7.09912 20.8207 6.77616L12.8207 3.17616C12.2988 2.94128 11.7012 2.94128 11.1793 3.17616L3.17927 6.77616Z', + fillRule: 'evenodd', + clipRule: 'evenodd', }, ], }, @@ -1207,33 +1206,6 @@ export const icons = { }, ], }, - policy: { - width: 24, - height: 24, - path: [ - { - d: 'M3.99999 3.09968e-07H14.0001C16.7615 3.09968e-07 19.0001 2.23858 19.0001 5V15H17.0001V5C17.0001 3.34315 15.6569 2 14.0001 2H6.00001L6.00005 15C6.00005 16.6569 7.3432 18 9.00005 18H11.4376V20H9.00005C6.23863 20 4.00005 17.7614 4.00005 15L3.99999 3.09968e-07Z', - fillRule: 'evenodd', - clipRule: 'evenodd', - }, - { - d: 'M8 18C8.32719 18 8.61768 17.8429 8.80012 17.5999C8.92563 17.4328 9 17.2251 9 17C9 16.4477 8.55228 16 8 16V14H18.5C20.1569 14 21.5 15.3431 21.5 17C21.5 18.6569 20.1569 20 18.5 20H9.00005L8 18ZM10.8293 18H18.5C19.0523 18 19.5 17.5523 19.5 17C19.5 16.4477 19.0523 16 18.5 16H10.8293C10.9398 16.3128 11 16.6494 11 17C11 17.3506 10.9398 17.6872 10.8293 18Z', - fillRule: 'evenodd', - clipRule: 'evenodd', - }, - { - d: 'M3 4H4V2H3C2.44772 2 2 2.44772 2 3C2 3.55228 2.44772 4 3 4ZM6 6L6 2.62268e-07L3 0C1.34315 -1.44847e-07 1.44847e-07 1.34315 0 3C-1.44847e-07 4.65685 1.34315 6 3 6L6 6Z', - fillRule: 'evenodd', - clipRule: 'evenodd', - }, - { - d: 'M8 5H15V7H8V5Z', - }, - { - d: 'M8 9H13V11H8V9Z', - }, - ], - }, iota: { width: 24, height: 24, diff --git a/packages/shared/routes/dashboard/governance/Governance.svelte b/packages/shared/routes/dashboard/governance/Governance.svelte index aeae13c92c7..2f4769ccf0d 100644 --- a/packages/shared/routes/dashboard/governance/Governance.svelte +++ b/packages/shared/routes/dashboard/governance/Governance.svelte @@ -14,7 +14,7 @@ } -
+
{#if $governanceRoute === GovernanceRoute.Init} {:else if $governanceRoute === GovernanceRoute.EventDetails} diff --git a/packages/shared/routes/dashboard/governance/views/GovernanceDashboard.svelte b/packages/shared/routes/dashboard/governance/views/GovernanceDashboard.svelte index 3d261ca2752..fbf874ecaf7 100644 --- a/packages/shared/routes/dashboard/governance/views/GovernanceDashboard.svelte +++ b/packages/shared/routes/dashboard/governance/views/GovernanceDashboard.svelte @@ -8,7 +8,7 @@
-
+
diff --git a/packages/shared/routes/dashboard/governance/views/GovernanceEventDetails.svelte b/packages/shared/routes/dashboard/governance/views/GovernanceEventDetails.svelte index 6c630956094..a549054a5c5 100644 --- a/packages/shared/routes/dashboard/governance/views/GovernanceEventDetails.svelte +++ b/packages/shared/routes/dashboard/governance/views/GovernanceEventDetails.svelte @@ -80,7 +80,7 @@ -
+
diff --git a/packages/shared/routes/dashboard/governance/views/GovernanceEvents.svelte b/packages/shared/routes/dashboard/governance/views/GovernanceEvents.svelte index b2e37e39f5e..26f22233c8e 100644 --- a/packages/shared/routes/dashboard/governance/views/GovernanceEvents.svelte +++ b/packages/shared/routes/dashboard/governance/views/GovernanceEvents.svelte @@ -2,10 +2,10 @@ import { localize } from '@core/i18n' import { governanceRouter, openSettings, settingsRouter } from '@core/router/' import { GovernanceRoute, SettingsRoute } from '@core/router/enums' - import { Button, Illustration, Link, Text, Spinner } from 'shared/components' + import { Button, Illustration, Link, Spinner, Text } from 'shared/components' import { getOfficialNetworkConfig, updateClientOptions } from 'shared/lib/network' - import { ParticipationEvent } from 'shared/lib/participation/types' import { isFetchingParticipationInfo } from 'shared/lib/participation/stores' + import { ParticipationEvent } from 'shared/lib/participation/types' import { activeProfile, updateProfile } from 'shared/lib/profile' import { NetworkConfig, NetworkType } from 'shared/lib/typings/network' @@ -14,6 +14,8 @@ const networkConfig: NetworkConfig = $activeProfile?.settings.networkConfig || getOfficialNetworkConfig(NetworkType.ChrysalisMainnet) + let illustrationHeight = 0 + $: { updateClientOptions(networkConfig) updateProfile('settings.networkConfig', networkConfig) @@ -32,9 +34,14 @@ {#if event} -
-
- +
+
+ diff --git a/packages/shared/routes/dashboard/staking/Staking.svelte b/packages/shared/routes/dashboard/staking/Staking.svelte index c4f24f0d922..b3d1c1d16c2 100644 --- a/packages/shared/routes/dashboard/staking/Staking.svelte +++ b/packages/shared/routes/dashboard/staking/Staking.svelte @@ -104,7 +104,7 @@
-
+
From 9ae5048502140b369a28b9061351e54c07e3ff41 Mon Sep 17 00:00:00 2001 From: Charlie Varley Date: Fri, 20 May 2022 13:02:23 +0100 Subject: [PATCH 110/171] fix: block voting when balance is zero (#3256) --- .../views/GovernanceEventInfo.svelte | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/shared/routes/dashboard/governance/views/GovernanceEventInfo.svelte b/packages/shared/routes/dashboard/governance/views/GovernanceEventInfo.svelte index b56cde5211a..f79db405dde 100644 --- a/packages/shared/routes/dashboard/governance/views/GovernanceEventInfo.svelte +++ b/packages/shared/routes/dashboard/governance/views/GovernanceEventInfo.svelte @@ -1,20 +1,28 @@
- {nextVote?.text} - {nextVote?.additionalInfo} - {#if loading} - - {:else} - {#if $currentAccountTreasuryVoteValue} -
- - {localize( - `popups.votingConfirmation.additionalInfo${ - $currentAccountTreasuryVoteValue !== nextVote.value ? 'Changing' : 'Stopping' + {title} + {#if activeFlow === VotingAction.Cast} +
+ + {localize('popups.governanceManager.castYourVoteInfo', { + values: { + amount: formatUnitBestMatch($selectedAccountStore?.rawIotaBalance, true, 3), + voteText: nextVote?.text, + voteValue: nextVote?.value, + }, + })} + + +
+ {:else if activeFlow === VotingAction.Stop || activeFlow === VotingAction.Change} +
+ {localize( + `popups.governanceManager.${ + activeFlow === VotingAction.Stop ? 'stopVotingInfo' : 'changeVoteInfo' + }`, + { + values: { + voteText: nextVote?.text, + voteValue: nextVote?.value, + }, + } + )} + +
+ + + {localize( + `popups.governanceManager.${ + activeFlow === VotingAction.Stop ? 'stopVotingDisclaimer' : 'changeVoteDisclaimer' }` - )} +
+
+ +
- {/if} - {#if canMergeVotes} -
- - {localize('popups.votingConfirmation.partiallyVoted', { - values: { account: $selectedAccountStore?.alias }, - })} - - - {localize('popups.votingConfirmation.partiallyVotedAmount', { - values: { amount: formatUnitBestMatch($currentAccountTreasuryVotePartiallyUnvotedAmount) }, - })} +
+ {:else if activeFlow === VotingAction.Merge} +
+ {localize('popups.governanceManager.partialVoteInfo', { + values: { + amount: formatUnitBestMatch($currentAccountTreasuryVotePartiallyUnvotedAmount), + account: $selectedAccountStore?.alias, + }, + })} + +
+ + + {localize('popups.governanceManager.mergeVoteDisclaimer')}
- {/if} -
- {#if !$currentAccountTreasuryVoteValue} - - {:else} - {#if isVotingNextVote} - - {/if} - {#if canMergeVotes} - + - {:else if $currentAccountTreasuryVoteValue !== nextVote.value} - - {/if} - {/if} + {/if} + +
{/if}
diff --git a/packages/shared/components/popups/Success.svelte b/packages/shared/components/popups/Success.svelte index e30bbee5185..0db1c58620f 100644 --- a/packages/shared/components/popups/Success.svelte +++ b/packages/shared/components/popups/Success.svelte @@ -1,20 +1,28 @@ -
-
- +
+
+
+ +
+ {#if title} + {title} + {/if} + {#if body} + {body} + {/if}
- {successText}
diff --git a/packages/shared/lib/participation/participation.ts b/packages/shared/lib/participation/participation.ts index 5510a96de15..09be2b65ec0 100644 --- a/packages/shared/lib/participation/participation.ts +++ b/packages/shared/lib/participation/participation.ts @@ -5,6 +5,7 @@ import { canAccountReachMinimumAirdrop } from './account' import { getParticipationOverview, getParticipationEvents } from './api' import { ASSEMBLY_EVENT_ID, PARTICIPATION_POLL_DURATION, SHIMMER_EVENT_ID } from './constants' import { + isChangingParticipation, isPerformingParticipation, participationAction, participationEvents, @@ -89,6 +90,7 @@ export const resetParticipation = (): void => { isFetchingParticipationInfo.set(false) isPerformingParticipation.set(false) participationAction.set(null) + isChangingParticipation.set(false) participationEvents.set([]) participationOverview.set([]) pendingParticipations.set([]) diff --git a/packages/shared/lib/participation/stores.ts b/packages/shared/lib/participation/stores.ts index 1744196d7d3..ad2f858a860 100644 --- a/packages/shared/lib/participation/stores.ts +++ b/packages/shared/lib/participation/stores.ts @@ -34,6 +34,11 @@ export const pendingParticipations = writable([]) */ export const participationAction = writable(null) +/** + * Store used to keep track when the user has excplicitly requested to change a participation (eg, governance vote). + */ +export const isChangingParticipation = writable(false) + /** * The overview / statistics about participation. See #AccountParticipationOverview for more details. */ @@ -252,9 +257,9 @@ export const resetPerformingParticipation = (): void => { if (!get(isSoftwareProfile)) { transferState.set(null) } - isPerformingParticipation.set(false) participationAction.set(undefined) + isChangingParticipation.set(false) } export const participationHistory = persistent('participationHistory', []) diff --git a/packages/shared/lib/participation/types.ts b/packages/shared/lib/participation/types.ts index cccc4682b15..82b8a05bc6e 100644 --- a/packages/shared/lib/participation/types.ts +++ b/packages/shared/lib/participation/types.ts @@ -45,6 +45,13 @@ export enum ParticipationEventType { Staking = 1, } +export enum VotingAction { + Cast = 'castVotes', + Merge = 'mergeVotes', + Stop = 'stopVotes', + Change = 'changeVotes', +} + /** * The status of a participation event. */ diff --git a/packages/shared/lib/walletApiListeners.ts b/packages/shared/lib/walletApiListeners.ts index 961b38dd604..a46e178c14d 100644 --- a/packages/shared/lib/walletApiListeners.ts +++ b/packages/shared/lib/walletApiListeners.ts @@ -1,9 +1,10 @@ +import { localize } from '@core/i18n' import { formatUnitBestMatch } from 'shared/lib/units' import { aggregateAccountActivity, api, - getAccountMetadataWithCallback, formatAccountWithMetadata, + getAccountMetadataWithCallback, processMigratedTransactions, replaceMessage, saveNewMessage, @@ -12,17 +13,21 @@ import { wallet, } from 'shared/lib/wallet' import { get } from 'svelte/store' -import { localize } from '@core/i18n' import { showAppNotification, showSystemNotification } from './notifications' +import { ASSEMBLY_EVENT_ID } from './participation' import { getParticipationOverview } from './participation/api' -import { getPendingParticipation, hasPendingParticipation, removePendingParticipations } from './participation/stores' +import { + getPendingParticipation, + hasPendingParticipation, + isChangingParticipation, + removePendingParticipations, +} from './participation/stores' // PARTICIPATION import { ParticipationAction, PendingParticipation } from './participation/types' import { closePopup, openPopup, popupState } from './popup' import { isStrongholdLocked, updateProfile } from './profile' import type { Message } from './typings/message' import type { WalletAccount } from './typings/wallet' -import { ASSEMBLY_EVENT_ID } from './participation' /** * Initialises event listeners from wallet library @@ -113,8 +118,15 @@ export const initialiseListeners = (): void => { await getParticipationOverview(ASSEMBLY_EVENT_ID) // If it is a message related to any participation event, display a notification and close any open participation popup - displayParticipationNotification(getPendingParticipation(message.id)) - if (get(popupState).type === 'governanceManager' || get(popupState).type === 'stakingManager') { + // except for unvote for when the user is changing the vote (automatic unvote & vote) + if ( + !get(isChangingParticipation) || + (get(isChangingParticipation) && + getPendingParticipation(message.id)?.action !== ParticipationAction.Unvote) + ) { + displayParticipationNotification(getPendingParticipation(message.id)) + } + if (get(popupState).type === 'stakingManager') { closePopup() } @@ -390,7 +402,7 @@ export function displayParticipationNotification(pendingParticipation: PendingPa localeGroup = 'stakingManager' localeAction = action === ParticipationAction.Stake ? 'staked' : 'unstaked' } else if (action === ParticipationAction.Vote || action === ParticipationAction.Unvote) { - localeGroup = 'votingConfirmation' + localeGroup = 'governanceManager' localeAction = action === ParticipationAction.Vote ? 'voted' : 'unvoted' } showAppNotification({ diff --git a/packages/shared/locales/en.json b/packages/shared/locales/en.json index be2ea044fe1..d181d6fdcb0 100644 --- a/packages/shared/locales/en.json +++ b/packages/shared/locales/en.json @@ -860,13 +860,32 @@ "body": "IOTA staking for Assembly continues... Participate in phase {periodNumber} for 90 days. Stake your IOTA tokens and earn ASMB rewards!", "info": "Shimmer staking is now complete and only ASMB tokens will be distributed." }, - "votingConfirmation": { - "partiallyVoted": "You have received additional funds to {account}. You can vote with these tokens by merging your vote.", - "partiallyVotedAmount": "Unused funds: {amount}", - "additionalInfoStopping": "Please note that stopping voting during the counting period won't impact any votes that have already been counted.", - "additionalInfoChanging": "Please note that changing your vote during the counting period won't impact any votes that have already been counted.", + "governanceManager": { + "castYourVote": "Cast your vote", + "castYourVoteInfo": "You're about to vote for Option {voteValue} ({voteText}) with {amount}", + "castingVotes": "Casting votes", + "stopVoting": "Stop voting", + "stopVotingInfo": "Are you sure you want to stop voting for Option {voteValue} – {voteText}?", + "stopVotingDisclaimer": "Please note that stopping voting during the counting period won't impact any votes that have already been counted", + "stoppingVoting": "Stopping voting", + "changeVote": "Change vote", + "changeVoteDisclaimer": "Please note that changing your vote during the counting period won't impact any votes that have already been counted", + "changeVoteInfo": "Are you sure you want to change your vote to Option {voteValue} ({voteText})?", + "changingVote": "Changing vote", + "manageVotes": "Manage votes", + "partialVoteInfo": "You have received {amount} to {account}. You can vote with these funds by merging them with your current vote.", + "mergeVoteDisclaimer": "Please note that merging votes won't impact any votes that have already been counted", + "mergingVotes": "Merging votes", "votedSuccessfully": "You have started voting with {account}.", - "unvotedSuccessfully": "You have stopped voting with {account}." + "unvotedSuccessfully": "You have stopped voting with {account}.", + "successPopup": { + "castVotesTitle": "Voted successfully", + "stopVotesTitle": "Voting stopped", + "mergeVotesTitle": "Vote merged", + "changeVotesTitle": "Vote changed", + "castBody": "You are now voting for Option {voteValue} ({voteText}).", + "stopBody": "You have stopped voting. This does not impact votes that have already been counted." + } }, "shimmer-info": { "title": "About Shimmer", diff --git a/packages/shared/routes/dashboard/governance/views/GovernanceDashboard.svelte b/packages/shared/routes/dashboard/governance/views/GovernanceDashboard.svelte index fbf874ecaf7..e2d9287ae78 100644 --- a/packages/shared/routes/dashboard/governance/views/GovernanceDashboard.svelte +++ b/packages/shared/routes/dashboard/governance/views/GovernanceDashboard.svelte @@ -8,7 +8,7 @@
-
+
diff --git a/packages/shared/routes/dashboard/governance/views/GovernanceEventDetails.svelte b/packages/shared/routes/dashboard/governance/views/GovernanceEventDetails.svelte index a549054a5c5..32c83845cd2 100644 --- a/packages/shared/routes/dashboard/governance/views/GovernanceEventDetails.svelte +++ b/packages/shared/routes/dashboard/governance/views/GovernanceEventDetails.svelte @@ -80,7 +80,7 @@ -
+
diff --git a/packages/shared/routes/dashboard/governance/views/GovernanceEventInfo.svelte b/packages/shared/routes/dashboard/governance/views/GovernanceEventInfo.svelte index 697f7bd0f9b..0f471c9030d 100644 --- a/packages/shared/routes/dashboard/governance/views/GovernanceEventInfo.svelte +++ b/packages/shared/routes/dashboard/governance/views/GovernanceEventInfo.svelte @@ -119,23 +119,18 @@ /> {/if}
-
+
{event?.information?.name} - {#if event?.information?.additionalInfo} + {#if event?.information?.payload?.questions[0]?.text} {event?.information?.additionalInfo} {/if} - {#if event?.information?.payload?.questions[0]?.text} - + {#if event?.information?.additionalInfo} + {event?.information?.payload?.questions[0]?.text} {/if} - {#if event?.information?.payload?.questions[0]?.additionalInfo} - - {event?.information?.payload?.questions[0]?.additionalInfo} - - {/if}
{#each event?.information?.payload?.questions[0]?.answers ?? [] as answer} @@ -149,7 +144,7 @@ class="relative py-5 px-6 bg-gray-50 dark:bg-gray-900 dark:bg-opacity-50 hover:bg-gray-100 dark:hover:bg-gray-900 dark:hover:bg-opaciity-100 rounded-xl border border-solid border-gray-200 dark:border-transparent" >
-
+
{#if isSelected($currentAccountTreasuryVoteValue, answer?.value) || isWinnerAnswer(answer?.value)} {#if event?.status?.status === ParticipationEventState.Holding} @@ -238,8 +233,10 @@ {/if} {:else} -
- {localize('actions.castVotes')} +
+ {#if !$currentAccountTreasuryVoteValue} + {localize('actions.castVotes')} + {/if}
{/if} diff --git a/packages/shared/routes/dashboard/staking/Staking.svelte b/packages/shared/routes/dashboard/staking/Staking.svelte index b3d1c1d16c2..cfdb80941e3 100644 --- a/packages/shared/routes/dashboard/staking/Staking.svelte +++ b/packages/shared/routes/dashboard/staking/Staking.svelte @@ -104,7 +104,7 @@
-
+
From 27b5a45e872bebff208fb4dd09e213c6cb98cf95 Mon Sep 17 00:00:00 2001 From: Charlie Varley Date: Mon, 23 May 2022 22:16:33 +0100 Subject: [PATCH 113/171] fix: voting text fixes (#3307) * fix: voting weight string * fix: minimum stake when voting string * fix: update proposal not found string * enhancement: add time to voting phase timelines --- packages/shared/components/GovernanceInfoTooltip.svelte | 9 ++++++++- packages/shared/components/popups/Transaction.svelte | 6 +++++- packages/shared/locales/en.json | 5 +++-- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/shared/components/GovernanceInfoTooltip.svelte b/packages/shared/components/GovernanceInfoTooltip.svelte index cc33b95eb1b..aaaa870a24d 100644 --- a/packages/shared/components/GovernanceInfoTooltip.svelte +++ b/packages/shared/components/GovernanceInfoTooltip.svelte @@ -20,7 +20,14 @@ VotingWeight = 'votingWeight', } - const dateFormat = { format: 'long' } + const dateFormat = { + year: 'numeric', + month: 'short', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + timeZoneName: 'short', + } as Intl.DateTimeFormatOptions let eventProgress: number switch (event?.status?.status) { diff --git a/packages/shared/components/popups/Transaction.svelte b/packages/shared/components/popups/Transaction.svelte index a00881d8e1c..943fc9f67db 100644 --- a/packages/shared/components/popups/Transaction.svelte +++ b/packages/shared/components/popups/Transaction.svelte @@ -103,7 +103,11 @@ {localize( mustAcknowledgeBelowMinRewardParticipationWarning - ? 'popups.transaction.sendingFromStakedAccountBelowMinReward' + ? `popups.transaction.${ + activeParticipationType === ActiveParticipationType.Stake + ? 'sendingFromStakedAccountBelowMinReward' + : 'sendingFromStakedAccountBelowMinRewardVote' + }` : `popups.transaction.sendingFromActiveParticipationAccount.${activeParticipationType}` )} diff --git a/packages/shared/locales/en.json b/packages/shared/locales/en.json index 1fb49969da4..e02aedc6200 100644 --- a/packages/shared/locales/en.json +++ b/packages/shared/locales/en.json @@ -567,7 +567,7 @@ "title": "Your voting weight", "equality": "1000 IOTA = 1 VOTE", "description1": "Your voting weight is derived from your wallet balance. When a voting proposal is in the Counting phase, active votes are counted and accumulated every 10s.", - "description2": "1 Ki of voting weight (1000 IOTA tokens) yields 1 vote every 10s. This means you must keep voting for the full duration of the Counting phase to issue your full voting weight." + "description2": "1 Ki of voting weight (1000 IOTA tokens) yields 1 vote every 10s. This means you must continue voting for the full duration of the Counting phase in order to achieve your full voting weight." } }, "info": { @@ -613,7 +613,7 @@ "treasury": { "notFound": { "title": "Unable to load Community Treasury vote", - "subtitle": "Please connect to a node that supports this proposal", + "subtitle": "Please connect to a node that has added this vote", "buttonConnect": "Connect to default node", "buttonSettings": "View node settings", "fetching": "Fetching governance event info..." @@ -752,6 +752,7 @@ "body": "You’re about to send {amount} to", "sendingFromStakedAccount": "You are sending a transfer from a wallet that is currently being staked. This may unstake your tokens. Feel free to send the transfer but you may need to restake your remaining tokens afterwards.", "sendingFromStakedAccountBelowMinReward": "You are sending a transfer from a wallet that has not yet reached the minimum staking rewards. This may unstake your tokens and you may lose your staking rewards on this wallet.", + "sendingFromStakedAccountBelowMinRewardVote": "You are sending a transfer from a wallet that has not yet reached the minimum staking rewards. This may unstake your tokens and you may lose your staking rewards on this wallet. You may also need to vote again.", "sendingFromActiveParticipationAccount": { "stakeVote": "You are sending a transfer from a wallet that is currently staking and voting. This may unstake your tokens and stop your vote. Feel free to send the transfer but you may need to restake and vote again with your remaining tokens afterwards.", "stake": "You are sending a transfer from a wallet that is currently being staked. This may unstake your tokens. Feel free to send the transfer but you may need to restake your remaining tokens afterwards.", From e221afa064ba62aef2a6a729e5bb25c818edfad5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bego=C3=B1a=20=C3=81lvarez=20de=20la=20Cruz?= Date: Tue, 24 May 2022 12:18:07 +0200 Subject: [PATCH 114/171] Feat: add participation loaders (#3297) * feat: add participation loaders * feat: add more reactivity * feat: add syncing reactivity * feat: imrpove css * feat: update get spinner message logic * feat: add missing reset governance view * feat: add voting loaders to staking * feat: set same syncing string in voting as staking * fix: isChangingParticipation being reset before real timing * feat: remove unnecessary line --- .../popups/GovernanceManager.svelte | 2 +- packages/shared/lib/participation/api.ts | 2 +- packages/shared/lib/participation/stores.ts | 10 +- packages/shared/lib/participation/types.ts | 1 + packages/shared/lib/walletApiListeners.ts | 1 + .../views/GovernanceEventInfo.svelte | 109 ++++++++++++++++-- .../staking/views/StakingSummary.svelte | 29 +++-- 7 files changed, 131 insertions(+), 23 deletions(-) diff --git a/packages/shared/components/popups/GovernanceManager.svelte b/packages/shared/components/popups/GovernanceManager.svelte index c90b646812e..93f50b6e61a 100644 --- a/packages/shared/components/popups/GovernanceManager.svelte +++ b/packages/shared/components/popups/GovernanceManager.svelte @@ -159,7 +159,7 @@ if (!isSoftwareProfile) { transferState.set(null) } - + activeFlow = getActiveFlow() isPerformingParticipation.set(false) participationAction.set(undefined) } diff --git a/packages/shared/lib/participation/api.ts b/packages/shared/lib/participation/api.ts index 8001c541bfa..f4cedb4c085 100644 --- a/packages/shared/lib/participation/api.ts +++ b/packages/shared/lib/participation/api.ts @@ -80,7 +80,7 @@ export function participate( onSuccess(response: Event) { response.payload.forEach((message) => saveNewMessage(accountId, message)) - addNewPendingParticipation(response.payload, accountId, action) + addNewPendingParticipation(response.payload, accountId, action, participations) const eventIds = participations.map((participation) => participation.eventId) updateParticipationHistoryFromPayload(response.payload, accountId, action, eventIds) diff --git a/packages/shared/lib/participation/stores.ts b/packages/shared/lib/participation/stores.ts index ad2f858a860..77fc7925563 100644 --- a/packages/shared/lib/participation/stores.ts +++ b/packages/shared/lib/participation/stores.ts @@ -11,6 +11,7 @@ import { transferState, wallet } from '../wallet' import { ASSEMBLY_EVENT_ID, SHIMMER_EVENT_ID, TREASURY_VOTE_EVENT_ID } from './constants' import { ParticipateResponsePayload, + Participation, ParticipationAction, ParticipationEvent, ParticipationEventState, @@ -189,15 +190,17 @@ export const shimmerStakingRemainingTime: Readable = derived( export const addNewPendingParticipation = ( payload: ParticipateResponsePayload, accountId: string, - action: ParticipationAction + action: ParticipationAction, + participations?: Participation[] ): void => { const _pendingParticipation = { accountId, action, + participations, } - pendingParticipations.update((participations) => [ - ...participations, + pendingParticipations.update((_participations) => [ + ..._participations, ...payload.map((tx) => Object.assign({}, _pendingParticipation, { messageId: tx.id })), ]) } @@ -259,7 +262,6 @@ export const resetPerformingParticipation = (): void => { } isPerformingParticipation.set(false) participationAction.set(undefined) - isChangingParticipation.set(false) } export const participationHistory = persistent('participationHistory', []) diff --git a/packages/shared/lib/participation/types.ts b/packages/shared/lib/participation/types.ts index 82b8a05bc6e..fce450f5834 100644 --- a/packages/shared/lib/participation/types.ts +++ b/packages/shared/lib/participation/types.ts @@ -207,6 +207,7 @@ export type PendingParticipation = { messageId: string accountId: string action: ParticipationAction + participations?: Participation[] } /** diff --git a/packages/shared/lib/walletApiListeners.ts b/packages/shared/lib/walletApiListeners.ts index a46e178c14d..9046285770c 100644 --- a/packages/shared/lib/walletApiListeners.ts +++ b/packages/shared/lib/walletApiListeners.ts @@ -124,6 +124,7 @@ export const initialiseListeners = (): void => { (get(isChangingParticipation) && getPendingParticipation(message.id)?.action !== ParticipationAction.Unvote) ) { + isChangingParticipation.set(false) displayParticipationNotification(getPendingParticipation(message.id)) } if (get(popupState).type === 'stakingManager') { diff --git a/packages/shared/routes/dashboard/governance/views/GovernanceEventInfo.svelte b/packages/shared/routes/dashboard/governance/views/GovernanceEventInfo.svelte index 0f471c9030d..1acd9aadfdb 100644 --- a/packages/shared/routes/dashboard/governance/views/GovernanceEventInfo.svelte +++ b/packages/shared/routes/dashboard/governance/views/GovernanceEventInfo.svelte @@ -15,22 +15,43 @@ import { openPopup } from '@lib/popup' import { formatUnitBestMatch } from '@lib/units' import { selectedAccountStore } from '@lib/wallet' - import { DashboardPane, GovernanceInfoTooltip, Icon, Text, Tooltip } from 'shared/components' + import { DashboardPane, GovernanceInfoTooltip, Icon, Spinner, Text, Tooltip } from 'shared/components' import { showAppNotification } from 'shared/lib/notifications' + import { + isChangingParticipation, + participationAction, + pendingParticipations, + } from 'shared/lib/participation/stores' + import { ParticipationAction } from 'shared/lib/participation/types' + import { isSyncing } from 'shared/lib/wallet' export let event: ParticipationEvent export let nextVote: VotingEventAnswer = null - $: cannotVote = getAccountParticipationAbility($selectedAccountStore) === AccountParticipationAbility.HasDustAmount - const tooltip = { statusTimeline: { anchor: null as HTMLElement, show: false }, partiallyVoted: { anchor: null as HTMLElement, show: false }, } + $: eventAnswers = event?.information?.payload?.questions[0]?.answers ?? [] $: results = event?.status?.questions?.[0]?.answers?.filter( (answer) => answer?.value !== 0 && answer?.value !== 255 ) + $: cannotVote = getAccountParticipationAbility($selectedAccountStore) === AccountParticipationAbility.HasDustAmount + $: disableVoting = + $isChangingParticipation || $pendingParticipations?.length > 0 || !!$participationAction || $isSyncing + + let disableVotingMessages: { + show?: boolean + busy?: boolean + message?: string + }[] + $: disableVoting, + eventAnswers, + $isSyncing, + $currentAccountTreasuryVoteValue, + $pendingParticipations, + updateDisableVotingMessages() const isSelected = (castedAnswerValue: string, answerValue: string): boolean => castedAnswerValue === answerValue @@ -90,6 +111,70 @@ break } } + + function updateDisableVotingMessages(): void { + if (!disableVoting) return + else { + disableVotingMessages = [] + const pendingParticipation = $pendingParticipations?.[0] + eventAnswers.forEach((eventAnswer) => { + if ($isSyncing) { + disableVotingMessages.push({ + show: true, + busy: true, + message: localize('general.syncing'), + }) + } else if ( + $participationAction === ParticipationAction.Stake || + $participationAction === ParticipationAction.Unstake + ) { + const locale = + $participationAction === ParticipationAction.Stake ? 'general.staking' : 'general.unstaking' + disableVotingMessages.push({ + show: true, + busy: true, + message: localize(locale), + }) + } else if ( + pendingParticipation?.action === ParticipationAction.Vote || + pendingParticipation?.action === ParticipationAction.Unvote + ) { + const pendingParticipationAnswers = + pendingParticipation?.participations?.map((participations) => participations?.answers) ?? [] + if (pendingParticipation?.action === ParticipationAction.Vote) { + if ( + pendingParticipationAnswers.some((participation) => + participation.includes(eventAnswer?.value) + ) + ) { + disableVotingMessages.push({ + show: true, + busy: true, + message: localize('general.voting'), + }) + } else { + disableVotingMessages.push({ + show: false, + }) + } + } else { + if (isSelected($currentAccountTreasuryVoteValue, eventAnswer?.value)) { + disableVotingMessages.push({ + show: true, + busy: true, + message: localize('general.unvoting'), + }) + } else { + disableVotingMessages.push({ + show: false, + }) + } + } + } + }) + disableVotingMessages = disableVotingMessages + } + } @@ -133,14 +218,14 @@ {/if}
- {#each event?.information?.payload?.questions[0]?.answers ?? [] as answer} + {#each event?.information?.payload?.questions[0]?.answers ?? [] as answer, answerIndex}