diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..d90c066d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +root = true + +[*] +charset = utf-8 +indent_size = 4 +end_of_line = lf +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.yml] +indent_size = 4 +indent_style = space diff --git a/.prettierrc.json b/.prettierrc.json index 95f5249c..50b3a486 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,6 +1,6 @@ { "semi": true, - "tabWidth": 2, + "tabWidth": 4, "printWidth": 100, "singleQuote": true, "trailingComma": "all", diff --git a/package.json b/package.json index 85336303..ea2c78da 100644 --- a/package.json +++ b/package.json @@ -1,86 +1,86 @@ { - "name": "ark-connect-webext", - "private": true, - "version": "1.4.1", - "type": "module", - "scripts": { - "dev": "VITE_SEED_ADDRESSES=true vite", - "dev:firefox": "VITE_SEED_ADDRESSES=true BROWSER=firefox vite", - "dev:bare": "vite", - "dev:bare:firefox": "BROWSER=firefox vite", - "test": "vitest", - "build": "rm -rf dist && tsc && vite build && zip build.zip dist", - "build:firefox": "rm -rf dist && BROWSER=firefox vite build --config vite.production.config.ts", - "build:chrome": "rm -rf dist && BROWSER=chrome vite build --config vite.production.config.ts", - "lint": "npx eslint -c .eslintrc.json --cache --ext .jsx,.js,.tsx,.ts src --fix", - "format": "prettier --write src/**/*.{js,jsx,ts,tsx} --config .prettierrc.json", - "preview": "vite preview", - "generate:icons": "node scripts/generate-icons.js" - }, - "dependencies": { - "@ardenthq/sdk": "1.3.0-beta.1", - "@ardenthq/sdk-ark": "1.3.0-beta.1", - "@ardenthq/sdk-cryptography": "1.3.0-beta.1", - "@ardenthq/sdk-helpers": "1.3.0-beta.1", - "@ardenthq/sdk-intl": "1.3.0-beta.1", - "@ardenthq/sdk-ledger": "1.3.0-beta.1", - "@ardenthq/sdk-profiles": "1.3.0-beta.1", - "@reduxjs/toolkit": "^1.9.5", - "@sentry/react": "^7.69.0", - "@styled-system/should-forward-prop": "^5.1.5", - "@tippyjs/react": "^4.2.6", - "assert": "2.0.0", - "crypto-js": "^4.1.1", - "focus-trap-react": "^10.2.3", - "formik": "^2.4.3", - "locale-currency": "^0.0.2", - "node-fetch": "2.6.11", - "p-retry": "^6.2.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-idle-timer": "^5.7.2", - "react-redux": "^8.1.2", - "react-refresh": "^0.14.0", - "react-router-dom": "^6.15.0", - "redux": "^5.0.1", - "redux-persist": "^6.0.0", - "semver": "^7.5.4", - "socks-proxy-agent": "^7.0.0", - "string-hash": "^1.1.3", - "styled-components": "^6.0.7", - "styled-system": "^5.1.5", - "tippy.js": "^6.3.7", - "uuid": "^9.0.1", - "xss": "^1.0.14", - "yup": "^1.2.0" - }, - "devDependencies": { - "@samrum/vite-plugin-web-extension": "^5.0.0", - "@testing-library/react": "^14.1.2", - "@types/crypto-js": "^4.1.1", - "@types/react": "^18.2.15", - "@types/react-dom": "^18.2.7", - "@types/semver": "^7.5.6", - "@types/string-hash": "^1.1.1", - "@types/styled-components": "^5.1.26", - "@types/styled-system": "^5.1.16", - "@types/styled-system__should-forward-prop": "^5.1.2", - "@types/uuid": "^9.0.5", - "@types/webextension-polyfill": "^0.10.0", - "@typescript-eslint/eslint-plugin": "^6.3.0", - "@typescript-eslint/parser": "^6.3.0", - "@vitejs/plugin-react": "^4.0.4", - "eslint": "^8.46.0", - "eslint-plugin-react": "^7.33.1", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-refresh": "^0.4.3", - "jsdom": "^24.0.0", - "prettier": "^3.0.1", - "svgo": "^3.0.2", - "typescript": "^5.0.2", - "vite": "^5.0.12", - "vite-plugin-web-extension": "^4.1.1", - "vitest": "^1.2.1", - "webextension-polyfill": "^0.10.0" - } + "name": "ark-connect-webext", + "private": true, + "version": "1.4.1", + "type": "module", + "scripts": { + "dev": "VITE_SEED_ADDRESSES=true vite", + "dev:firefox": "VITE_SEED_ADDRESSES=true BROWSER=firefox vite", + "dev:bare": "vite", + "dev:bare:firefox": "BROWSER=firefox vite", + "test": "vitest", + "build": "rm -rf dist && tsc && vite build && zip build.zip dist", + "build:firefox": "rm -rf dist && BROWSER=firefox vite build --config vite.production.config.ts", + "build:chrome": "rm -rf dist && BROWSER=chrome vite build --config vite.production.config.ts", + "lint": "npx eslint -c .eslintrc.json --cache --ext .jsx,.js,.tsx,.ts src --fix", + "format": "prettier --write src/**/*.{ts,tsx} --config .prettierrc.json", + "preview": "vite preview", + "generate:icons": "node scripts/generate-icons.js" + }, + "dependencies": { + "@ardenthq/sdk": "1.3.0-beta.1", + "@ardenthq/sdk-ark": "1.3.0-beta.1", + "@ardenthq/sdk-cryptography": "1.3.0-beta.1", + "@ardenthq/sdk-helpers": "1.3.0-beta.1", + "@ardenthq/sdk-intl": "1.3.0-beta.1", + "@ardenthq/sdk-ledger": "1.3.0-beta.1", + "@ardenthq/sdk-profiles": "1.3.0-beta.1", + "@reduxjs/toolkit": "^1.9.5", + "@sentry/react": "^7.69.0", + "@styled-system/should-forward-prop": "^5.1.5", + "@tippyjs/react": "^4.2.6", + "assert": "2.0.0", + "crypto-js": "^4.1.1", + "focus-trap-react": "^10.2.3", + "formik": "^2.4.3", + "locale-currency": "^0.0.2", + "node-fetch": "2.6.11", + "p-retry": "^6.2.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-idle-timer": "^5.7.2", + "react-redux": "^8.1.2", + "react-refresh": "^0.14.0", + "react-router-dom": "^6.15.0", + "redux": "^5.0.1", + "redux-persist": "^6.0.0", + "semver": "^7.5.4", + "socks-proxy-agent": "^7.0.0", + "string-hash": "^1.1.3", + "styled-components": "^6.0.7", + "styled-system": "^5.1.5", + "tippy.js": "^6.3.7", + "uuid": "^9.0.1", + "xss": "^1.0.14", + "yup": "^1.2.0" + }, + "devDependencies": { + "@samrum/vite-plugin-web-extension": "^5.0.0", + "@testing-library/react": "^14.1.2", + "@types/crypto-js": "^4.1.1", + "@types/react": "^18.2.15", + "@types/react-dom": "^18.2.7", + "@types/semver": "^7.5.6", + "@types/string-hash": "^1.1.1", + "@types/styled-components": "^5.1.26", + "@types/styled-system": "^5.1.16", + "@types/styled-system__should-forward-prop": "^5.1.2", + "@types/uuid": "^9.0.5", + "@types/webextension-polyfill": "^0.10.0", + "@typescript-eslint/eslint-plugin": "^6.3.0", + "@typescript-eslint/parser": "^6.3.0", + "@vitejs/plugin-react": "^4.0.4", + "eslint": "^8.46.0", + "eslint-plugin-react": "^7.33.1", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.3", + "jsdom": "^24.0.0", + "prettier": "^3.0.1", + "svgo": "^3.0.2", + "typescript": "^5.0.2", + "vite": "^5.0.12", + "vite-plugin-web-extension": "^4.1.1", + "vitest": "^1.2.1", + "webextension-polyfill": "^0.10.0" + } } diff --git a/src/components/AutoUnlockWrapper.tsx b/src/components/AutoUnlockWrapper.tsx index 2fb31dd7..390e009b 100644 --- a/src/components/AutoUnlockWrapper.tsx +++ b/src/components/AutoUnlockWrapper.tsx @@ -11,80 +11,80 @@ import { useIdleTimer } from 'react-idle-timer'; import browser from 'webextension-polyfill'; type Props = { - children: React.ReactNode | React.ReactNode[]; + children: React.ReactNode | React.ReactNode[]; }; const AutoUnlockWrapper = ({ children }: Props) => { - const dispatch = useAppDispatch(); - const { currentThemeMode } = useThemeMode(); - const { persistScreen } = getPersistedValues(); - const { profile, isProfileReady } = useProfileContext(); - const navigate = useNavigate(); - const [isLoadingLocalData, setIsLoadingLocalData] = useState(true); - const locked = useAppSelector(UIStore.selectLocked); + const dispatch = useAppDispatch(); + const { currentThemeMode } = useThemeMode(); + const { persistScreen } = getPersistedValues(); + const { profile, isProfileReady } = useProfileContext(); + const navigate = useNavigate(); + const [isLoadingLocalData, setIsLoadingLocalData] = useState(true); + const locked = useAppSelector(UIStore.selectLocked); - useLayoutEffect(() => { - const checkLocked = async () => { - const status = await browser.runtime.sendMessage({ type: 'CHECK_LOCK' }); + useLayoutEffect(() => { + const checkLocked = async () => { + const status = await browser.runtime.sendMessage({ type: 'CHECK_LOCK' }); - dispatch(UIStore.lockedChanged(status.isLocked)); - }; + dispatch(UIStore.lockedChanged(status.isLocked)); + }; - void checkLocked(); - }, [locked]); + void checkLocked(); + }, [locked]); - useEffect(() => { - handleAutoLockNavigation(); - setIsLoadingLocalData(false); + useEffect(() => { + handleAutoLockNavigation(); + setIsLoadingLocalData(false); - handlePersistScreenRedirect(); - handleLedgerNavigation(); - }, [locked, profile.id()]); + handlePersistScreenRedirect(); + handleLedgerNavigation(); + }, [locked, profile.id()]); - useIdleTimer({ - throttle: 1000, - onAction: () => { - browser.runtime.sendMessage({ type: 'REGISTERED_ACTIVITY' }); - }, - disabled: locked, - }); + useIdleTimer({ + throttle: 1000, + onAction: () => { + browser.runtime.sendMessage({ type: 'REGISTERED_ACTIVITY' }); + }, + disabled: locked, + }); - const handleLedgerNavigation = () => { - const locationHref = window.location.href; + const handleLedgerNavigation = () => { + const locationHref = window.location.href; - if (!locationHref.includes('import_with_ledger')) return; - navigate('/ledger-import'); - }; + if (!locationHref.includes('import_with_ledger')) return; + navigate('/ledger-import'); + }; - const handlePersistScreenRedirect = () => { - if (!persistScreen) return; - navigate(persistScreen.screen); - }; + const handlePersistScreenRedirect = () => { + if (!persistScreen) return; + navigate(persistScreen.screen); + }; - const handleAutoLockNavigation = () => { - if (locked) { - navigate('/enter-password'); - return; - } + const handleAutoLockNavigation = () => { + if (locked) { + navigate('/enter-password'); + return; + } - if (isProfileReady && profile.wallets().count() === 0) { - navigate('/splash-screen'); - return; - } - }; + if (isProfileReady && profile.wallets().count() === 0) { + navigate('/splash-screen'); + return; + } + }; - return ( - - {children} - - ); + return ( + + {children} + + ); }; export default AutoUnlockWrapper; diff --git a/src/components/Logo.tsx b/src/components/Logo.tsx index c907630a..8c5a0375 100644 --- a/src/components/Logo.tsx +++ b/src/components/Logo.tsx @@ -3,14 +3,14 @@ import { Icon } from '@/shared/components/'; import { Theme } from '@/shared/theme'; type LogoProps = { - className?: string; + className?: string; } & ColorProps & - LayoutProps; + LayoutProps; export const Logo = ({ className, ...rest }: LogoProps) => { - return ; + return ; }; export const LogoIcon = ({ className, ...rest }: LogoProps) => { - return ; + return ; }; diff --git a/src/pages/Approve.tsx b/src/pages/Approve.tsx index 8d6d13e7..7ef5e553 100644 --- a/src/pages/Approve.tsx +++ b/src/pages/Approve.tsx @@ -17,99 +17,111 @@ import { assertIsUnlocked } from '@/lib/background/assertions'; import useThemeMode from '@/lib/hooks/useThemeMode'; export enum ApproveActionType { - SIGNATURE = 'signature', - TRANSACTION = 'transfer', - VOTE = 'vote', - UNVOTE = 'unvote', - SWITCH_VOTE = 'switch-vote', + SIGNATURE = 'signature', + TRANSACTION = 'transfer', + VOTE = 'vote', + UNVOTE = 'unvote', + SWITCH_VOTE = 'switch-vote', } const Approve = () => { - const location = useLocation(); - const { profile } = useProfileContext(); - const { connect } = useLedgerContext(); - const { getThemeColor } = useThemeMode(); - const abortReference = useRef(new AbortController()); - const [isModalOpen, setIsModalOpen] = useState(false); - const wallets = useAppSelector(WalletStore.selectWallets); + const location = useLocation(); + const { profile } = useProfileContext(); + const { connect } = useLedgerContext(); + const { getThemeColor } = useThemeMode(); + const abortReference = useRef(new AbortController()); + const [isModalOpen, setIsModalOpen] = useState(false); + const wallets = useAppSelector(WalletStore.selectWallets); - const walletData = wallets.find((wallet) => wallet.walletId === location.state.session.walletId)!; - const wallet = profile.wallets().findById(walletData?.walletId); + const walletData = wallets.find( + (wallet) => wallet.walletId === location.state.session.walletId, + )!; + const wallet = profile.wallets().findById(walletData?.walletId); - const locked = useAppSelector(UIStore.selectLocked); - assertIsUnlocked(locked); + const locked = useAppSelector(UIStore.selectLocked); + assertIsUnlocked(locked); - const approveWithLedger = async ( - profile: Contracts.IProfile, - wallet: Contracts.IReadWriteWallet, - ) => { - if (!isLedgerTransportSupported()) { - throw new Error('Ledger Transport is not supported!'); - } - setIsModalOpen(true); - await connect(profile, wallet.coinId(), wallet.networkId(), undefined, true); - }; + const approveWithLedger = async ( + profile: Contracts.IProfile, + wallet: Contracts.IReadWriteWallet, + ) => { + if (!isLedgerTransportSupported()) { + throw new Error('Ledger Transport is not supported!'); + } + setIsModalOpen(true); + await connect(profile, wallet.coinId(), wallet.networkId(), undefined, true); + }; - const closeLedgerScreen = () => { - setIsModalOpen(false); - }; + const closeLedgerScreen = () => { + setIsModalOpen(false); + }; - const hasVoted = wallet.voting().current().length > 0; - const getActionType = (actionType: ApproveActionType): ApproveActionType => { - switch (actionType) { - case ApproveActionType.VOTE: - return hasVoted ? ApproveActionType.SWITCH_VOTE : ApproveActionType.VOTE; - default: - return actionType; - } - }; + const hasVoted = wallet.voting().current().length > 0; + const getActionType = (actionType: ApproveActionType): ApproveActionType => { + switch (actionType) { + case ApproveActionType.VOTE: + return hasVoted ? ApproveActionType.SWITCH_VOTE : ApproveActionType.VOTE; + default: + return actionType; + } + }; - return ( - - {location.state?.type === ApproveActionType.SIGNATURE && ( - - )} - {location.state?.type === ApproveActionType.TRANSACTION && ( - - )} - {(location.state?.type === ApproveActionType.VOTE || - location.state?.type === ApproveActionType.UNVOTE) && ( - - )} - {isModalOpen && ( - {}} containerPadding='0' contentStyles={{minHeight: '100vh', margin: '0', backgroundColor: getThemeColor('warning600', 'warning400')}} activateFocusTrap={false} hideCloseButton > - - - )} - - ); + return ( + + {location.state?.type === ApproveActionType.SIGNATURE && ( + + )} + {location.state?.type === ApproveActionType.TRANSACTION && ( + + )} + {(location.state?.type === ApproveActionType.VOTE || + location.state?.type === ApproveActionType.UNVOTE) && ( + + )} + {isModalOpen && ( + {}} + containerPadding='0' + contentStyles={{ + minHeight: '100vh', + margin: '0', + backgroundColor: getThemeColor('warning600', 'warning400'), + }} + activateFocusTrap={false} + hideCloseButton + > + + + )} + + ); }; export default Approve; diff --git a/src/pages/Connect.tsx b/src/pages/Connect.tsx index 1466e51a..ef6de7b3 100644 --- a/src/pages/Connect.tsx +++ b/src/pages/Connect.tsx @@ -15,107 +15,110 @@ import ActionHeader from '@/shared/components/actions/ActionHeader'; import { useNotifyOnUnload } from '@/lib/hooks/useNotifyOnUnload'; const Connect = () => { - const location = useLocation(); - const dispatch = useAppDispatch(); - const sessions = useAppSelector(SessionStore.selectSessions); - const { profile } = useProfileContext(); - const primaryWalletId = useAppSelector(WalletStore.selectPrimaryWalletId); - const primaryWallet = primaryWalletId ? profile.wallets().findById(primaryWalletId) : undefined; - - const locked = useAppSelector(selectLocked); - assertIsUnlocked(locked); - - const reject = (message = 'Connection denied!') => { - browser.runtime.sendMessage({ - type: 'CONNECT_REJECT', - data: { - domain: location.state?.domain, - status: 'failed', - message, - tabId: location.state?.tabId, - }, - }); - }; - - const setSubmitted = useNotifyOnUnload(reject); - - const isAlreadyConnected = () => { - return Object.values(sessions).some((session) => { - return session.domain === location.state?.domain && session.walletId === primaryWallet?.id(); - }); - }; - - const onSubmit = async () => { - const loadingModal = { - isOpen: true, - isLoading: true, - completedMessage: 'Securely Connected', - loadingMessage: 'Connecting...', + const location = useLocation(); + const dispatch = useAppDispatch(); + const sessions = useAppSelector(SessionStore.selectSessions); + const { profile } = useProfileContext(); + const primaryWalletId = useAppSelector(WalletStore.selectPrimaryWalletId); + const primaryWallet = primaryWalletId ? profile.wallets().findById(primaryWalletId) : undefined; + + const locked = useAppSelector(selectLocked); + assertIsUnlocked(locked); + + const reject = (message = 'Connection denied!') => { + browser.runtime.sendMessage({ + type: 'CONNECT_REJECT', + data: { + domain: location.state?.domain, + status: 'failed', + message, + tabId: location.state?.tabId, + }, + }); }; - const isConnected = isAlreadyConnected(); - - dispatch(ModalStore.loadingModalUpdated(loadingModal)); - - if (!primaryWallet) { - reject('Wallet not found'); - return; - } - - if (isConnected) { - reject('Already connected!'); - return; - } - - if (primaryWallet) { - const sessionId = uuidv4(); - await dispatch( - SessionStore.sessionAdded({ - id: sessionId, - domain: location.state?.domain, - createdAt: new Date().toISOString(), - logo: location.state?.favicon, - walletId: primaryWallet.id(), - }), - ); - - await browser.runtime.sendMessage({ - type: 'CONNECT_RESOLVE', - data: { - domain: location.state?.domain, - status: 'success', - tabId: location.state?.tabId, - sessionId: sessionId, - }, - }); - - setSubmitted(); - - await browser.windows.remove(location.state?.windowId); - return; - } - }; - - const onCancel = async () => { - reject(); - await browser.windows.remove(location.state?.windowId); - }; - - return ( - - - - - - - - ); + const setSubmitted = useNotifyOnUnload(reject); + + const isAlreadyConnected = () => { + return Object.values(sessions).some((session) => { + return ( + session.domain === location.state?.domain && + session.walletId === primaryWallet?.id() + ); + }); + }; + + const onSubmit = async () => { + const loadingModal = { + isOpen: true, + isLoading: true, + completedMessage: 'Securely Connected', + loadingMessage: 'Connecting...', + }; + + const isConnected = isAlreadyConnected(); + + dispatch(ModalStore.loadingModalUpdated(loadingModal)); + + if (!primaryWallet) { + reject('Wallet not found'); + return; + } + + if (isConnected) { + reject('Already connected!'); + return; + } + + if (primaryWallet) { + const sessionId = uuidv4(); + await dispatch( + SessionStore.sessionAdded({ + id: sessionId, + domain: location.state?.domain, + createdAt: new Date().toISOString(), + logo: location.state?.favicon, + walletId: primaryWallet.id(), + }), + ); + + await browser.runtime.sendMessage({ + type: 'CONNECT_RESOLVE', + data: { + domain: location.state?.domain, + status: 'success', + tabId: location.state?.tabId, + sessionId: sessionId, + }, + }); + + setSubmitted(); + + await browser.windows.remove(location.state?.windowId); + return; + } + }; + + const onCancel = async () => { + reject(); + await browser.windows.remove(location.state?.windowId); + }; + + return ( + + + + + + + + ); }; export default Connect; diff --git a/src/pages/Connections.tsx b/src/pages/Connections.tsx index bdba966c..ab37b290 100644 --- a/src/pages/Connections.tsx +++ b/src/pages/Connections.tsx @@ -6,19 +6,19 @@ import { Container } from '@/shared/components'; import SubPageLayout from '@/components/settings/SubPageLayout'; const Connections = () => { - const sessions = useAppSelector(SessionStore.selectSessions); + const sessions = useAppSelector(SessionStore.selectSessions); - return ( - - {Object.values(sessions).length === 0 ? ( - - ) : ( - - - - )} - - ); + return ( + + {Object.values(sessions).length === 0 ? ( + + ) : ( + + + + )} + + ); }; export default Connections; diff --git a/src/pages/CreateWallet.tsx b/src/pages/CreateWallet.tsx index 2731c432..5614581c 100644 --- a/src/pages/CreateWallet.tsx +++ b/src/pages/CreateWallet.tsx @@ -2,13 +2,13 @@ import CreateNewWallet from '@/components/wallet/create'; import { Layout, FlexContainer } from '@/shared/components'; const CreateWallet = () => { - return ( - - - - - - ); + return ( + + + + + + ); }; export default CreateWallet; diff --git a/src/pages/EnterPassword.tsx b/src/pages/EnterPassword.tsx index a840489d..a6b44185 100644 --- a/src/pages/EnterPassword.tsx +++ b/src/pages/EnterPassword.tsx @@ -1,13 +1,13 @@ import { - Button, - Container, - Layout, - LockIcon, - FlexContainer, - PasswordInput, - Paragraph, - InternalLink, - Icon, + Button, + Container, + Layout, + LockIcon, + FlexContainer, + PasswordInput, + Paragraph, + InternalLink, + Icon, } from '@/shared/components'; import { useNavigate } from 'react-router-dom'; import React, { useState } from 'react'; @@ -20,115 +20,121 @@ import * as UIStore from '@/lib/store/ui'; import browser from 'webextension-polyfill'; const EnterPassword = () => { - const navigate = useNavigate(); - const dispatch = useAppDispatch(); - const { initProfile } = useProfileContext(); - const { onError } = useErrorHandlerContext(); - const [password, setPassword] = useState(''); - const [validationVariant, setValidationVariant] = useState('primary'); + const navigate = useNavigate(); + const dispatch = useAppDispatch(); + const { initProfile } = useProfileContext(); + const { onError } = useErrorHandlerContext(); + const [password, setPassword] = useState(''); + const [validationVariant, setValidationVariant] = useState('primary'); - const unlockExtension = async () => { - try { - const status = await browser.runtime.sendMessage({ - type: 'UNLOCK', - data: { password }, - }); + const unlockExtension = async () => { + try { + const status = await browser.runtime.sendMessage({ + type: 'UNLOCK', + data: { password }, + }); - if (status.isLocked) { - setValidationVariant('destructive'); - return; - } + if (status.isLocked) { + setValidationVariant('destructive'); + return; + } - await initProfile(); + await initProfile(); - setValidationVariant('primary'); + setValidationVariant('primary'); - dispatch(UIStore.lockedChanged(false)); + dispatch(UIStore.lockedChanged(false)); - navigate('/'); - } catch (error) { - onError(error); - } - }; + navigate('/'); + } catch (error) { + onError(error); + } + }; - const handlePasswordChange = (evt: React.ChangeEvent) => { - setPassword(evt.target.value); - if (validationVariant !== 'destructive') return; - setValidationVariant('primary'); - }; + const handlePasswordChange = (evt: React.ChangeEvent) => { + setPassword(evt.target.value); + if (validationVariant !== 'destructive') return; + setValidationVariant('primary'); + }; - const handleEnterKey = (evt: React.KeyboardEvent) => { - if (evt.key === 'Enter') { - unlockExtension(); - } - }; + const handleEnterKey = (evt: React.KeyboardEvent) => { + if (evt.key === 'Enter') { + unlockExtension(); + } + }; - return ( - - - - - - - - - Enter Password to Unlock - - - - - - - Forgot Password? - - - - - - ); + return ( + + + + + + + + + Enter Password to Unlock + + + + + + + Forgot Password? + + + + + + ); }; const StyledIconWrapper = styled(Container)` - width: 20px; - height: 20px; - position: absolute; - top: 50%; - right: 16px; - transform: translateY(-50%); + width: 20px; + height: 20px; + position: absolute; + top: 50%; + right: 16px; + transform: translateY(-50%); - ${({ theme }) => ` + ${({ theme }) => ` & #corner-down-left { stroke: ${theme.colors.primary500}; } diff --git a/src/pages/ForgotPassword.tsx b/src/pages/ForgotPassword.tsx index 5f368776..8e88a4c8 100644 --- a/src/pages/ForgotPassword.tsx +++ b/src/pages/ForgotPassword.tsx @@ -8,62 +8,63 @@ import browser from 'webextension-polyfill'; import { useProfileContext } from '@/lib/context/Profile'; const ForgotPassword = () => { - const logoutAll = useLogoutAll(); - const [lostPasswordAwareness, setLostPasswordAwareness] = useState(false); - const { onError } = useErrorHandlerContext(); + const logoutAll = useLogoutAll(); + const [lostPasswordAwareness, setLostPasswordAwareness] = useState(false); + const { onError } = useErrorHandlerContext(); - const { initProfile } = useProfileContext(); + const { initProfile } = useProfileContext(); - const { getThemeColor } = useThemeMode(); + const { getThemeColor } = useThemeMode(); - const handleLogout = async () => { - try { - await browser.runtime.sendMessage({ type: 'RESET' }); + const handleLogout = async () => { + try { + await browser.runtime.sendMessage({ type: 'RESET' }); - await logoutAll(); + await logoutAll(); - await initProfile(); - } catch (error) { - onError(error); - } - }; + await initProfile(); + } catch (error) { + onError(error); + } + }; - return ( - - - - Unfortunately there is no recovery method available other than resetting the extension and - re-importing your address(es). Ensure that you have your passphrase(s) saved. - + return ( + + + + Unfortunately there is no recovery method available other than resetting the + extension and re-importing your address(es). Ensure that you have your + passphrase(s) saved. + - - - + + + - - setLostPasswordAwareness(evt.target.checked)} - title='I am aware that resetting the extension will result in the loss of all data, including locally stored passphrases.' - /> - - - - - ); + + setLostPasswordAwareness(evt.target.checked)} + title='I am aware that resetting the extension will result in the loss of all data, including locally stored passphrases.' + /> + + + + + ); }; export default ForgotPassword; diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index ebe026cf..e8944810 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -1,11 +1,11 @@ import Balance from '@/components/wallet/Balance'; import { - Container, - FlexContainer, - Paragraph, - Icon, - Layout, - ExternalLink, + Container, + FlexContainer, + Paragraph, + Icon, + Layout, + ExternalLink, } from '@/shared/components'; import constants from '@/constants'; import { useEffect } from 'react'; @@ -15,97 +15,101 @@ import { usePrimaryWallet } from '@/lib/hooks/usePrimaryWallet'; import useThemeMode from '@/lib/hooks/useThemeMode'; const Home = () => { - const { convertedBalance } = useProfileContext(); + const { convertedBalance } = useProfileContext(); - const primaryWallet = usePrimaryWallet(); + const primaryWallet = usePrimaryWallet(); - const { getThemeColor } = useThemeMode(); + const { getThemeColor } = useThemeMode(); - useEffect(() => { - clearPersistScreenData(); - }, []); + useEffect(() => { + clearPersistScreenData(); + }, []); - return ( - - - - - - - - - - - Explorer - - - - + return ( + + + + + + + + + + + Explorer + + + + - - - {primaryWallet?.network().isTest() ? 'Faucet' : 'Exchanges'} - - - - - - - - - - Try Our Demo App Now! - - - - - - - - ); + + + {primaryWallet?.network().isTest() ? 'Faucet' : 'Exchanges'} + + + + + + + + + + Try Our Demo App Now! + + + + + + + + ); }; export default Home; diff --git a/src/pages/ImportWallet.tsx b/src/pages/ImportWallet.tsx index 401a0f2b..24253a18 100644 --- a/src/pages/ImportWallet.tsx +++ b/src/pages/ImportWallet.tsx @@ -2,19 +2,19 @@ import ImportNewWallet from '@/components/wallet/import'; import { Layout, FlexContainer } from '@/shared/components'; const ImportWallet = () => { - return ( - - - - - - ); + return ( + + + + + + ); }; export default ImportWallet; diff --git a/src/pages/ImportWithLedger.tsx b/src/pages/ImportWithLedger.tsx index 5cf4305c..6b92a6d2 100644 --- a/src/pages/ImportWithLedger.tsx +++ b/src/pages/ImportWithLedger.tsx @@ -23,150 +23,162 @@ import { useProfileContext } from '@/lib/context/Profile'; import useThemeMode from '@/lib/hooks/useThemeMode'; export type ImportWithLedger = { - wallets: LedgerData[]; - importedWallets: Contracts.IReadWriteWallet[]; - completed: boolean; - password: string; - passwordConfirm: string; + wallets: LedgerData[]; + importedWallets: Contracts.IReadWriteWallet[]; + completed: boolean; + password: string; + passwordConfirm: string; }; const ImportWithLedger = () => { - const { currentThemeMode } = useThemeMode(); - const { activeNetwork: network } = useNetwork(); - const { profile, initProfile } = useProfileContext(); - const { defaultCurrency } = useLocaleCurrency(); - const dispatch = useAppDispatch(); - const { error, removeErrors } = useLedgerContext(); - const { onError } = useErrorHandlerContext(); - const [steps, setSteps] = useState([ - { component: LedgerConnectionStep }, - { component: ImportWallets }, - ]); + const { currentThemeMode } = useThemeMode(); + const { activeNetwork: network } = useNetwork(); + const { profile, initProfile } = useProfileContext(); + const { defaultCurrency } = useLocaleCurrency(); + const dispatch = useAppDispatch(); + const { error, removeErrors } = useLedgerContext(); + const { onError } = useErrorHandlerContext(); + const [steps, setSteps] = useState([ + { component: LedgerConnectionStep }, + { component: ImportWallets }, + ]); - const formik = useFormik({ - initialValues: { - wallets: [], - importedWallets: [], - completed: false, - password: '', - passwordConfirm: '', - }, - onSubmit: async (values, formikHelpers) => { - const wallets = values.wallets.map((wallet) => { - return { - address: wallet.address, - network: network.id(), - coin: network.coin(), - path: wallet.path, - alias: getDefaultAlias({ - profile, - network, - }), - }; - }); - - const { error } = await browser.runtime.sendMessage({ - type: 'IMPORT_WALLETS', - data: { - currency: defaultCurrency, - password: values.password, - wallets, + const formik = useFormik({ + initialValues: { + wallets: [], + importedWallets: [], + completed: false, + password: '', + passwordConfirm: '', }, - }); + onSubmit: async (values, formikHelpers) => { + const wallets = values.wallets.map((wallet) => { + return { + address: wallet.address, + network: network.id(), + coin: network.coin(), + path: wallet.path, + alias: getDefaultAlias({ + profile, + network, + }), + }; + }); + + const { error } = await browser.runtime.sendMessage({ + type: 'IMPORT_WALLETS', + data: { + currency: defaultCurrency, + password: values.password, + wallets, + }, + }); - if (error) { - onError(error); - return; - } + if (error) { + onError(error); + return; + } - await initProfile(); + await initProfile(); - dispatch( - ModalStore.loadingModalUpdated({ - isOpen: true, - isLoading: false, - loadingMessage: 'Setting up your wallet', - completedMessage: 'Your wallet is ready!', - completedDescription: 'You can now open the extension and manage your addresses!', - }), - ); + dispatch( + ModalStore.loadingModalUpdated({ + isOpen: true, + isLoading: false, + loadingMessage: 'Setting up your wallet', + completedMessage: 'Your wallet is ready!', + completedDescription: + 'You can now open the extension and manage your addresses!', + }), + ); - formikHelpers.resetForm(); - }, - }); + formikHelpers.resetForm(); + }, + }); - useEffect(() => { - (async () => { - const { hasOnboarded } = await getLocalValues(); - if (!hasOnboarded) { - setSteps([...steps, { component: SetupPassword }]); - } - })(); - }, []); + useEffect(() => { + (async () => { + const { hasOnboarded } = await getLocalValues(); + if (!hasOnboarded) { + setSteps([...steps, { component: SetupPassword }]); + } + })(); + }, []); - return ( - -
- - - - - - - {error && ( - - - - - - {error && error.message ? error.message : error} - - - - - + return ( + +
+ + + + + + + {error && ( + + + + + + {error && error.message ? error.message : error} + + + + + + + + )} - - )} - - - ); + + ); }; const LedgerError = styled(Container)<{ themeMode: ThemeMode }>` - position: fixed; - left: 0; - bottom: 0; - width: 100%; - z-index: 15; - padding: 8px 0; - display: flex; - justify-content: center; - align-items: center; - background-color: ${(props) => - props.themeMode === ThemeMode.LIGHT ? props.theme.colors.error50 : 'rgba(255, 86, 74, 0.26)'}; - border-top: 1px solid - ${(props) => - props.themeMode === ThemeMode.LIGHT - ? props.theme.colors.error300 - : props.theme.colors.error500}; + position: fixed; + left: 0; + bottom: 0; + width: 100%; + z-index: 15; + padding: 8px 0; + display: flex; + justify-content: center; + align-items: center; + background-color: ${(props) => + props.themeMode === ThemeMode.LIGHT + ? props.theme.colors.error50 + : 'rgba(255, 86, 74, 0.26)'}; + border-top: 1px solid + ${(props) => + props.themeMode === ThemeMode.LIGHT + ? props.theme.colors.error300 + : props.theme.colors.error500}; `; export default ImportWithLedger; diff --git a/src/pages/InitialImportWallet.tsx b/src/pages/InitialImportWallet.tsx index 47465f63..451c63e9 100644 --- a/src/pages/InitialImportWallet.tsx +++ b/src/pages/InitialImportWallet.tsx @@ -8,63 +8,64 @@ import { useEffect } from 'react'; import { clearPersistScreenData } from '@/components/wallet/form-persist/helpers'; const InitialImportWallet = () => { - const navigate = useNavigate(); + const navigate = useNavigate(); - const { getThemeColor } = useThemeMode(); + const { getThemeColor } = useThemeMode(); - useEffect(() => { - clearPersistScreenData(); - }, []); + useEffect(() => { + clearPersistScreenData(); + }, []); - return ( - - - Select an option below that you would like to proceed with... - - navigate('/wallet/import')} - /> + return ( + + + Select an option below that you would like to proceed with... + + navigate('/wallet/import')} + /> - - ARK Connect requires the use of a chromium
based browser when using a Ledger. - - } - placement='bottom' - > -
- { - if (isFirefox) return; - browser.tabs.create({ - url: browser.runtime.getURL('/src/main.html?import_with_ledger'), - }); - window.close(); // Close extension popup as we navigate away - }} - color='primary' - /> -
-
-
- ); + + ARK Connect requires the use of a chromium
based browser when using a + Ledger. + + } + placement='bottom' + > +
+ { + if (isFirefox) return; + browser.tabs.create({ + url: browser.runtime.getURL('/src/main.html?import_with_ledger'), + }); + window.close(); // Close extension popup as we navigate away + }} + color='primary' + /> +
+
+
+ ); }; export default InitialImportWallet; diff --git a/src/pages/Logout.tsx b/src/pages/Logout.tsx index abc03d87..2bb7a3bf 100644 --- a/src/pages/Logout.tsx +++ b/src/pages/Logout.tsx @@ -14,181 +14,181 @@ import useThemeMode from '@/lib/hooks/useThemeMode'; import SubPageLayout from '@/components/settings/SubPageLayout'; const Logout = () => { - const dispatch = useAppDispatch(); - const navigate = useNavigate(); - const location = useLocation(); - const { initProfile, profile } = useProfileContext(); - const [password, setPassword] = useState(''); - const [validationVariant, setValidationVariant] = useState('primary'); - const { getThemeColor } = useThemeMode(); - const sessions = useAppSelector(SessionStore.selectSessions); - const { onError } = useErrorHandlerContext(); - const walletsIds = useAppSelector(WalletStore.selectWalletsIds); - - const walletsToLogout = location.state; - - const walletId: string | undefined = - walletsToLogout && walletsToLogout.length === 1 ? walletsToLogout[0] : walletsIds[0]; - - const wallet = walletId !== undefined ? profile.wallets().findById(walletId) : undefined; - - const logoutWallet = async () => { - try { - if (!(await isValidPassword(password))) { - setValidationVariant('destructive'); - return; - } - setValidationVariant('primary'); - if (!location.state) return; - - const walletsToDelete = location.state; - - location.state.forEach(async (walletId: string) => { - Object.values(sessions).map((session) => { - if (session.walletId !== walletId) return; - ExtensionEvents({ profile }).disconnect(session.domain); - - dispatch(SessionStore.sessionRemoved([session.id])); + const dispatch = useAppDispatch(); + const navigate = useNavigate(); + const location = useLocation(); + const { initProfile, profile } = useProfileContext(); + const [password, setPassword] = useState(''); + const [validationVariant, setValidationVariant] = useState('primary'); + const { getThemeColor } = useThemeMode(); + const sessions = useAppSelector(SessionStore.selectSessions); + const { onError } = useErrorHandlerContext(); + const walletsIds = useAppSelector(WalletStore.selectWalletsIds); + + const walletsToLogout = location.state; + + const walletId: string | undefined = + walletsToLogout && walletsToLogout.length === 1 ? walletsToLogout[0] : walletsIds[0]; + + const wallet = walletId !== undefined ? profile.wallets().findById(walletId) : undefined; + + const logoutWallet = async () => { + try { + if (!(await isValidPassword(password))) { + setValidationVariant('destructive'); + return; + } + setValidationVariant('primary'); + if (!location.state) return; + + const walletsToDelete = location.state; + + location.state.forEach(async (walletId: string) => { + Object.values(sessions).map((session) => { + if (session.walletId !== walletId) return; + ExtensionEvents({ profile }).disconnect(session.domain); + + dispatch(SessionStore.sessionRemoved([session.id])); + }); + }); + + const { error } = await browser.runtime.sendMessage({ + type: 'REMOVE_WALLETS', + data: { + password, + walletIds: walletsToDelete, + }, + }); + + if (error) { + onError(error); + return; + } + + await dispatch(WalletStore.walletRemoved(location.state)); + + await initProfile(); + navigate('/'); + } catch (error) { + onError(error); + } + }; + + const handlePasswordChange = (evt: React.ChangeEvent) => { + setPassword(evt.target.value); + if (validationVariant !== 'destructive') return; + setValidationVariant('primary'); + }; + + const handleEnterKey = async (evt: React.KeyboardEvent) => { + if (evt.key === 'Enter') { + await logoutWallet(); + } + }; + + const getAddressesType = () => { + let hasLedger = false; + let hasPassphrase = false; + let text = ''; + + walletsToLogout.some((walletId: string) => { + const wallet = profile.wallets().findById(walletId); + if (wallet.isLedger()) { + hasLedger = true; + } else { + hasPassphrase = true; + } + + return hasLedger && hasPassphrase; }); - }); - - const { error } = await browser.runtime.sendMessage({ - type: 'REMOVE_WALLETS', - data: { - password, - walletIds: walletsToDelete, - }, - }); - - if (error) { - onError(error); - return; - } - - await dispatch(WalletStore.walletRemoved(location.state)); - - await initProfile(); - navigate('/'); - } catch (error) { - onError(error); - } - }; - - const handlePasswordChange = (evt: React.ChangeEvent) => { - setPassword(evt.target.value); - if (validationVariant !== 'destructive') return; - setValidationVariant('primary'); - }; - - const handleEnterKey = async (evt: React.KeyboardEvent) => { - if (evt.key === 'Enter') { - await logoutWallet(); - } - }; - - const getAddressesType = () => { - let hasLedger = false; - let hasPassphrase = false; - let text = ''; - - walletsToLogout.some((walletId: string) => { - const wallet = profile.wallets().findById(walletId); - if (wallet.isLedger()) { - hasLedger = true; - } else { - hasPassphrase = true; - } - - return hasLedger && hasPassphrase; - }); - - if (hasLedger && hasPassphrase) { - text = 'a passphrase or a Ledger device'; - } else if (hasLedger) { - text = 'a Ledger device'; - } else { - text = 'a passphrase'; - } - - return text; - }; - - return ( - 1 ? 'es' : ''}`} - hideCloseButton={false} - > - - 1 ? 'es' : ''}`} + hideCloseButton={false} > - {walletsToLogout && walletsToLogout.length > 1 ? ( - - Are you sure you want to remove{' '} - - {walletsToLogout.length} addresses? - {' '} - {`You won’t be able to login again without ${getAddressesType()}.`} - - ) : ( - `Are you sure you want to remove this address? You will be unable to log in again using this address without ${ - wallet?.isLedger() ? 'a Ledger device.' : 'a passphrase.' - }` - )} - - - - - - - - - Enter Password - - - - - - - - - - - ); + + + {walletsToLogout && walletsToLogout.length > 1 ? ( + + Are you sure you want to remove{' '} + + {walletsToLogout.length} addresses? + {' '} + {`You won’t be able to login again without ${getAddressesType()}.`} + + ) : ( + `Are you sure you want to remove this address? You will be unable to log in again using this address without ${ + wallet?.isLedger() ? 'a Ledger device.' : 'a passphrase.' + }` + )} + + + + + + + + + Enter Password + + + + + + + + + + + ); }; export default Logout; diff --git a/src/pages/Onboarding.tsx b/src/pages/Onboarding.tsx index c1d35d33..490a608e 100644 --- a/src/pages/Onboarding.tsx +++ b/src/pages/Onboarding.tsx @@ -1,14 +1,14 @@ import React, { useState, useEffect } from 'react'; import { - Container, - ProgressBar, - FingerPrintIcon, - ControlConnectionsIcon, - TransactionsPassphraseIcon, - Heading, - FlexContainer, - Button, - Header, + Container, + ProgressBar, + FingerPrintIcon, + ControlConnectionsIcon, + TransactionsPassphraseIcon, + Heading, + FlexContainer, + Button, + Header, } from '@/shared/components'; import styled, { keyframes } from 'styled-components'; import { useLocation, useNavigate } from 'react-router-dom'; @@ -16,76 +16,76 @@ import { useProfileContext } from '@/lib/context/Profile'; import useLogoutAll from '@/lib/hooks/useLogoutAll'; type OnboardingScreen = { - id: number; - illustration: React.ReactNode; - heading: React.ReactNode; + id: number; + illustration: React.ReactNode; + heading: React.ReactNode; }; const Onboarding = () => { - const { initProfile } = useProfileContext(); - const logoutAll = useLogoutAll(); - const navigate = useNavigate(); - const { state } = useLocation(); + const { initProfile } = useProfileContext(); + const logoutAll = useLogoutAll(); + const navigate = useNavigate(); + const { state } = useLocation(); - const [activeOnboardingScreen, setActiveOnboardingScreen] = useState(0); + const [activeOnboardingScreen, setActiveOnboardingScreen] = useState(0); - useEffect(() => { - (async () => { - if (state?.initProfile) { - await logoutAll(); + useEffect(() => { + (async () => { + if (state?.initProfile) { + await logoutAll(); - await initProfile(); - } - })(); - const interval = setInterval(() => { - setActiveOnboardingScreen((prevIndex) => (prevIndex + 1) % 3); - }, 5000); - return () => { - clearInterval(interval); - }; - }, []); + await initProfile(); + } + })(); + const interval = setInterval(() => { + setActiveOnboardingScreen((prevIndex) => (prevIndex + 1) % 3); + }, 5000); + return () => { + clearInterval(interval); + }; + }, []); - return ( - -
- - - {onboardingScreens.map((screen, index) => ( - index - ? 'isPrev' - : 'isNext' - }`} - $flexVariant='columnCenter' - gridGap='24px' - paddingX='36' - > - - {screen.illustration} - {screen.heading} + return ( + +
+ + + {onboardingScreens.map((screen, index) => ( + index + ? 'isPrev' + : 'isNext' + }`} + $flexVariant='columnCenter' + gridGap='24px' + paddingX='36' + > + + {screen.illustration} + {screen.heading} + + + ))} + + + + - - ))} - - - - - - - ); + + ); }; const fadeIn = keyframes` @@ -99,64 +99,64 @@ const fadeIn = keyframes` `; const FadeInLayout = styled(Container)` - animation: ${fadeIn} 1s ease-in-out; + animation: ${fadeIn} 1s ease-in-out; `; const SlidingItem = styled(FlexContainer)` - width: 100%; - position: absolute; - top: 70px; - left: 0; - opacity: 1; - transition: - transform 1s ease-in-out, - opacity 1s ease-in-out; - - &.isActive { - transform: translateX(0); + width: 100%; + position: absolute; + top: 70px; + left: 0; opacity: 1; - } + transition: + transform 1s ease-in-out, + opacity 1s ease-in-out; - &.isNext { - transform: translateX(100%); - opacity: 0; - } + &.isActive { + transform: translateX(0); + opacity: 1; + } - &.isPrev { - transform: translateX(-100%); - opacity: 0; - } + &.isNext { + transform: translateX(100%); + opacity: 0; + } + + &.isPrev { + transform: translateX(-100%); + opacity: 0; + } `; const onboardingScreens: OnboardingScreen[] = [ - { - id: 1, - illustration: , - heading: ( - - Easily & securely log in to
your favorite web3 apps. -
- ), - }, - { - id: 2, - illustration: , - heading: ( - - Control your identity with our
session management feature. -
- ), - }, - { - id: 3, - illustration: , - heading: ( - - Sign transactions and
- perform on-chain actions. -
- ), - }, + { + id: 1, + illustration: , + heading: ( + + Easily & securely log in to
your favorite web3 apps. +
+ ), + }, + { + id: 2, + illustration: , + heading: ( + + Control your identity with our
session management feature. +
+ ), + }, + { + id: 3, + illustration: , + heading: ( + + Sign transactions and
+ perform on-chain actions. +
+ ), + }, ]; export default Onboarding; diff --git a/src/pages/SplashScreen.tsx b/src/pages/SplashScreen.tsx index aebd4f29..77f39f95 100644 --- a/src/pages/SplashScreen.tsx +++ b/src/pages/SplashScreen.tsx @@ -4,38 +4,38 @@ import { Navigate } from 'react-router-dom'; import styled, { keyframes } from 'styled-components'; const SplashScreen = () => { - const [animationFinished, setAnimationFinished] = useState(false); - - useEffect(() => { - const animationTimeout = setTimeout(() => { - setAnimationFinished(true); - }, 3000); - - return () => { - clearTimeout(animationTimeout); - }; - }, []); - - if (animationFinished) return ; - - return ( - - - - - - - - - - - ); + const [animationFinished, setAnimationFinished] = useState(false); + + useEffect(() => { + const animationTimeout = setTimeout(() => { + setAnimationFinished(true); + }, 3000); + + return () => { + clearTimeout(animationTimeout); + }; + }, []); + + if (animationFinished) return ; + + return ( + + + + + + + + + + + ); }; const fadeInAndTransform = keyframes` @@ -93,51 +93,51 @@ const translateUp = keyframes` `; const SplashScreenWrapper = styled.div` - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - position: fixed; - top: 0; - left: 0; - height: 600px; - width: 100%; - background-color: ${({ theme }) => theme.colors.primary700}; - animation: ${slideUp} 1.2s ease-in-out 1.8s forwards; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + position: fixed; + top: 0; + left: 0; + height: 600px; + width: 100%; + background-color: ${({ theme }) => theme.colors.primary700}; + animation: ${slideUp} 1.2s ease-in-out 1.8s forwards; `; const AnimatedContent = styled.div` - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; - grid-gap: 16px; - animation: - ${fadeInAndTransform} 0.8s ease-in-out forwards, - ${scale} 0.4s ease-in-out 1s forwards; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + grid-gap: 16px; + animation: + ${fadeInAndTransform} 0.8s ease-in-out forwards, + ${scale} 0.4s ease-in-out 1s forwards; `; const ContainersWrapper = styled.div` - position: absolute; - bottom: 0; - width: 100%; - display: flex; - flex-direction: column; - transform: translateY(100%); - animation: ${translateUp} 0.7s ease-in-out 1.8s forwards; + position: absolute; + bottom: 0; + width: 100%; + display: flex; + flex-direction: column; + transform: translateY(100%); + animation: ${translateUp} 0.7s ease-in-out 1.8s forwards; `; const GreenContainer = styled.div` - width: 100%; - height: 200px; - background-color: ${({ theme }) => theme.colors.primary650}; - animation: ${decreaseHeight} 0.5s ease-in-out 2s forwards; + width: 100%; + height: 200px; + background-color: ${({ theme }) => theme.colors.primary650}; + animation: ${decreaseHeight} 0.5s ease-in-out 2s forwards; `; const WhiteContainer = styled.div` - width: 100%; - height: 60px; - background-color: ${({ theme }) => theme.colors.base}; + width: 100%; + height: 60px; + background-color: ${({ theme }) => theme.colors.base}; `; export default SplashScreen; diff --git a/src/pages/TransactionApproved.tsx b/src/pages/TransactionApproved.tsx index 552d5a1d..bd84e947 100644 --- a/src/pages/TransactionApproved.tsx +++ b/src/pages/TransactionApproved.tsx @@ -10,75 +10,80 @@ import { useEffect } from 'react'; import { useLocation } from 'react-router-dom'; const TransactionApproved = () => { - const { state } = useLocation(); - const { profile } = useProfileContext(); - const { env } = useEnvironmentContext(); - const { session } = state; + const { state } = useLocation(); + const { profile } = useProfileContext(); + const { env } = useEnvironmentContext(); + const { session } = state; - const onClose = async () => { - await removeWindowInstance(state?.windowId); - }; + const onClose = async () => { + await removeWindowInstance(state?.windowId); + }; - useEffect(() => { - profile.sync(); - env.persist(); - }, []); + useEffect(() => { + profile.sync(); + env.persist(); + }, []); - return ( - - - - - - - - Transaction Approved - - - - - - - - - View transaction on ARKScan - - - + position='fixed' + top='0' + left='0' + zIndex='10' + backgroundColor='primaryBackground' + $flexVariant='columnCenter' + > + + + + + + + Transaction Approved + + + + + + + + + View transaction on ARKScan + + + + + - - - ); + ); }; export default TransactionApproved; diff --git a/src/pages/VoteApproved.tsx b/src/pages/VoteApproved.tsx index b4a693cc..f6ddf9bf 100644 --- a/src/pages/VoteApproved.tsx +++ b/src/pages/VoteApproved.tsx @@ -9,88 +9,88 @@ import RequestedBy from '@/shared/components/actions/RequestedBy'; import { useProfileContext } from '@/lib/context/Profile'; const VoteApproved = () => { - const { state } = useLocation(); - const { profile } = useProfileContext(); - const { session } = state; - const wallet = profile.wallets().findById(session.walletId); + const { state } = useLocation(); + const { profile } = useProfileContext(); + const { session } = state; + const wallet = profile.wallets().findById(session.walletId); - const onClose = async () => { - await removeWindowInstance(state?.windowId); - }; - - const getTitle = () => { - switch(state?.type) { - case ApproveActionType.VOTE: - return 'Vote Approved'; - case ApproveActionType.UNVOTE: - return 'Unvote Approved'; - case ApproveActionType.SWITCH_VOTE: - return 'Switch Vote Approved'; - default: - return ''; - } - }; + const onClose = async () => { + await removeWindowInstance(state?.windowId); + }; - return ( - - - + const getTitle = () => { + switch (state?.type) { + case ApproveActionType.VOTE: + return 'Vote Approved'; + case ApproveActionType.UNVOTE: + return 'Unvote Approved'; + case ApproveActionType.SWITCH_VOTE: + return 'Switch Vote Approved'; + default: + return ''; + } + }; + + return ( - - - - {getTitle()} - - - - - - - - - View transaction on ARKScan - - - + position='fixed' + top='0' + left='0' + zIndex='10' + backgroundColor='primaryBackground' + $flexVariant='columnCenter' + > + + + + + + + {getTitle()} + + + + + + + + + View transaction on ARKScan + + + + + - - - ); + ); }; export default VoteApproved; diff --git a/src/pages/WalletNotFound.tsx b/src/pages/WalletNotFound.tsx index 3bd40f2f..231fef4c 100644 --- a/src/pages/WalletNotFound.tsx +++ b/src/pages/WalletNotFound.tsx @@ -1,36 +1,36 @@ import { FlexContainer, Paragraph, EmptyConnectionsIcon, Layout } from '@/shared/components'; const WalletNotFound = () => { - return ( - - - - - - You don't have any wallet imported in ARK Connect!
- Please create or import a wallet first! -
-
-
-
- ); + return ( + + + + + + You don't have any wallet imported in ARK Connect!
+ Please create or import a wallet first! +
+
+
+
+ ); }; export default WalletNotFound; diff --git a/src/routing/index.ts b/src/routing/index.ts index 1846d92a..61c51a53 100644 --- a/src/routing/index.ts +++ b/src/routing/index.ts @@ -26,145 +26,145 @@ import ImportWithLedger from '@/pages/ImportWithLedger'; import { AddressSettings } from '@/components/wallet/AddressSettings'; type RouteData = { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - Component: (...props: any[]) => JSX.Element; - title: string; - path: string; - exact?: boolean; - children?: RouteData[]; - reRoute?: string; - icon?: IconDefinition; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + Component: (...props: any[]) => JSX.Element; + title: string; + path: string; + exact?: boolean; + children?: RouteData[]; + reRoute?: string; + icon?: IconDefinition; }; const routes: RouteData[] = [ - { - Component: Home, - path: '/', - title: 'Home', - icon: 'home', - exact: true, - }, - { - Component: Connections, - path: '/connections', - title: 'Connections', - icon: 'connections', - }, - { - Component: CreateOrImport, - path: '/create-import-address', - title: 'Create or Import Address', - }, - { - Component: ChangeLocalPassword, - path: '/local-password', - title: 'Change Local Password', - }, - { - Component: AutoLockTimer, - path: '/autolock-timer', - title: 'Auto Lock Timer', - }, - { - Component: ChangeLocalCurrency, - path: '/local-currency', - title: 'Change Local Currency', - }, - { - Component: AboutARK, - path: '/about', - title: 'About ARK Connect', - }, - { - Component: Logout, - path: '/logout', - title: 'Remove Address', - }, - { - Component: SplashScreen, - path: '/splash-screen', - title: 'Splash Screen', - }, - { - Component: Onboarding, - path: '/onboarding', - title: 'Onboarding', - }, - { - Component: Approve, - path: '/approve', - title: 'Approve', - }, - { - Component: Connect, - path: '/connect', - title: 'Connect', - }, - { - Component: InitialImportWallet, - path: '/wallet', - title: 'Import Wallet Initial', - }, - { - Component: ImportWithLedger, - path: '/ledger-import', - title: 'Import with Ledger', - }, - { - Component: CreateWallet, - path: '/wallet/create', - title: 'Create Wallet', - }, - { - Component: ImportWallet, - path: '/wallet/import', - title: 'Import Wallet', - }, - { - Component: EnterPassword, - path: '/enter-password', - title: 'Enter Password', - }, - { - Component: EditAddressName, - path: '/edit-address-name/:walletId', - title: 'Edit Address Name', - }, - { - Component: ViewSensitiveInfo, - path: '/view-sensitive-info/:walletId/:type', - title: 'Show Private Key', - }, - { - Component: ForgotPassword, - path: '/forgot-password', - title: 'Forgot Password', - }, - { - Component: MultipleWalletLogout, - path: '/multiple-wallet-logout', - title: 'Multiple Wallet Logout', - }, - { - Component: TransactionApproved, - path: '/transaction/success', - title: 'Transaction Approved', - }, - { - Component: VoteApproved, - path: '/vote/success', - title: 'Vote Approved', - }, - { - Component: WalletNotFound, - path: '/wallet/not-found', - title: 'Wallet Not Found', - }, - { - Component: AddressSettings, - path: '/address/settings', - title: 'Address Settings', - }, + { + Component: Home, + path: '/', + title: 'Home', + icon: 'home', + exact: true, + }, + { + Component: Connections, + path: '/connections', + title: 'Connections', + icon: 'connections', + }, + { + Component: CreateOrImport, + path: '/create-import-address', + title: 'Create or Import Address', + }, + { + Component: ChangeLocalPassword, + path: '/local-password', + title: 'Change Local Password', + }, + { + Component: AutoLockTimer, + path: '/autolock-timer', + title: 'Auto Lock Timer', + }, + { + Component: ChangeLocalCurrency, + path: '/local-currency', + title: 'Change Local Currency', + }, + { + Component: AboutARK, + path: '/about', + title: 'About ARK Connect', + }, + { + Component: Logout, + path: '/logout', + title: 'Remove Address', + }, + { + Component: SplashScreen, + path: '/splash-screen', + title: 'Splash Screen', + }, + { + Component: Onboarding, + path: '/onboarding', + title: 'Onboarding', + }, + { + Component: Approve, + path: '/approve', + title: 'Approve', + }, + { + Component: Connect, + path: '/connect', + title: 'Connect', + }, + { + Component: InitialImportWallet, + path: '/wallet', + title: 'Import Wallet Initial', + }, + { + Component: ImportWithLedger, + path: '/ledger-import', + title: 'Import with Ledger', + }, + { + Component: CreateWallet, + path: '/wallet/create', + title: 'Create Wallet', + }, + { + Component: ImportWallet, + path: '/wallet/import', + title: 'Import Wallet', + }, + { + Component: EnterPassword, + path: '/enter-password', + title: 'Enter Password', + }, + { + Component: EditAddressName, + path: '/edit-address-name/:walletId', + title: 'Edit Address Name', + }, + { + Component: ViewSensitiveInfo, + path: '/view-sensitive-info/:walletId/:type', + title: 'Show Private Key', + }, + { + Component: ForgotPassword, + path: '/forgot-password', + title: 'Forgot Password', + }, + { + Component: MultipleWalletLogout, + path: '/multiple-wallet-logout', + title: 'Multiple Wallet Logout', + }, + { + Component: TransactionApproved, + path: '/transaction/success', + title: 'Transaction Approved', + }, + { + Component: VoteApproved, + path: '/vote/success', + title: 'Vote Approved', + }, + { + Component: WalletNotFound, + path: '/wallet/not-found', + title: 'Wallet Not Found', + }, + { + Component: AddressSettings, + path: '/address/settings', + title: 'Address Settings', + }, ]; export default routes; diff --git a/src/tests/helpers.ts b/src/tests/helpers.ts index 50c26541..09ba35d5 100644 --- a/src/tests/helpers.ts +++ b/src/tests/helpers.ts @@ -5,55 +5,55 @@ import fixtureData from '@/tests/fixtures/env/storage.json'; import TestingPasswords from '@/tests/fixtures/env/testing-passwords.json'; export const bootEnvironmentWithProfileFixtures = async ({ - env, - shouldRestoreDefaultProfile = false, + env, + shouldRestoreDefaultProfile = false, }: { - env: Environment; - shouldRestoreDefaultProfile?: boolean; + env: Environment; + shouldRestoreDefaultProfile?: boolean; }) => { - const ids = Object.keys(fixtureData.profiles); - const fixtureProfiles: any = fixtureData.profiles; - const storageData: StorageData = { data: {}, profiles: {} }; - - for (const id of ids) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - //@ts-ignore - const password: string = TestingPasswords?.profiles[id]?.password; - - const profileData = { id, ...fixtureProfiles[id] }; - let data = Base64.encode(JSON.stringify(profileData)); - - if (password) { - // Re-import profile as passwordless, reset password and dump encrypted data. - delete profileData.settings.password; - - const passwordProtectedProfile = await env.profiles().import(data); - await env.profiles().restore(passwordProtectedProfile); - passwordProtectedProfile.auth().setPassword(password); - - data = await env.profiles().export(passwordProtectedProfile, undefined, password); + const ids = Object.keys(fixtureData.profiles); + const fixtureProfiles: any = fixtureData.profiles; + const storageData: StorageData = { data: {}, profiles: {} }; + + for (const id of ids) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + //@ts-ignore + const password: string = TestingPasswords?.profiles[id]?.password; + + const profileData = { id, ...fixtureProfiles[id] }; + let data = Base64.encode(JSON.stringify(profileData)); + + if (password) { + // Re-import profile as passwordless, reset password and dump encrypted data. + delete profileData.settings.password; + + const passwordProtectedProfile = await env.profiles().import(data); + await env.profiles().restore(passwordProtectedProfile); + passwordProtectedProfile.auth().setPassword(password); + + data = await env.profiles().export(passwordProtectedProfile, undefined, password); + } + + storageData.profiles[id] = { + data, + id, + name: fixtureProfiles[id].settings.NAME, + password: fixtureProfiles[id].settings.PASSWORD, + }; } - storageData.profiles[id] = { - data, - id, - name: fixtureProfiles[id].settings.NAME, - password: fixtureProfiles[id].settings.PASSWORD, - }; - } - - await env.verify(storageData); - await env.boot(); + await env.verify(storageData); + await env.boot(); - // await env.profiles().restore(env.profiles().last(), "password"); + // await env.profiles().restore(env.profiles().last(), "password"); - if (shouldRestoreDefaultProfile) { - const profile = env.profiles().first(); - await env.profiles().restore(profile); + if (shouldRestoreDefaultProfile) { + const profile = env.profiles().first(); + await env.profiles().restore(profile); - await profile.sync(); - } + await profile.sync(); + } }; export const isUnit = () => - !!['true', '1'].includes(process.env.REACT_APP_IS_UNIT?.toLowerCase() || ''); + !!['true', '1'].includes(process.env.REACT_APP_IS_UNIT?.toLowerCase() || ''); diff --git a/src/tests/utils.tsx b/src/tests/utils.tsx index dfae0425..a8020fef 100644 --- a/src/tests/utils.tsx +++ b/src/tests/utils.tsx @@ -2,10 +2,10 @@ import { AppWrapper, MainWrapper } from '@/App'; import { render as testingLibraryRender } from '@testing-library/react'; const Wrapper = ({ children }: { children?: React.ReactNode }) => ( - - {children} - + + {children} + ); export const render = (component: React.ReactElement, options: any = {}) => - testingLibraryRender(component, { wrapper: Wrapper, ...options }); + testingLibraryRender(component, { wrapper: Wrapper, ...options });