From bccc22fc9780e206d7c4976b3090811de476fd6c Mon Sep 17 00:00:00 2001 From: Peiman <25097709+Rickk137@users.noreply.github.com> Date: Wed, 12 Oct 2022 13:30:30 +0330 Subject: [PATCH] Sov 464 d 2 wc connect wallet button (#27) * feat: add DisconnectSubmenu component * feat: use menu for dissconnect submenu * dissconnet menu * feat: wallet identity * feat: improve wallet Identity * resolve PR issues * resolve PR issues * Delete App.test.tsx * Update package.json * fix: DisconnectSubmenu * feat: ConnectWalletButton component * feat: wallet connection setup * feat: wallet connect button finished * fix: resolve PR issues * update @sovryn/onboard-core * fix: onboard version * fix: disable wallet connect button in pending state * chore: move WalletIdentity to ui library * chore: add WalletIdentity storybook examples * resolve: PR issues * fix: canvas test issue * chore: set startLength default prop value * test: WalletIdentity * fix: wallet identity padding * chore: remove hardcoded labels from DisconnectSubmenu (and update tests/stories) * chore: add WalletIdentity label override example in dapp code * fix: update button text color * feat: add DisconnectSubmenu component * feat: use menu for dissconnect submenu * dissconnet menu * feat: wallet identity * feat: improve wallet Identity * resolve PR issues * resolve PR issues * fix: DisconnectSubmenu * feat: ConnectWalletButton component * feat: wallet connection setup * feat: wallet connect button finished * fix: resolve PR issues * update @sovryn/onboard-core * chore: move WalletIdentity to ui library * fix: canvas test issue * test: WalletIdentity * fix: wallet identity padding * style: update dropdown colors * chore: fix package.json Co-authored-by: Victor Creed <69458664+creed-victor@users.noreply.github.com> Co-authored-by: Victor Creed Co-authored-by: soulBit --- apps/frontend/craco.config.js | 1 + apps/frontend/package.json | 10 +- apps/frontend/src/app/2_molecules/.gitkeep | 0 .../ConnectWalletButton.tsx | 49 +++ apps/frontend/src/app/2_molecules/index.tsx | 1 + .../app/3_organisms/EthersProviderTest.tsx | 48 --- .../frontend/src/app/5_pages/App/App.test.tsx | 11 - apps/frontend/src/app/5_pages/App/App.tsx | 17 +- apps/frontend/src/hooks/useWalletConnect.ts | 44 +++ apps/frontend/src/index.tsx | 9 +- apps/frontend/src/lib/connector.ts | 30 ++ apps/frontend/src/utils/helpers.ts | 9 + apps/frontend/src/utils/network.ts | 21 -- apps/frontend/tailwind.config.js | 6 +- packages/ui/jest.config.js | 2 +- packages/ui/package.json | 2 + .../ui/src/1_atoms/Button/Button.module.css | 2 +- .../ui/src/1_atoms/Button/Button.test.tsx | 12 +- packages/ui/src/1_atoms/Button/Button.tsx | 144 +++++---- packages/ui/src/1_atoms/Icon/Icon.tsx | 11 +- .../Icon/{icon.test.jsx => icon.test.tsx} | 0 packages/ui/src/1_atoms/Icon/iconNames.ts | 2 + packages/ui/src/1_atoms/Icon/iconSvgPaths.ts | 6 + .../2_molecules/Dropdown/Dropdown.module.css | 10 +- .../ui/src/2_molecules/Dropdown/Dropdown.tsx | 197 ++++++------ .../components/MenuItem/MenuItem.module.css | 13 +- .../Menu/components/MenuItem/MenuItem.tsx | 12 +- .../WalletIdentity/WalletIdentity.module.css | 11 + .../WalletIdentity/WalletIdentity.stories.tsx | 56 ++++ .../WalletIdentity/WalletIdentity.test.tsx | 96 ++++++ .../WalletIdentity/WalletIdentity.tsx | 68 ++++ .../AddressBadge/AddressBadge.module.css | 6 + .../components/AddressBadge/AddressBadge.tsx | 49 +++ .../DisconnectSubmenu/DisconnectSubmenu.tsx | 52 +++ packages/ui/src/2_molecules/index.ts | 2 + packages/ui/src/utils/index.ts | 10 + yarn.lock | 303 +++++++++++++++++- 37 files changed, 1038 insertions(+), 284 deletions(-) delete mode 100644 apps/frontend/src/app/2_molecules/.gitkeep create mode 100644 apps/frontend/src/app/2_molecules/ConnectWalletButton/ConnectWalletButton.tsx create mode 100644 apps/frontend/src/app/2_molecules/index.tsx delete mode 100644 apps/frontend/src/app/3_organisms/EthersProviderTest.tsx delete mode 100644 apps/frontend/src/app/5_pages/App/App.test.tsx create mode 100644 apps/frontend/src/hooks/useWalletConnect.ts create mode 100644 apps/frontend/src/lib/connector.ts create mode 100644 apps/frontend/src/utils/helpers.ts delete mode 100644 apps/frontend/src/utils/network.ts rename packages/ui/src/1_atoms/Icon/{icon.test.jsx => icon.test.tsx} (100%) create mode 100644 packages/ui/src/2_molecules/WalletIdentity/WalletIdentity.module.css create mode 100644 packages/ui/src/2_molecules/WalletIdentity/WalletIdentity.stories.tsx create mode 100644 packages/ui/src/2_molecules/WalletIdentity/WalletIdentity.test.tsx create mode 100644 packages/ui/src/2_molecules/WalletIdentity/WalletIdentity.tsx create mode 100644 packages/ui/src/2_molecules/WalletIdentity/components/AddressBadge/AddressBadge.module.css create mode 100644 packages/ui/src/2_molecules/WalletIdentity/components/AddressBadge/AddressBadge.tsx create mode 100644 packages/ui/src/2_molecules/WalletIdentity/components/DisconnectSubmenu/DisconnectSubmenu.tsx diff --git a/apps/frontend/craco.config.js b/apps/frontend/craco.config.js index 98b8bbb58..a70eb6b25 100644 --- a/apps/frontend/craco.config.js +++ b/apps/frontend/craco.config.js @@ -19,6 +19,7 @@ module.exports = { configFile: 'tsconfig.json', }, }); + config.resolve.fallback = { stream: require.resolve('readable-stream') }; return config; }, }, diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 4a9052c4f..d81cfbb87 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -4,8 +4,13 @@ "private": true, "dependencies": { "@sovryn/ethers-provider": "*", + "@sovryn/onboard-common": "0.0.1", + "@sovryn/onboard-core": "0.0.2", + "@sovryn/onboard-injected": "0.0.1", + "@sovryn/onboard-react": "0.0.2", "@sovryn/tailwindcss-config": "*", "@sovryn/ui": "*", + "classnames": "2.3.2", "ethers": "5.7.1", "react": "18.2.0", "react-dom": "18.2.0", @@ -24,14 +29,15 @@ "@types/node": "^16.11.39", "@types/react": "^18.0.12", "@types/react-dom": "^18.0.5", + "stream-browserify": "3.0.0", "ts-loader": "^9.3.1", "typescript": "^4.7.4" }, "scripts": { "dev": "craco start", "build": "craco build", - "test": "craco test --watchAll=false", - "test:staged": "craco test --watchAll=false --bail --onlyChanged", + "test": "craco test --watchAll=false --passWithNoTests", + "test:staged": "craco test --watchAll=false --passWithNoTests --bail --onlyChanged", "lint": "eslint -c .eslintrc.js ./" }, "browserslist": { diff --git a/apps/frontend/src/app/2_molecules/.gitkeep b/apps/frontend/src/app/2_molecules/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/apps/frontend/src/app/2_molecules/ConnectWalletButton/ConnectWalletButton.tsx b/apps/frontend/src/app/2_molecules/ConnectWalletButton/ConnectWalletButton.tsx new file mode 100644 index 000000000..cf0ad911a --- /dev/null +++ b/apps/frontend/src/app/2_molecules/ConnectWalletButton/ConnectWalletButton.tsx @@ -0,0 +1,49 @@ +import React, { FC, PropsWithChildren } from 'react'; + +import { Button } from '@sovryn/ui'; +import { WalletIdentity } from '@sovryn/ui'; + +export type ConnectWalletButtonProps = { + onConnect: () => void; + onDisconnect: () => void; + address: string | undefined; + pending?: boolean; + className?: string; + dataActionId?: string; +}; + +export const ConnectWalletButton: FC< + PropsWithChildren +> = ({ + address, + pending, + onDisconnect, + onConnect, + className, + dataActionId, +}) => { + if (!address) { + return ( + ); } - } else { - return ( - - ); - } -}); + }, +); diff --git a/packages/ui/src/1_atoms/Icon/Icon.tsx b/packages/ui/src/1_atoms/Icon/Icon.tsx index ece15987d..7c13677ec 100644 --- a/packages/ui/src/1_atoms/Icon/Icon.tsx +++ b/packages/ui/src/1_atoms/Icon/Icon.tsx @@ -9,7 +9,7 @@ import styles from './Icon.module.css'; import { IconType, ViewBoxSize, STANDARD, INLINE, SM } from './Icon.types'; import { IconSvgPaths } from './iconSvgPaths'; -type IconProps = { +export type IconProps = { /** * Name of a Sovryn UI icon, or an custom SVG element, or an Fontawesome imported icon to render. * This prop is required because it determines the content of the component @@ -32,6 +32,10 @@ type IconProps = { * Applied data-action-id value to the element, mainly needed for testing or for GA */ dataActionId?: string; + /** + * Applied viewBox to the svg element. + */ + viewBox?: string; }; export const Icon: React.FC = ({ @@ -40,6 +44,7 @@ export const Icon: React.FC = ({ inline, className, dataActionId, + viewBox = ViewBoxSize.DEFAULT, }) => { const isFaIcon = useMemo(() => !!icon && !!icon['prefix'], [icon]); @@ -77,7 +82,7 @@ export const Icon: React.FC = ({ )); return ( = ({ {paths} ); - }, [icon, inline, size, inlineBlock, className, dataActionId]); + }, [viewBox, icon, inline, size, inlineBlock, className, dataActionId]); return ( <> diff --git a/packages/ui/src/1_atoms/Icon/icon.test.jsx b/packages/ui/src/1_atoms/Icon/icon.test.tsx similarity index 100% rename from packages/ui/src/1_atoms/Icon/icon.test.jsx rename to packages/ui/src/1_atoms/Icon/icon.test.tsx diff --git a/packages/ui/src/1_atoms/Icon/iconNames.ts b/packages/ui/src/1_atoms/Icon/iconNames.ts index a9a17fc9e..95e80f8bd 100644 --- a/packages/ui/src/1_atoms/Icon/iconNames.ts +++ b/packages/ui/src/1_atoms/Icon/iconNames.ts @@ -21,3 +21,5 @@ export const TREND_ARROW_DOWN = 'trend-arrow-down'; export const WARNING = 'warning'; export const WITHDRAW = 'withdraw'; export const X_MARK = 'x-mark'; +export const COPY = 'copy'; +export const EXIT = 'exit'; diff --git a/packages/ui/src/1_atoms/Icon/iconSvgPaths.ts b/packages/ui/src/1_atoms/Icon/iconSvgPaths.ts index 617e4d5ab..a82adfe8d 100644 --- a/packages/ui/src/1_atoms/Icon/iconSvgPaths.ts +++ b/packages/ui/src/1_atoms/Icon/iconSvgPaths.ts @@ -73,4 +73,10 @@ export const IconSvgPaths: Record = { 'x-mark': [ 'M24 2.41714L21.5829 0L12 9.58286L2.41714 0L0 2.41714L9.58286 12L0 21.5829L2.41714 24L12 14.4171L21.5829 24L24 21.5829L14.4171 12L24 2.41714Z', ], + copy: [ + 'M15.4737 0H2.21053C0.994737 0 0 0.940909 0 2.09091V16.7273H2.21053V2.09091H15.4737V0ZM18.7895 4.18182H6.63158C5.41579 4.18182 4.42105 5.12273 4.42105 6.27273V20.9091C4.42105 22.0591 5.41579 23 6.63158 23H18.7895C20.0053 23 21 22.0591 21 20.9091V6.27273C21 5.12273 20.0053 4.18182 18.7895 4.18182ZM18.7895 20.9091H6.63158V6.27273H18.7895V20.9091Z', + ], + exit: [ + 'M18 4.88889L16.308 6.61222L19.404 9.77778H7.2V12.2222H19.404L16.308 15.3756L18 17.1111L24 11L18 4.88889ZM2.4 2.44444H12V0H2.4C1.08 0 0 1.1 0 2.44444V19.5556C0 20.9 1.08 22 2.4 22H12V19.5556H2.4V2.44444Z', + ], }; diff --git a/packages/ui/src/2_molecules/Dropdown/Dropdown.module.css b/packages/ui/src/2_molecules/Dropdown/Dropdown.module.css index 9aee4697f..e0f892b23 100644 --- a/packages/ui/src/2_molecules/Dropdown/Dropdown.module.css +++ b/packages/ui/src/2_molecules/Dropdown/Dropdown.module.css @@ -1,20 +1,20 @@ -.button { - @apply flex items-center bg-gray-50 justify-between relative h-full min-w-20 whitespace-nowrap font-roboto text-gray-10 text-xs font-semibold px-2.5 leading-none cursor-pointer select-none transition-colors border rounded border-gray-50; +.button[type='button'] { + @apply flex items-center bg-gray-60 border-gray-60 justify-between relative h-full min-w-20 whitespace-nowrap font-roboto text-gray-10 text-xs font-semibold leading-none cursor-pointer select-none transition-colors border rounded; &.isOpen { @apply bg-gray-80 border-gray-80; } &:hover { - @apply bg-gray-60 border-gray-50; + @apply border-gray-50; } &.small { - @apply h-8; + @apply h-8 px-2; } &.large { - @apply h-10; + @apply h-10 px-2.5; } } diff --git a/packages/ui/src/2_molecules/Dropdown/Dropdown.tsx b/packages/ui/src/2_molecules/Dropdown/Dropdown.tsx index 770387793..aa1c493cc 100644 --- a/packages/ui/src/2_molecules/Dropdown/Dropdown.tsx +++ b/packages/ui/src/2_molecules/Dropdown/Dropdown.tsx @@ -32,109 +32,114 @@ type DropdownProps = { dropdownClassName?: string; }; -export const Dropdown = forwardRef(({ - text, - children, - mode = DropdownMode.sameWidth, - size = DropdownSize.large, - onOpen, - onClose, - className, - dataActionId, - dropdownClassName, -}, ref) => { - const buttonRef = useRef(null); - const dropdownRef = useRef(null); - const [isOpen, setOpen] = useState(false); - const [coords, setCoords] = useState>(null); +export const Dropdown = forwardRef( + ( + { + text, + children, + mode = DropdownMode.sameWidth, + size = DropdownSize.large, + onOpen, + onClose, + className, + dataActionId, + dropdownClassName, + }, + ref, + ) => { + const buttonRef = useRef(null); + const dropdownRef = useRef(null); + const [isOpen, setOpen] = useState(false); + const [coords, setCoords] = useState>(null); - useImperativeHandle(ref, () => buttonRef.current!); + useImperativeHandle(ref, () => buttonRef.current!); - const onButtonClick = useCallback( - () => setOpen(prevValue => !prevValue), - [setOpen], - ); + const onButtonClick = useCallback( + () => setOpen(prevValue => !prevValue), + [setOpen], + ); - const getCoords = useCallback(() => { - const button = buttonRef.current?.getBoundingClientRect(); - const dropdownWidth = dropdownRef.current?.getBoundingClientRect().width; - const windowWidth = document.body.getBoundingClientRect().width; - const scrollOffset = window.scrollY; - if (button && dropdownWidth) { - const { top, left, right, width, height } = button; - return { - top: top + height + scrollOffset, - left: left, - right: right, - buttonWidth: width, - windowWidth: windowWidth, - dropdownWidth: dropdownWidth, - }; - } - return null; - }, []); + const getCoords = useCallback(() => { + const button = buttonRef.current?.getBoundingClientRect(); + const dropdownWidth = dropdownRef.current?.getBoundingClientRect().width; + const windowWidth = document.body.getBoundingClientRect().width; + const scrollOffset = window.scrollY; + if (button && dropdownWidth) { + const { top, left, right, width, height } = button; + return { + top: top + height + scrollOffset, + left: left, + right: right, + buttonWidth: width, + windowWidth: windowWidth, + dropdownWidth: dropdownWidth, + }; + } + return null; + }, []); - const dropdownStyles = useMemo(() => { - if (!coords) { - return; - } - return getDropdownPositionStyles(coords, mode); - }, [coords, mode]); + const dropdownStyles = useMemo(() => { + if (!coords) { + return; + } + return getDropdownPositionStyles(coords, mode); + }, [coords, mode]); - const classNamesComplete = useMemo( - () => - classNames(styles.button, styles[size], className, { - [styles.isOpen]: isOpen, - }), - [size, className, isOpen], - ); + const classNamesComplete = useMemo( + () => + classNames(styles.button, styles[size], className, { + [styles.isOpen]: isOpen, + }), + [size, className, isOpen], + ); - const useClickedOutside = useCallback(() => { - setOpen(false); - onClose?.(); - }, [onClose]); + const useClickedOutside = useCallback(() => { + setOpen(false); + onClose?.(); + }, [onClose]); - useOnClickOutside([buttonRef, dropdownRef], useClickedOutside); + useOnClickOutside([buttonRef, dropdownRef], useClickedOutside); - useEffect(() => { - if (!isOpen) { - return; - } - const coords = getCoords(); - setCoords(coords); - onOpen?.(); - }, [isOpen, getCoords, onOpen, mode]); + useEffect(() => { + if (!isOpen) { + return; + } + const coords = getCoords(); + setCoords(coords); + onOpen?.(); + }, [isOpen, getCoords, onOpen, mode]); - return ( - <> - + return ( + <> + - {isOpen && ( - -
- {children} -
-
- )} - - ); -}); + {isOpen && ( + +
+ {children} +
+
+ )} + + ); + }, +); diff --git a/packages/ui/src/2_molecules/Menu/components/MenuItem/MenuItem.module.css b/packages/ui/src/2_molecules/Menu/components/MenuItem/MenuItem.module.css index 6a0c7e87b..c5276d20d 100644 --- a/packages/ui/src/2_molecules/Menu/components/MenuItem/MenuItem.module.css +++ b/packages/ui/src/2_molecules/Menu/components/MenuItem/MenuItem.module.css @@ -22,19 +22,28 @@ line-height: 25px; } + & .text, + & .icon { + @apply text-gray-10; + } + + & .icon { + @apply text-gray-10 mr-2; + } + & .label { @apply text-gray-30 font-normal text-tiny inline-block leading-none pointer-events-none; } } &:last-child { - & .button{ + & .button { @apply mb-0; } } &:first-child { - & .button{ + & .button { @apply mt-0; } } diff --git a/packages/ui/src/2_molecules/Menu/components/MenuItem/MenuItem.tsx b/packages/ui/src/2_molecules/Menu/components/MenuItem/MenuItem.tsx index 3af5a527a..2c7a755d0 100644 --- a/packages/ui/src/2_molecules/Menu/components/MenuItem/MenuItem.tsx +++ b/packages/ui/src/2_molecules/Menu/components/MenuItem/MenuItem.tsx @@ -72,15 +72,7 @@ export const MenuItem: React.FC = ({
{icon && } {text} - - - - +
{label && {label}} @@ -135,8 +127,8 @@ export const MenuItem: React.FC = ({ onClickHandler, dataActionId, icon, - label, text, + label, isActive, ]); diff --git a/packages/ui/src/2_molecules/WalletIdentity/WalletIdentity.module.css b/packages/ui/src/2_molecules/WalletIdentity/WalletIdentity.module.css new file mode 100644 index 000000000..4d0759055 --- /dev/null +++ b/packages/ui/src/2_molecules/WalletIdentity/WalletIdentity.module.css @@ -0,0 +1,11 @@ +.addressBadge { + @apply inline-flex items-center bg-gray-60 h-8 font-roboto text-gray-10 text-xs font-semibold px-2 leading-none select-none rounded; +} + +.dropdown { + width: 155px; +} + +.dropdown { + width: 155px; +} diff --git a/packages/ui/src/2_molecules/WalletIdentity/WalletIdentity.stories.tsx b/packages/ui/src/2_molecules/WalletIdentity/WalletIdentity.stories.tsx new file mode 100644 index 000000000..7e2ffc930 --- /dev/null +++ b/packages/ui/src/2_molecules/WalletIdentity/WalletIdentity.stories.tsx @@ -0,0 +1,56 @@ +import { ComponentStory, ComponentMeta, Story } from '@storybook/react'; + +import React, { ComponentProps } from 'react'; + +import { WalletIdentity } from './WalletIdentity'; +import { AddressBadge } from './components/AddressBadge/AddressBadge'; +import { DisconnectSubmenu } from './components/DisconnectSubmenu/DisconnectSubmenu'; + +export default { + title: 'Molecule/WalletIdentity', + component: WalletIdentity, + subcomponents: { + AddressBadge, + DisconnectSubmenu, + }, + argTypes: { + hideSubmenu: { + defaultValue: false, + }, + startLength: { + defaultValue: 4, + }, + endLength: { + defaultValue: 4, + }, + }, +} as ComponentMeta; + +const Template: Story> = args => ( + +); + +export const _WalletIdentity = Template.bind({}); +_WalletIdentity.args = { + onDisconnect: () => alert('disconnected'), + address: '0xEDb8897aB6E907bc63CB256f74437D36298507E2', + dataActionId: 'walletIdentity', + submenuLabels: { + copyAddress: 'Copy Address', + disconnect: 'Disconnect', + }, +}; + +const DisconnectSubmenuTemplate: Story< + ComponentProps +> = args => ( +
+ +
+); + +export const _DisconnectSubmenu = DisconnectSubmenuTemplate.bind({}); +_DisconnectSubmenu.args = { + onDisconnect: () => alert('disconnected'), + address: '0xEDb8897aB6E907bc63CB256f74437D36298507E2', +}; diff --git a/packages/ui/src/2_molecules/WalletIdentity/WalletIdentity.test.tsx b/packages/ui/src/2_molecules/WalletIdentity/WalletIdentity.test.tsx new file mode 100644 index 000000000..34a52cbcf --- /dev/null +++ b/packages/ui/src/2_molecules/WalletIdentity/WalletIdentity.test.tsx @@ -0,0 +1,96 @@ +import { render } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import React from 'react'; + +import { prettyTx } from '../../utils'; +import { WalletIdentity } from './WalletIdentity'; + +jest.mock('react-router', () => ({ + ...(jest.requireActual('react-router') as {}), + useLocation: jest.fn().mockImplementation(() => { + return { pathname: '/testroute', search: '', hash: '', state: null }; + }), +})); + +Object.assign(navigator, { + clipboard: { + writeText: () => {}, + }, +}); + +describe('WalletIdentity', () => { + beforeEach(() => { + jest.spyOn(navigator.clipboard, 'writeText'); + jest.spyOn(window, 'alert').mockImplementation(() => {}); + }); + + test('renders WalletIdentity', async () => { + const testAddress = '0x32Be343B94f860124dC4fEe278FDCBD38C102D88'; + const { getByText } = render( + {}} + startLength={4} + endLength={4} + dataActionId="walletIdentityTest" + />, + ); + const addressBadge = getByText(prettyTx(testAddress, 4, 4)); + + expect(addressBadge).toBeDefined(); + expect(addressBadge).toHaveAttribute( + 'data-action-id', + 'walletIdentityTest', + ); + }); + + test('copy address button', async () => { + const testAddress = '0x32Be343B94f860124dC4fEe278FDCBD38C102D88'; + const { getByText, baseElement } = render( + {}} + startLength={4} + endLength={4} + dataActionId="walletIdentityTest" + />, + ); + const addressBadge = getByText(prettyTx(testAddress, 4, 4)); + + userEvent.click(addressBadge); + + const copyButton = baseElement.querySelector( + '[data-action-id="walletIdentityTest-menu-copyAddress"]', + ); + expect(copyButton).toBeInTheDocument(); + + userEvent.click(copyButton!); + expect(navigator.clipboard.writeText).toHaveBeenCalledWith(testAddress); + }); + + test('disconnect button', async () => { + const disconnectFunction = jest.fn(); + const testAddress = '0x32Be343B94f860124dC4fEe278FDCBD38C102D88'; + const { getByText, baseElement } = render( + , + ); + const addressBadge = getByText(prettyTx(testAddress, 4, 4)); + + userEvent.click(addressBadge); + + const disconnectButton = baseElement.querySelector( + '[data-action-id="disconnectTest-menu-disconnect"]', + ); + expect(disconnectButton).toBeInTheDocument(); + + userEvent.click(disconnectButton!); + expect(disconnectFunction).toHaveBeenCalled(); + }); +}); diff --git a/packages/ui/src/2_molecules/WalletIdentity/WalletIdentity.tsx b/packages/ui/src/2_molecules/WalletIdentity/WalletIdentity.tsx new file mode 100644 index 000000000..f385ad2d7 --- /dev/null +++ b/packages/ui/src/2_molecules/WalletIdentity/WalletIdentity.tsx @@ -0,0 +1,68 @@ +import React, { FC } from 'react'; + +import classNames from 'classnames'; + +import { Dropdown } from '../Dropdown/Dropdown'; +import { DropdownSize } from '../Dropdown/Dropdown.types'; +import styles from './WalletIdentity.module.css'; +import { AddressBadge } from './components/AddressBadge/AddressBadge'; +import { + DisconnectSubmenu, + MenuLabels, +} from './components/DisconnectSubmenu/DisconnectSubmenu'; + +export type WalletIdentityProps = { + onDisconnect?: () => void; + address: string; + className?: string; + dataActionId?: string; + hideSubmenu?: boolean; + submenuLabels?: MenuLabels; + startLength?: number; + endLength?: number; +}; + +export const WalletIdentity: FC = ({ + address, + onDisconnect, + className, + hideSubmenu = false, + startLength = 4, + endLength = 4, + dataActionId, + submenuLabels, +}) => { + if (hideSubmenu) { + return ( +
+ +
+ ); + } + return ( + + } + size={DropdownSize.small} + > + + + ); +}; diff --git a/packages/ui/src/2_molecules/WalletIdentity/components/AddressBadge/AddressBadge.module.css b/packages/ui/src/2_molecules/WalletIdentity/components/AddressBadge/AddressBadge.module.css new file mode 100644 index 000000000..f9a29a587 --- /dev/null +++ b/packages/ui/src/2_molecules/WalletIdentity/components/AddressBadge/AddressBadge.module.css @@ -0,0 +1,6 @@ +.addressBadge { + @apply flex flex-nowrap flex-row items-center w-full truncate font-semibold text-sm; + .walletLogo { + @apply rounded-full mr-2; + } +} diff --git a/packages/ui/src/2_molecules/WalletIdentity/components/AddressBadge/AddressBadge.tsx b/packages/ui/src/2_molecules/WalletIdentity/components/AddressBadge/AddressBadge.tsx new file mode 100644 index 000000000..2ecade1e4 --- /dev/null +++ b/packages/ui/src/2_molecules/WalletIdentity/components/AddressBadge/AddressBadge.tsx @@ -0,0 +1,49 @@ +import React, { FC } from 'react'; + +import blockies from 'ethereum-blockies'; + +import { prettyTx } from '../../../../utils'; +import styles from './AddressBadge.module.css'; + +export type AddressBadgeProps = { + address: string; + startLength?: number; + endLength?: number; + dataActionId?: string; +}; + +export const AddressBadge: FC = ({ + address, + startLength = 4, + endLength = 4, + dataActionId, +}) => { + const getWalletAddrBlockieImg = (): string => { + return blockies + .create({ + // All options are optional + seed: address, // seed used to generate icon data, default: random + color: '#dfe', // to manually specify the icon color, default: random + bgcolor: '#aaa', // choose a different background color, default: random + size: 8, // width/height of the icon in blocks, default: 8 + scale: 3, // width/height of each block in pixels, default: 4 + spotcolor: '#000', // each pixel has a 13% chance of being of a third color, + }) + .toDataURL(); + }; + + return ( + + + wallet address + + + {prettyTx(address || '', startLength, endLength)} + + + ); +}; diff --git a/packages/ui/src/2_molecules/WalletIdentity/components/DisconnectSubmenu/DisconnectSubmenu.tsx b/packages/ui/src/2_molecules/WalletIdentity/components/DisconnectSubmenu/DisconnectSubmenu.tsx new file mode 100644 index 000000000..607d22a78 --- /dev/null +++ b/packages/ui/src/2_molecules/WalletIdentity/components/DisconnectSubmenu/DisconnectSubmenu.tsx @@ -0,0 +1,52 @@ +import React, { FC, useCallback } from 'react'; + +import { Menu, MenuItem } from '../../../Menu/Menu'; + +export type MenuLabels = { + copyAddress: string; + disconnect: string; +}; + +export type DisconnectSubmenuProps = { + onDisconnect?: () => void; + address: string; + className?: string; + dataActionId?: string; + menuLabels?: MenuLabels; +}; + +export const DisconnectSubmenu: FC = ({ + address, + onDisconnect, + className, + dataActionId, + menuLabels, +}) => { + const copyAddress = useCallback(async () => { + await navigator.clipboard.writeText(address); + alert('Address was copied to clipboard.'); + }, [address]); + + return ( + + + {onDisconnect && ( + + )} + + ); +}; diff --git a/packages/ui/src/2_molecules/index.ts b/packages/ui/src/2_molecules/index.ts index bfda594ad..363aafd40 100644 --- a/packages/ui/src/2_molecules/index.ts +++ b/packages/ui/src/2_molecules/index.ts @@ -1,4 +1,6 @@ export * from './Overlay/Overlay'; export * from './Dialog/Dialog'; export * from './Dropdown/Dropdown'; +export * from './Dropdown/Dropdown.types'; export * from './Menu/Menu'; +export * from './WalletIdentity/WalletIdentity'; diff --git a/packages/ui/src/utils/index.ts b/packages/ui/src/utils/index.ts index f2d5e31d0..693dcf840 100644 --- a/packages/ui/src/utils/index.ts +++ b/packages/ui/src/utils/index.ts @@ -1 +1,11 @@ export const noop = () => {}; + +export const prettyTx = ( + text: string, + startLength: number = 6, + endLength: number = 4, +) => { + const start = text.substr(0, startLength); + const end = text.substr(-endLength); + return `${start} ··· ${end}`; +}; diff --git a/yarn.lock b/yarn.lock index 30d9763a7..99e3098a2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1537,6 +1537,14 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" +"@ethereumjs/common@^2.6.5": + version "2.6.5" + resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.5.tgz#0a75a22a046272579d91919cb12d84f2756e8d30" + integrity sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA== + dependencies: + crc-32 "^1.2.0" + ethereumjs-util "^7.1.5" + "@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.7.0": version "5.7.0" resolved "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz" @@ -1910,6 +1918,18 @@ resolved "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz" integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== +"@hapi/hoek@^9.0.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" + integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== + +"@hapi/topo@^5.0.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" + integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== + dependencies: + "@hapi/hoek" "^9.0.0" + "@humanwhocodes/config-array@^0.10.4": version "0.10.4" resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz" @@ -2649,6 +2669,23 @@ resolved "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz" integrity sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg== +"@sideway/address@^4.1.3": + version "4.1.4" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" + integrity sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@sideway/formula@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c" + integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg== + +"@sideway/pinpoint@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" + integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== + "@sinclair/typebox@^0.24.1": version "0.24.42" resolved "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.42.tgz" @@ -2675,6 +2712,61 @@ dependencies: "@sinonjs/commons" "^1.7.0" +"@sovryn/onboard-common@*", "@sovryn/onboard-common@0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@sovryn/onboard-common/-/onboard-common-0.0.1.tgz#d98c8aa842e4054b313d357a217b67eb618af0c2" + integrity sha512-m/01kyNT15Cj8cjMxqeaAF3nrMy9cO/QLGUg67UH3cXU95buT1BYuaqiuaT1on/NgwDka8ccsRZ/vGaWfKIRFA== + dependencies: + ethers "^5.7.0" + joi "^17.6.0" + +"@sovryn/onboard-core@*", "@sovryn/onboard-core@0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@sovryn/onboard-core/-/onboard-core-0.0.2.tgz#f70f1136d91a7b87a7598c59964863534c4950a5" + integrity sha512-Gmchytb0EV8GqZRXedMJ1Vedku2DGCcXmNc+Oj08zCg+RDF4u93LfMzanT8pZ7CY/z/loXR/kKOrKQLnBKhvPw== + dependencies: + "@sovryn/onboard-common" "*" + bowser "^2.11.0" + ethers "^5.7.0" + eventemitter3 "^4.0.7" + joi "^17.6.0" + lodash.partition "^4.6.0" + rxjs "^7.5.6" + +"@sovryn/onboard-hw-common@*": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@sovryn/onboard-hw-common/-/onboard-hw-common-0.0.1.tgz#53099c1e658856d4cab231e26524fb0b73922fda" + integrity sha512-rrcBRgvYfBz2R29DK0uoavQW+nOresd9EHOf+1JrlHoftQTzRxjhDjIzOW92MgO1qsp8iku46f97FDGkJPhGaQ== + dependencies: + "@ethereumjs/common" "^2.6.5" + "@sovryn/onboard-common" "*" + "@sovryn/onboard-core" "*" + ethers "^5.7.0" + joi "^17.6.0" + rxjs "^7.5.6" + +"@sovryn/onboard-injected@0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@sovryn/onboard-injected/-/onboard-injected-0.0.1.tgz#b55727b1aef711f4cb0a8ccfb54975d0e470163f" + integrity sha512-rzOWlMUr0OEGOIeMxp5ycprU7VvIPpV9cgXbey/2PoesBLZY/k99L+I1VJDfO+2cxi40g1YJk7sI+VcB8fZKqQ== + dependencies: + "@sovryn/onboard-common" "*" + ethers "^5.7.0" + eventemitter3 "^4.0.7" + joi "^17.6.0" + lodash.partition "^4.6.0" + lodash.uniqby "^4.7.0" + rxjs "^7.5.6" + +"@sovryn/onboard-react@0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@sovryn/onboard-react/-/onboard-react-0.0.2.tgz#1560dd26866d13c18825614fd7eaf990bf90fe2b" + integrity sha512-BimHLF2vVJXySxbHfOn0VpQlBOK+YTFNnnRjUvdV7LN9/xjE4qcO/p4JZfEiQr+JAlyQPmLHfkTkZoWEMYTmrw== + dependencies: + "@sovryn/onboard-common" "*" + "@sovryn/onboard-core" "*" + "@sovryn/onboard-hw-common" "*" + "@storybook/addon-actions@6.5.9": version "6.5.9" resolved "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-6.5.9.tgz" @@ -3986,6 +4078,13 @@ dependencies: "@babel/types" "^7.3.0" +"@types/bn.js@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" + integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== + dependencies: + "@types/node" "*" + "@types/body-parser@*": version "1.19.2" resolved "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz" @@ -4248,6 +4347,13 @@ resolved "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz" integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== +"@types/pbkdf2@^3.0.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.0.tgz#039a0e9b67da0cdc4ee5dab865caa6b267bb66b1" + integrity sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ== + dependencies: + "@types/node" "*" + "@types/prettier@^2.1.5": version "2.7.0" resolved "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.0.tgz" @@ -4318,6 +4424,13 @@ resolved "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz" integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== +"@types/secp256k1@^4.0.1": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.3.tgz#1b8e55d8e00f08ee7220b4d59a6abe89c37a901c" + integrity sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w== + dependencies: + "@types/node" "*" + "@types/serve-index@^1.9.1": version "1.9.1" resolved "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz" @@ -5567,6 +5680,13 @@ balanced-match@^1.0.0: resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base-x@^3.0.2: + version "3.0.9" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" + integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== + dependencies: + safe-buffer "^5.0.1" + base64-js@^1.0.2: version "1.5.1" resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" @@ -5639,6 +5759,11 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" +blakejs@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" + integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== + bluebird@^3.5.5: version "3.7.2" resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz" @@ -5649,7 +5774,7 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.2.1: +bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: version "5.2.1" resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== @@ -5687,6 +5812,11 @@ boolbase@^1.0.0, boolbase@~1.0.0: resolved "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz" integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== +bowser@^2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" + integrity sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA== + boxen@^5.1.2: version "5.1.2" resolved "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz" @@ -5761,7 +5891,7 @@ browser-process-hrtime@^1.0.0: resolved "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz" integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== -browserify-aes@^1.0.0, browserify-aes@^1.0.4: +browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz" integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== @@ -5832,6 +5962,22 @@ browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4 node-releases "^2.0.6" update-browserslist-db "^1.0.9" +bs58@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" + integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== + dependencies: + base-x "^3.0.2" + +bs58check@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" + integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== + dependencies: + bs58 "^4.0.0" + create-hash "^1.1.0" + safe-buffer "^5.1.2" + bser@2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz" @@ -6196,6 +6342,11 @@ classnames@2.3.1: resolved "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz" integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== +classnames@2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" + integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== + clean-css@^4.2.3: version "4.2.4" resolved "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz" @@ -6608,6 +6759,11 @@ cpy@^8.1.2: p-filter "^2.1.0" p-map "^3.0.0" +crc-32@^1.2.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" + integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== + create-ecdh@^4.0.0: version "4.0.4" resolved "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz" @@ -6838,6 +6994,11 @@ cssesc@^3.0.0: resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== +cssfontparser@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/cssfontparser/-/cssfontparser-1.2.1.tgz#f4022fc8f9700c68029d542084afbaf425a3f3e3" + integrity sha512-6tun4LoZnj7VN6YeegOVb67KBX/7JJsqvj+pv3ZA7F878/eN33AbGa5b/S/wXxS/tcp8nc40xRUrsPlxIyNUPg== + cssnano-preset-default@^5.2.12: version "5.2.12" resolved "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.12.tgz" @@ -7366,7 +7527,7 @@ electron-to-chromium@^1.4.251: resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.254.tgz" integrity sha512-Sh/7YsHqQYkA6ZHuHMy24e6TE4eX6KZVsZb9E/DvU1nQRIrH4BflO/4k+83tfdYvDl+MObvlqHPRICzEdC9c6Q== -elliptic@6.5.4, elliptic@^6.5.3: +elliptic@6.5.4, elliptic@^6.5.3, elliptic@^6.5.4: version "6.5.4" resolved "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz" integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== @@ -8153,7 +8314,44 @@ etag@~1.8.1: resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== -ethers@5.7.1: +ethereum-blockies@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ethereum-blockies/-/ethereum-blockies-0.1.1.tgz#879fe959deef492a7a92b43dc34ae8dc2ee591fc" + integrity sha512-ED+noMZ6z7RrzzhvrQna1L30C27MX+ZsdB5c/d5vygXtHjEyAQjQS2TgCYhPxs+z3U+u2YQsL9PiRkNl1f+ugg== + +ethereum-cryptography@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" + integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== + dependencies: + "@types/pbkdf2" "^3.0.0" + "@types/secp256k1" "^4.0.1" + blakejs "^1.1.0" + browserify-aes "^1.2.0" + bs58check "^2.1.2" + create-hash "^1.2.0" + create-hmac "^1.1.7" + hash.js "^1.1.7" + keccak "^3.0.0" + pbkdf2 "^3.0.17" + randombytes "^2.1.0" + safe-buffer "^5.1.2" + scrypt-js "^3.0.0" + secp256k1 "^4.0.1" + setimmediate "^1.0.5" + +ethereumjs-util@^7.1.5: + version "7.1.5" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" + integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== + dependencies: + "@types/bn.js" "^5.1.0" + bn.js "^5.1.2" + create-hash "^1.1.2" + ethereum-cryptography "^0.1.3" + rlp "^2.2.4" + +ethers@5.7.1, ethers@^5.7.0: version "5.7.1" resolved "https://registry.npmjs.org/ethers/-/ethers-5.7.1.tgz" integrity sha512-5krze4dRLITX7FpU8J4WscXqADiKmyeNlylmmDLbS95DaZpBhDe2YSwRQwKXWNyXcox7a3gBgm/MkGXV1O1S/Q== @@ -8189,7 +8387,7 @@ ethers@5.7.1: "@ethersproject/web" "5.7.1" "@ethersproject/wordlists" "5.7.0" -eventemitter3@^4.0.0, eventemitter3@^4.0.4: +eventemitter3@^4.0.0, eventemitter3@^4.0.4, eventemitter3@^4.0.7: version "4.0.7" resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== @@ -9150,7 +9348,7 @@ hash-base@^3.0.0: readable-stream "^3.6.0" safe-buffer "^5.2.0" -hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: version "1.1.7" resolved "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz" integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== @@ -9593,7 +9791,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: version "2.0.4" resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -10171,6 +10369,14 @@ javascript-natural-sort@0.7.1: resolved "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz" integrity sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw== +jest-canvas-mock@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jest-canvas-mock/-/jest-canvas-mock-2.4.0.tgz#947b71442d7719f8e055decaecdb334809465341" + integrity sha512-mmMpZzpmLzn5vepIaHk5HoH3Ka4WykbSoLuG/EKoJd0x0ID/t+INo1l8ByfcUJuDM+RIsL4QDg/gDnBbrj2/IQ== + dependencies: + cssfontparser "^1.2.1" + moo-color "^1.0.2" + jest-changed-files@^27.5.1: version "27.5.1" resolved "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz" @@ -11067,6 +11273,17 @@ jest@^27.4.3: import-local "^3.0.2" jest-cli "^27.5.1" +joi@^17.6.0: + version "17.6.2" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.6.2.tgz#00ac55ce6495596545cce45309f38738cfbd7cd3" + integrity sha512-+gqqdh1xc1wb+Lor0J9toqgeReyDOCqOdG8QSdRcEvwrcRiFQZneUCGKjFjuyBWUb3uaFOgY56yMaZ5FIc+H4w== + dependencies: + "@hapi/hoek" "^9.0.0" + "@hapi/topo" "^5.0.0" + "@sideway/address" "^4.1.3" + "@sideway/formula" "^3.0.0" + "@sideway/pinpoint" "^2.0.0" + joycon@^3.0.1: version "3.1.1" resolved "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz" @@ -11252,6 +11469,15 @@ junk@^3.1.0: resolved "https://registry.npmjs.org/junk/-/junk-3.1.0.tgz" integrity sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ== +keccak@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0" + integrity sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + readable-stream "^3.6.0" + kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" @@ -11469,6 +11695,11 @@ lodash.merge@^4.6.2: resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== +lodash.partition@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.partition/-/lodash.partition-4.6.0.tgz#a38e46b73469e0420b0da1212e66d414be364ba4" + integrity sha512-35L3dSF3Q6V1w5j6V3NhNlQjzsRDC/pYKCTdYTmwqSib+Q8ponkAmt/PwEOq3EmI38DSCl+SkIVwLd+uSlVdrg== + lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz" @@ -11484,6 +11715,11 @@ lodash.uniq@4.5.0, lodash.uniq@^4.5.0: resolved "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz" integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== +lodash.uniqby@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302" + integrity sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww== + lodash@4.17.21, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: version "4.17.21" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" @@ -11963,6 +12199,13 @@ mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +moo-color@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/moo-color/-/moo-color-1.0.3.tgz#d56435f8359c8284d83ac58016df7427febece74" + integrity sha512-i/+ZKXMDf6aqYtBhuOcej71YSlbjT3wCO/4H1j8rPvxDJEifdwgg5MaFyu6iYAT8GBZJg2z0dkgK4YMzvURALQ== + dependencies: + color-name "^1.1.4" + move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz" @@ -12072,6 +12315,11 @@ no-case@^3.0.4: lower-case "^2.0.2" tslib "^2.0.3" +node-addon-api@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" + integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== + node-dir@^0.1.10: version "0.1.17" resolved "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz" @@ -12091,6 +12339,11 @@ node-forge@^1: resolved "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz" integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== +node-gyp-build@^4.2.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.5.0.tgz#7a64eefa0b21112f89f58379da128ac177f20e40" + integrity sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg== + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz" @@ -12704,7 +12957,7 @@ path-type@^4.0.0: resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -pbkdf2@^3.0.3: +pbkdf2@^3.0.17, pbkdf2@^3.0.3: version "3.1.2" resolved "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz" integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== @@ -14041,7 +14294,7 @@ read-pkg@^5.2.0: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.6, readable-stream@^3.6.0: +readable-stream@^3.0.6, readable-stream@^3.5.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -14411,6 +14664,13 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" +rlp@^2.2.4: + version "2.2.7" + resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" + integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== + dependencies: + bn.js "^5.2.0" + rollup-plugin-dts@4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/rollup-plugin-dts/-/rollup-plugin-dts-4.2.2.tgz#82876b8784213af29b02cf260b45e404ff835ce1" @@ -14497,9 +14757,9 @@ rxjs@7.5.6: dependencies: tslib "^2.1.0" -rxjs@^7.5.5: +rxjs@^7.5.5, rxjs@^7.5.6: version "7.5.7" - resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.7.tgz#2ec0d57fdc89ece220d2e702730ae8f1e49def39" integrity sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA== dependencies: tslib "^2.1.0" @@ -14636,11 +14896,20 @@ schema-utils@^4.0.0: ajv-formats "^2.1.1" ajv-keywords "^5.0.0" -scrypt-js@3.0.1: +scrypt-js@3.0.1, scrypt-js@^3.0.0: version "3.0.1" resolved "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz" integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== +secp256k1@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" + integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== + dependencies: + elliptic "^6.5.4" + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + select-hose@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz" @@ -14759,7 +15028,7 @@ set-value@^2.0.0, set-value@^2.0.1: is-plain-object "^2.0.3" split-string "^3.0.1" -setimmediate@^1.0.4: +setimmediate@^1.0.4, setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz" integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== @@ -15125,6 +15394,14 @@ storybook-css-modules@1.0.8: resolved "https://registry.npmjs.org/storybook-css-modules/-/storybook-css-modules-1.0.8.tgz" integrity sha512-anITwllH6nLw0quPElVBLRrE8QDbcRv0Dgl8sKLOc4uiqw+g1GE2l21Stjx3Wyv2O6ZKJScbyOpOuuz3SmeaOQ== +stream-browserify@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-3.0.0.tgz#22b0a2850cdf6503e73085da1fc7b7d0c2122f2f" + integrity sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA== + dependencies: + inherits "~2.0.4" + readable-stream "^3.5.0" + stream-browserify@^2.0.1: version "2.0.2" resolved "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz"