diff --git a/.changelog/1699.feature.md b/.changelog/1699.feature.md new file mode 100644 index 0000000000..bd1ffc51d9 --- /dev/null +++ b/.changelog/1699.feature.md @@ -0,0 +1 @@ +Named accounts feature diff --git a/playwright/tests/toolbar.spec.ts b/playwright/tests/toolbar.spec.ts index d8e574a571..8826289c40 100644 --- a/playwright/tests/toolbar.spec.ts +++ b/playwright/tests/toolbar.spec.ts @@ -66,6 +66,19 @@ test.describe('Profile tab', () => { }) test.describe('My Accounts tab', () => { + test('should set custom name', async ({ page }) => { + await page.goto('/open-wallet/private-key') + await fillPrivateKeyAndPassword(page) + await page.getByTestId('account-selector').click() + await page.getByText('Manage').click() + await page.getByPlaceholder('Name (Optional)').fill('My Custom Name') + await page.keyboard.press('Enter') + await page.getByTestId('close-settings-modal').first().click() + await expect(page.getByTestId('close-settings-modal')).not.toBeVisible() + await expect(page.getByText('My Custom Name')).toBeVisible() + await expect(page.getByText('oasis1 qz0k 5q8v jqvu 4s4n wxyj 406y lnfl kc4v rcjg huwk')).not.toBeVisible() + }) + test('should get a private key', async ({ page }) => { await page.goto('/open-wallet/private-key') await fillPrivateKeyAndPassword(page) @@ -102,10 +115,10 @@ test.describe('My Accounts tab', () => { await openAccountSelectorWithMultipleItems(page) await page.getByText('Manage').nth(0).click() await page.getByText('Delete Account').click() - await page.getByRole('textbox').fill('foo') + await page.getByTestId('account-delete-confirmation-input').fill('foo') await page.getByRole('button', { name: 'Yes, delete' }).click() expect(page.getByText("Type 'delete'")).toBeVisible() - await page.getByRole('textbox').fill('delete') + await page.getByTestId('account-delete-confirmation-input').fill('delete') await page.getByRole('button', { name: 'Yes, delete' }).click() await expect(page).not.toHaveURL(new RegExp(`/account/${mnemonicAddress0}`)) await expect(page.getByTestId('account-choice')).toHaveCount(3) @@ -115,7 +128,7 @@ test.describe('My Accounts tab', () => { await openAccountSelectorWithMultipleItems(page) await page.getByText('Manage').nth(1).click() await page.getByText('Delete Account').click() - await page.getByRole('textbox').fill('delete') + await page.getByTestId('account-delete-confirmation-input').fill('delete') await page.getByRole('button', { name: 'Yes, delete' }).click() await expect(page).toHaveURL(new RegExp(`/account/${mnemonicAddress0}`)) await expect(page.getByTestId('account-choice')).toHaveCount(3) diff --git a/src/app/components/AddressBox/__tests__/__snapshots__/index.test.tsx.snap b/src/app/components/AddressBox/__tests__/__snapshots__/index.test.tsx.snap index b0c559a878..dd188f7d3c 100644 --- a/src/app/components/AddressBox/__tests__/__snapshots__/index.test.tsx.snap +++ b/src/app/components/AddressBox/__tests__/__snapshots__/index.test.tsx.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[` should render address properly 1`] = ` -.c2 { +.c3 { display: inline-block; -webkit-flex: 0 0 auto; -ms-flex: 0 0 auto; @@ -12,23 +12,23 @@ exports[` should render address properly 1`] = ` stroke: #666666; } -.c2 g { +.c3 g { fill: inherit; stroke: inherit; } -.c2 *:not([stroke])[fill='none'] { +.c3 *:not([stroke])[fill='none'] { stroke-width: 0; } -.c2 *[stroke*='#'],.c2 *[STROKE*='#'] { +.c3 *[stroke*='#'],.c3 *[STROKE*='#'] { stroke: inherit; fill: none; } -.c2 *[fill-rule], -.c2 *[FILL-RULE], -.c2 *[fill*='#'],.c2 *[FILL*='#'] { +.c3 *[fill-rule], +.c3 *[FILL-RULE], +.c3 *[fill*='#'],.c3 *[FILL*='#'] { fill: inherit; stroke: none; } @@ -49,26 +49,64 @@ exports[` should render address properly 1`] = ` -webkit-flex-direction: row; -ms-flex-direction: row; flex-direction: row; - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; padding-right: 12px; border-radius: 5px; } -.c3 { +.c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + box-sizing: border-box; + max-width: 100%; + margin-right: 48px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + min-width: 0; + min-height: 0; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + width: 690px; + -webkit-flex: 1 1; + -ms-flex: 1 1; + flex: 1 1; + padding-bottom: 6px; +} + +.c4 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + box-sizing: border-box; + max-width: 100%; + min-width: 0; + min-height: 0; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-flex: 1 1; + -ms-flex: 1 1; + flex: 1 1; +} + +.c5 { font-size: 18px; line-height: 24px; font-weight: bold; word-break: break-word; } -.c4 { +.c6 { font-size: inherit; line-height: normal; } -.c1 { +.c2 { display: inline-block; box-sizing: border-box; cursor: pointer; @@ -88,40 +126,40 @@ exports[` should render address properly 1`] = ` padding: 12px; } -.c1:focus { +.c2:focus { outline: none; box-shadow: 0 0 2px 2px #6FFFB0; } -.c1:focus > circle, -.c1:focus > ellipse, -.c1:focus > line, -.c1:focus > path, -.c1:focus > polygon, -.c1:focus > polyline, -.c1:focus > rect { +.c2:focus > circle, +.c2:focus > ellipse, +.c2:focus > line, +.c2:focus > path, +.c2:focus > polygon, +.c2:focus > polyline, +.c2:focus > rect { outline: none; box-shadow: 0 0 2px 2px #6FFFB0; } -.c1:focus::-moz-focus-inner { +.c2:focus::-moz-focus-inner { border: 0; } -.c1:focus:not(:focus-visible) { +.c2:focus:not(:focus-visible) { outline: none; box-shadow: none; } -.c1:focus:not(:focus-visible) > circle,.c1:focus:not(:focus-visible) > ellipse, -.c1:focus:not(:focus-visible) > line,.c1:focus:not(:focus-visible) > path, -.c1:focus:not(:focus-visible) > polygon,.c1:focus:not(:focus-visible) > polyline, -.c1:focus:not(:focus-visible) > rect { +.c2:focus:not(:focus-visible) > circle,.c2:focus:not(:focus-visible) > ellipse, +.c2:focus:not(:focus-visible) > line,.c2:focus:not(:focus-visible) > path, +.c2:focus:not(:focus-visible) > polygon,.c2:focus:not(:focus-visible) > polyline, +.c2:focus:not(:focus-visible) > rect { outline: none; box-shadow: none; } -.c1:focus:not(:focus-visible)::-moz-focus-inner { +.c2:focus:not(:focus-visible)::-moz-focus-inner { border: 0; } @@ -131,43 +169,474 @@ exports[` should render address properly 1`] = ` } } +@media only screen and (max-width:768px) { + .c1 { + margin-right: 24px; + } +} + +@media only screen and (max-width:768px) { + .c1 { + padding-bottom: 3px; + } +} +
- - - + + + +
- oasis1 qqur xkga vtcj jytn eume clx5 9ds3 avja qg7f tqph + + + oasis1 qqur xkga vtcj jytn eume clx5 9ds3 avja qg7f tqph + + - - +
+
+
+ +`; + +exports[` should render name properly 1`] = ` +.c6 { + display: inline-block; + -webkit-flex: 0 0 auto; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 16px; + height: 16px; + fill: link; + stroke: link; +} + +.c6 g { + fill: inherit; + stroke: inherit; +} + +.c6 *:not([stroke])[fill='none'] { + stroke-width: 0; +} + +.c6 *[stroke*='#'],.c6 *[STROKE*='#'] { + stroke: inherit; + fill: none; +} + +.c6 *[fill-rule], +.c6 *[FILL-RULE], +.c6 *[fill*='#'],.c6 *[FILL*='#'] { + fill: inherit; + stroke: none; +} + +.c11 { + display: inline-block; + -webkit-flex: 0 0 auto; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 18px; + height: 18px; + fill: currentColor; + stroke: currentColor; +} + +.c11 g { + fill: inherit; + stroke: inherit; +} + +.c11 *:not([stroke])[fill='none'] { + stroke-width: 0; +} + +.c11 *[stroke*='#'],.c11 *[STROKE*='#'] { + stroke: inherit; + fill: none; +} + +.c11 *[fill-rule], +.c11 *[FILL-RULE], +.c11 *[fill*='#'],.c11 *[FILL*='#'] { + fill: inherit; + stroke: none; +} + +.c0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + box-sizing: border-box; + max-width: 100%; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + min-width: 0; + min-height: 0; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + padding-right: 12px; + border-radius: 5px; +} + +.c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + box-sizing: border-box; + max-width: 100%; + margin-right: 48px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border-bottom: solid 1px background-front-border; + min-width: 0; + min-height: 0; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + width: 690px; + -webkit-flex: 1 1; + -ms-flex: 1 1; + flex: 1 1; + padding-bottom: 6px; +} + +.c2 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + box-sizing: border-box; + max-width: 100%; + min-width: 0; + min-height: 0; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-flex: 1 1; + -ms-flex: 1 1; + flex: 1 1; +} + +.c3 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + box-sizing: border-box; + max-width: 100%; + min-width: 0; + min-height: 0; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + padding-left: 12px; +} + +.c9 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + box-sizing: border-box; + max-width: 100%; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + min-width: 0; + min-height: 0; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; +} + +.c10 { + -webkit-flex: 0 0 auto; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + -webkit-align-self: stretch; + -ms-flex-item-align: stretch; + align-self: stretch; + width: 12px; +} + +.c4 { + font-size: 18px; + line-height: 24px; + font-weight: bold; + word-break: break-word; +} + +.c5 { + display: inline-block; + box-sizing: border-box; + cursor: pointer; + font: inherit; + -webkit-text-decoration: none; + text-decoration: none; + margin: 0; + background: transparent; + overflow: visible; + text-transform: none; + color: inherit; + outline: none; + border: none; + padding: 0; + text-align: inherit; + line-height: 0; + padding: 12px; +} + +.c5:focus { + outline: none; + box-shadow: 0 0 2px 2px #6FFFB0; +} + +.c5:focus > circle, +.c5:focus > ellipse, +.c5:focus > line, +.c5:focus > path, +.c5:focus > polygon, +.c5:focus > polyline, +.c5:focus > rect { + outline: none; + box-shadow: 0 0 2px 2px #6FFFB0; +} + +.c5:focus::-moz-focus-inner { + border: 0; +} + +.c5:focus:not(:focus-visible) { + outline: none; + box-shadow: none; +} + +.c5:focus:not(:focus-visible) > circle,.c5:focus:not(:focus-visible) > ellipse, +.c5:focus:not(:focus-visible) > line,.c5:focus:not(:focus-visible) > path, +.c5:focus:not(:focus-visible) > polygon,.c5:focus:not(:focus-visible) > polyline, +.c5:focus:not(:focus-visible) > rect { + outline: none; + box-shadow: none; +} + +.c5:focus:not(:focus-visible)::-moz-focus-inner { + border: 0; +} + +.c7 { + display: inline-block; + box-sizing: border-box; + cursor: pointer; + font: inherit; + -webkit-text-decoration: none; + text-decoration: none; + margin: 0; + background: transparent; + overflow: visible; + text-transform: none; + border: 2px solid #7D4CDB; + border-radius: 18px; + color: #444444; + padding: 4px 22px; + font-size: 18px; + line-height: 24px; + -webkit-transition-property: color,background-color,border-color,box-shadow; + transition-property: color,background-color,border-color,box-shadow; + -webkit-transition-duration: 0.1s; + transition-duration: 0.1s; + -webkit-transition-timing-function: ease-in-out; + transition-timing-function: ease-in-out; +} + +.c7:hover { + box-shadow: 0px 0px 0px 2px #7D4CDB; +} + +.c7:focus { + outline: none; + box-shadow: 0 0 2px 2px #6FFFB0; +} + +.c7:focus > circle, +.c7:focus > ellipse, +.c7:focus > line, +.c7:focus > path, +.c7:focus > polygon, +.c7:focus > polyline, +.c7:focus > rect { + outline: none; + box-shadow: 0 0 2px 2px #6FFFB0; +} + +.c7:focus::-moz-focus-inner { + border: 0; +} + +.c7:focus:not(:focus-visible) { + outline: none; + box-shadow: none; +} + +.c7:focus:not(:focus-visible) > circle,.c7:focus:not(:focus-visible) > ellipse, +.c7:focus:not(:focus-visible) > line,.c7:focus:not(:focus-visible) > path, +.c7:focus:not(:focus-visible) > polygon,.c7:focus:not(:focus-visible) > polyline, +.c7:focus:not(:focus-visible) > rect { + outline: none; + box-shadow: none; +} + +.c7:focus:not(:focus-visible)::-moz-focus-inner { + border: 0; +} + +.c8 { + background-color: background-custom-2; + border-width: 1px; + color: text-custom; +} + +@media only screen and (max-width:768px) { + .c0 { + padding-right: 6px; + } +} + +@media only screen and (max-width:768px) { + .c1 { + margin-right: 24px; + } +} + +@media only screen and (max-width:768px) { + .c1 { + border-bottom: solid 1px background-front-border; + } +} + +@media only screen and (max-width:768px) { + .c1 { + padding-bottom: 3px; + } +} + +@media only screen and (max-width:768px) { + .c3 { + padding-left: 6px; + } +} + +
+
+
+
+
+ + My Wallet + + +
+
+
+
`; diff --git a/src/app/components/AddressBox/__tests__/index.test.tsx b/src/app/components/AddressBox/__tests__/index.test.tsx index 79aa6351f4..e10cc20243 100644 --- a/src/app/components/AddressBox/__tests__/index.test.tsx +++ b/src/app/components/AddressBox/__tests__/index.test.tsx @@ -1,10 +1,9 @@ -import * as React from 'react' import copy from 'copy-to-clipboard' import { screen } from '@testing-library/dom' import { render } from '@testing-library/react' import userEvent from '@testing-library/user-event' -import { AddressBox } from '../index' +import { AddressBox, EditableAddressBox, EditableNameBox } from '../index' jest.mock('copy-to-clipboard') @@ -20,14 +19,58 @@ describe('', () => { it('should be able to copy address to clipboard', async () => { renderComponent() - await userEvent.click(screen.getByTestId('copy-address')) + await userEvent.click(screen.getByTestId('copy-address-icon')) expect(copy).toHaveBeenCalledWith(testAddress) }) it('should be able to show a notification', async () => { renderComponent() jest.mocked(copy).mockReturnValue(true) // Copy must return true so that the notification is actually displayed - await userEvent.click(screen.getByTestId('copy-address')) + await userEvent.click(screen.getByTestId('copy-address-icon')) expect(await screen.getByText('account.addressCopied')).toBeInTheDocument() }) }) + +const openEditModal = jest.fn() +const renderEditableNameBoxComponent = () => + render() + +describe('', () => { + it('should render name properly', () => { + const { container } = renderEditableNameBoxComponent() + expect(container).toMatchSnapshot() + }) + + it('should render edit icon', async () => { + renderEditableNameBoxComponent() + expect(screen.queryByTestId('editable-address-edit-button')).not.toBeInTheDocument() + await userEvent.click(screen.getByTestId('editable-name-edit-button')) + expect(openEditModal).toHaveBeenCalled() + }) + + it('should be able to copy address to clipboard', async () => { + renderEditableNameBoxComponent() + expect(screen.queryByTestId('copy-address-icon')).not.toBeInTheDocument() + await userEvent.click(screen.getByTestId('copy-address-button')) + expect(copy).toHaveBeenCalledWith(testAddress) + }) +}) + +const renderEditableAddressBoxComponent = () => + render() + +describe('', () => { + it('should render edit icon', async () => { + renderEditableAddressBoxComponent() + expect(screen.queryByTestId('editable-name-edit-button')).not.toBeInTheDocument() + await userEvent.click(screen.getByTestId('editable-address-edit-button')) + expect(openEditModal).toHaveBeenCalled() + }) + + it('should be able to copy address to clipboard', async () => { + renderEditableAddressBoxComponent() + expect(screen.queryByTestId('copy-address-button')).not.toBeInTheDocument() + await userEvent.click(screen.getByTestId('copy-address-icon')) + expect(copy).toHaveBeenCalledWith(testAddress) + }) +}) diff --git a/src/app/components/AddressBox/index.tsx b/src/app/components/AddressBox/index.tsx index 93cfa2c040..2527372670 100644 --- a/src/app/components/AddressBox/index.tsx +++ b/src/app/components/AddressBox/index.tsx @@ -3,30 +3,44 @@ * AddressBox * */ +import { useContext } from 'react' import copy from 'copy-to-clipboard' +import styled from 'styled-components' +import { normalizeColor } from 'grommet/es6/utils' import { Box } from 'grommet/es6/components/Box' import { Button } from 'grommet/es6/components/Button' import { Text } from 'grommet/es6/components/Text' import { Notification } from 'grommet/es6/components/Notification' +import { ResponsiveContext } from 'grommet/es6/contexts/ResponsiveContext' import { Copy } from 'grommet-icons/es6/icons/Copy' -import React, { memo, useState } from 'react' +import { Edit } from 'grommet-icons/es6/icons/Edit' +import { memo, useState, ReactNode } from 'react' import { useTranslation } from 'react-i18next' - +import { trimLongString } from '../ShortAddress/trimLongString' import { PrettyAddress } from '../PrettyAddress' -interface Props { +const StyledButton = styled(Button)` + background-color: ${({ theme }) => normalizeColor('background-custom-2', theme)}; + border-width: 1px; + color: ${({ theme }) => normalizeColor('text-custom', theme)}; +` + +interface AddressBoxProps { address: string border?: boolean + children?: ReactNode + separator?: boolean +} + +interface ContainerProps extends AddressBoxProps { + copyToClipboard: 'icon' | 'button' } -export const AddressBox = memo((props: Props) => { +const Container = ({ address, border, children, copyToClipboard, separator }: ContainerProps) => { const { t } = useTranslation() const [notificationVisible, setNotificationVisible] = useState(false) - + const isMobile = useContext(ResponsiveContext) === 'small' const hideNotification = () => setNotificationVisible(false) - - const address = props.address - const copyAddress = () => { const wasCopied = copy(address) if (wasCopied) { @@ -36,17 +50,44 @@ export const AddressBox = memo((props: Props) => { return ( - - - + + + +
- oasis1 qz0k 5q8v jqvu 4s4n wxyj 406y lnfl kc4v rcjg huwk + + + oasis1 qz0k 5q8v jqvu 4s4n wxyj 406y lnfl kc4v rcjg huwk + + - - +
+
Total @@ -1047,7 +1125,7 @@ exports[` should match snapshot 1`] = ` 100.000001111 should match snapshot 1`] = ` 100.0 should match snapshot 1`] = ` 0.000001111 should match snapshot 1`] = ` 0.0 should match snapshot 1`] = `
should match snapshot 1`] = `
should match snapshot 1`] = `

No transactions found.

diff --git a/src/app/pages/AccountPage/__tests__/index.test.tsx b/src/app/pages/AccountPage/__tests__/index.test.tsx index 46bd88cf19..4c7e32d6b1 100644 --- a/src/app/pages/AccountPage/__tests__/index.test.tsx +++ b/src/app/pages/AccountPage/__tests__/index.test.tsx @@ -1,5 +1,4 @@ import { render, screen } from '@testing-library/react' -import * as React from 'react' import { Provider, useDispatch } from 'react-redux' import { MemoryRouter, Route, Routes } from 'react-router-dom' import { ThemeProvider } from 'styles/theme/ThemeProvider' @@ -9,6 +8,7 @@ import { AccountPage } from '..' import { AccountDetails } from '../Features/AccountDetails' import { DeepPartialRootState } from 'types/RootState' import { stakingActions } from 'app/state/staking' +import { PersistState } from 'app/state/persist/types' import { WalletErrors } from 'types/errors' jest.unmock('react-i18next') @@ -106,4 +106,51 @@ describe('', () => { const balance = await screen.findByTestId('account-balance-total') expect(balance).toHaveTextContent('1,563,114,365,108.133940743') }) + + it('should render edit address variant', async () => { + store = configureAppStore({ + ...store.getState(), + account: { + ...store.getState().account, + available: 1563114365108133939632n.toString(), + }, + persist: { + hasPersistedProfiles: true, + stringifiedEncryptionKey: 'unlockedProfile', + } as PersistState, + }) + renderPage(store, ['/account/oasis1qz0k5q8vjqvu4s4nwxyj406ylnflkc4vrcjghuwk']) + expect(screen.getByText('oasis1 qz0k 5q8v jqvu 4s4n wxyj 406y lnfl kc4v rcjg huwk')).toBeInTheDocument() + expect(screen.getByTestId('editable-address-edit-button')).toBeInTheDocument() + }) + + it('should render edit name variant', async () => { + store = configureAppStore({ + ...store.getState(), + account: { + ...store.getState().account, + available: 1563114365108133939632n.toString(), + }, + persist: { + hasPersistedProfiles: true, + stringifiedEncryptionKey: 'unlockedProfile', + } as PersistState, + wallet: { + selectedWallet: 'oasis1qz0k5q8vjqvu4s4nwxyj406ylnflkc4vrcjghuwk', + wallets: { + oasis1qz0k5q8vjqvu4s4nwxyj406ylnflkc4vrcjghuwk: { + ...store.getState().wallet.wallets.oasis1qz0k5q8vjqvu4s4nwxyj406ylnflkc4vrcjghuwk, + address: 'oasis1qz0k5q8vjqvu4s4nwxyj406ylnflkc4vrcjghuwk', + name: 'My Wallet', + }, + }, + }, + }) + renderPage(store, ['/account/oasis1qz0k5q8vjqvu4s4nwxyj406ylnflkc4vrcjghuwk']) + expect( + screen.queryByText('oasis1 qz0k 5q8v jqvu 4s4n wxyj 406y lnfl kc4v rcjg huwk'), + ).not.toBeInTheDocument() + expect(screen.getByText('My Wallet')).toBeInTheDocument() + expect(screen.getByTestId('editable-name-edit-button')).toBeInTheDocument() + }) }) diff --git a/src/app/pages/AccountPage/index.tsx b/src/app/pages/AccountPage/index.tsx index a75e391bcb..cdec66ecf7 100644 --- a/src/app/pages/AccountPage/index.tsx +++ b/src/app/pages/AccountPage/index.tsx @@ -26,7 +26,8 @@ import { normalizeColor } from 'grommet/es6/utils' import { accountActions } from 'app/state/account' import { selectAccount } from 'app/state/account/selectors' import { BalanceDetails } from 'app/state/account/types' -import { selectAddress, selectHasAccounts } from 'app/state/wallet/selectors' +import { selectActiveWallet, selectHasAccounts, selectHasOneAccount } from 'app/state/wallet/selectors' +import { walletActions } from 'app/state/wallet' import { AccountSummary } from './Features/AccountSummary' import { AccountPageParams } from './validateAccountPageRoute' import { Button } from 'grommet/es6/components/Button' @@ -75,10 +76,10 @@ export function AccountPage(props: AccountPageProps) { const stake = useSelector(selectStaking) const walletHasAccounts = useSelector(selectHasAccounts) - const walletAddress = useSelector(selectAddress) + const wallet = useSelector(selectActiveWallet) const selectedNetwork = useSelector(selectSelectedNetwork) const { active } = useSelector(selectTransaction) - + const hasOneAccount = useSelector(selectHasOneAccount) const balanceDelegations = stake.delegations?.reduce((acc, v) => acc + BigInt(v.amount), 0n) const balanceDebondingDelegations = stake.debondingDelegations?.reduce( (acc, v) => acc + BigInt(v.amount), @@ -133,7 +134,15 @@ export function AccountPage(props: AccountPageProps) { { + dispatch(walletActions.deleteWallet(address)) + wallet!.address === address && dispatch(walletActions.selectFirstWallet()) + } + } + wallet={wallet} walletHasAccounts={walletHasAccounts} />