From a4ca94ccefb0c4e10ec1817870d2e225d044c90f Mon Sep 17 00:00:00 2001 From: Fouad Date: Mon, 13 Feb 2023 10:26:37 +0000 Subject: [PATCH 1/9] dont force user to copy mnemonic (#2992) * dont force user to copy mnemonic * add title to mnemonic page --- .../Accounts/modals/AddAccountModal.tsx | 9 ++-- .../Accounts/modals/MnemonicModal.tsx | 5 +- nym-wallet/src/components/Mnemonic.tsx | 54 ++++++++++--------- nym-wallet/src/pages/auth/index.tsx | 9 ---- .../src/pages/auth/pages/create-mnemonic.tsx | 14 +++-- nym-wallet/src/pages/index.ts | 1 - 6 files changed, 39 insertions(+), 53 deletions(-) delete mode 100644 nym-wallet/src/pages/auth/index.tsx diff --git a/nym-wallet/src/components/Accounts/modals/AddAccountModal.tsx b/nym-wallet/src/components/Accounts/modals/AddAccountModal.tsx index 61d6f7b9e5..ac2132e636 100644 --- a/nym-wallet/src/components/Accounts/modals/AddAccountModal.tsx +++ b/nym-wallet/src/components/Accounts/modals/AddAccountModal.tsx @@ -10,7 +10,6 @@ import { TextField, Typography, } from '@mui/material'; -import { useClipboard } from 'use-clipboard-copy'; import { createMnemonic, validateMnemonic } from 'src/requests'; import { Console } from 'src/utils/console'; import { AccountsContext } from 'src/context'; @@ -30,16 +29,16 @@ const importAccountSteps = [ ]; const MnemonicStep = ({ mnemonic, onNext, onBack }: { mnemonic: string; onNext: () => void; onBack: () => void }) => { - const { copy, copied } = useClipboard({ copiedTimeout: 5000 }); + const [confirmed, setConfirmed] = useState(false); return ( - + - diff --git a/nym-wallet/src/components/Accounts/modals/MnemonicModal.tsx b/nym-wallet/src/components/Accounts/modals/MnemonicModal.tsx index c9ea2202a3..e2d6e02c2a 100644 --- a/nym-wallet/src/components/Accounts/modals/MnemonicModal.tsx +++ b/nym-wallet/src/components/Accounts/modals/MnemonicModal.tsx @@ -11,15 +11,12 @@ import { Typography, } from '@mui/material'; import { AccountsContext } from 'src/context'; -import { useClipboard } from 'use-clipboard-copy'; import { Mnemonic, PasswordInput } from 'src/components'; import { StyledBackButton } from 'src/components/StyledBackButton'; export const MnemonicModal = () => { const [password, setPassword] = useState(''); - const { copy, copied } = useClipboard({ copiedTimeout: 5000 }); - const { dialogToDisplay, setDialogToDisplay, @@ -72,7 +69,7 @@ export const MnemonicModal = () => { /> ) : ( - + )} diff --git a/nym-wallet/src/components/Mnemonic.tsx b/nym-wallet/src/components/Mnemonic.tsx index d445172e9a..ac222d2cef 100644 --- a/nym-wallet/src/components/Mnemonic.tsx +++ b/nym-wallet/src/components/Mnemonic.tsx @@ -1,23 +1,33 @@ import React from 'react'; -import { Button, Stack, TextField, Typography } from '@mui/material'; -import { Check, ContentCopySharp } from '@mui/icons-material'; +import { Checkbox, FormControlLabel, Stack, TextField, Typography } from '@mui/material'; import { Warning } from './Warning'; +import { Title } from 'src/pages/auth/components/heading'; +import { Box } from '@mui/system'; export const Mnemonic = ({ mnemonic, - copied, - handleCopy, + confirmed, + withTitle, + handleConfirmed, }: { mnemonic: string; - copied: boolean; - handleCopy: (text?: string) => void; + confirmed?: boolean; + withTitle?: boolean; + handleConfirmed?: (confirmed: boolean) => void; }) => ( - - - - Below is your 24 word mnemonic, make sure to store it in a safe place for accessing your wallet in the future - - + + {withTitle && ( + + + </Box> + )} + <Box sx={{ pb: 2 }}> + <Warning> + <Typography sx={{ textAlign: 'center' }}> + Below is your 24 word mnemonic, make sure to store it in a safe place for accessing your wallet in the future + </Typography> + </Warning> + </Box> <TextField label="Mnemonic" type="input" @@ -38,19 +48,11 @@ export const Mnemonic = ({ }} /> - <Button - color="inherit" - disableElevation - size="large" - onClick={() => { - handleCopy(mnemonic); - }} - sx={{ - width: 250, - }} - endIcon={!copied ? <ContentCopySharp /> : <Check color="success" />} - > - Copy mnemonic - </Button> + {handleConfirmed && ( + <FormControlLabel + label="I saved my mnemonic" + control={<Checkbox checked={confirmed} onChange={(_, checked) => handleConfirmed(checked)} />} + /> + )} </Stack> ); diff --git a/nym-wallet/src/pages/auth/index.tsx b/nym-wallet/src/pages/auth/index.tsx deleted file mode 100644 index 598566db6f..0000000000 --- a/nym-wallet/src/pages/auth/index.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; -import { AuthProvider } from 'src/context'; -import { AuthRoutes } from 'src/routes/auth'; - -export const Auth = () => ( - <AuthProvider> - <AuthRoutes /> - </AuthProvider> -); diff --git a/nym-wallet/src/pages/auth/pages/create-mnemonic.tsx b/nym-wallet/src/pages/auth/pages/create-mnemonic.tsx index 2809d3b3b1..e3ab373d55 100644 --- a/nym-wallet/src/pages/auth/pages/create-mnemonic.tsx +++ b/nym-wallet/src/pages/auth/pages/create-mnemonic.tsx @@ -1,13 +1,13 @@ -import React, { useContext, useEffect } from 'react'; +import React, { useContext, useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { Container, Button, Stack } from '@mui/material'; import { AuthContext } from 'src/context/auth'; -import { useClipboard } from 'use-clipboard-copy'; import { Mnemonic } from '../../../components'; export const CreateMnemonic = () => { const { mnemonic, mnemonicWords, generateMnemonic, resetState } = useContext(AuthContext); const navigate = useNavigate(); + const [confirmed, setConfirmed] = useState(false); useEffect(() => { if (mnemonicWords.length === 0) { @@ -15,12 +15,10 @@ export const CreateMnemonic = () => { } }, []); - const { copy, copied } = useClipboard({ copiedTimeout: 5000 }); return ( - <Container maxWidth="xs"> + <Container maxWidth="sm"> <Stack alignItems="center" spacing={3} maxWidth="xs"> - <Mnemonic mnemonic={mnemonic} handleCopy={copy} copied={copied} /> - + <Mnemonic mnemonic={mnemonic} handleConfirmed={setConfirmed} confirmed={confirmed} withTitle /> <Button variant="contained" color="primary" @@ -28,9 +26,9 @@ export const CreateMnemonic = () => { size="large" onClick={() => navigate('/verify-mnemonic')} sx={{ width: '100%', fontSize: 15 }} - disabled={!copied} + disabled={!confirmed} > - I saved my mnemonic + Continue </Button> <Button onClick={() => { diff --git a/nym-wallet/src/pages/index.ts b/nym-wallet/src/pages/index.ts index c2944d771c..21d21cf7b5 100644 --- a/nym-wallet/src/pages/index.ts +++ b/nym-wallet/src/pages/index.ts @@ -1,4 +1,3 @@ -export * from './auth'; export * from './Admin'; export * from './balance'; export * from './bonding'; From 4652d65874ea6bc4c1b6afa9209d5715c0871f2e Mon Sep 17 00:00:00 2001 From: Fouad <fmtabbara@hotmail.co.uk> Date: Mon, 13 Feb 2023 10:27:04 +0000 Subject: [PATCH 2/9] Update password strength checking (#2994) * use zxcvbn password strength checker * prevent user from proceeding with a weak password + add tips * create storybook for password strength component * update storybook * update password-strength --- nym-wallet/package.json | 4 +- .../auth/components/password-strength.tsx | 112 +++++++++--------- .../components/passwordStrength.stories.tsx | 59 +++++++++ .../src/pages/auth/pages/connect-password.tsx | 7 +- .../src/pages/auth/pages/create-password.tsx | 6 +- nym-wallet/src/pages/bonding/Bonding.tsx | 3 +- .../node-settings/apy-playground/index.tsx | 3 +- .../general-settings/ParametersSettings.tsx | 2 +- nym-wallet/src/requests/queries.ts | 6 +- yarn.lock | 10 ++ 10 files changed, 137 insertions(+), 75 deletions(-) create mode 100644 nym-wallet/src/pages/auth/components/passwordStrength.stories.tsx diff --git a/nym-wallet/package.json b/nym-wallet/package.json index 9dc201f639..65ebc83226 100644 --- a/nym-wallet/package.json +++ b/nym-wallet/package.json @@ -52,7 +52,8 @@ "string-to-color": "^2.2.2", "use-clipboard-copy": "^0.2.0", "uuid": "^8.3.2", - "yup": "^0.32.9" + "yup": "^0.32.9", + "zxcvbn": "^4.4.2" }, "devDependencies": { "@babel/core": "^7.15.0", @@ -76,6 +77,7 @@ "@types/react-dom": "^18.0.10", "@types/semver": "^7.3.8", "@types/uuid": "^8.3.4", + "@types/zxcvbn": "^4.4.1", "@typescript-eslint/eslint-plugin": "^5.13.0", "@typescript-eslint/parser": "^5.13.0", "babel-loader": "^8.3.0", diff --git a/nym-wallet/src/pages/auth/components/password-strength.tsx b/nym-wallet/src/pages/auth/components/password-strength.tsx index 7e867f73fd..87ad9a3aa9 100644 --- a/nym-wallet/src/pages/auth/components/password-strength.tsx +++ b/nym-wallet/src/pages/auth/components/password-strength.tsx @@ -1,52 +1,61 @@ /* eslint-disable no-nested-ternary */ -import React, { useEffect, useState } from 'react'; +import React from 'react'; +import zxcvbn, { ZXCVBNScore } from 'zxcvbn'; import { LockOutlined } from '@mui/icons-material'; import { LinearProgress, Stack, Typography, Box } from '@mui/material'; -type TStrength = 'weak' | 'medium' | 'strong' | 'init'; - -const strong = /^(?=.*[a-z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{8,})/; -const medium = /^(((?=.*[a-z]))|((?=.*[a-z])(?=.*[0-9]))|((?=.*[0-9])))(?=.{6,})/; - const colorMap = { - init: 'inherit' as 'inherit', - weak: 'error' as 'error', - medium: 'warning' as 'warning', - strong: 'success' as 'success', + 4: 'success' as 'success', + 3: 'success' as 'success', + 2: 'warning' as 'warning', + 1: 'error' as 'error', + 0: 'error' as 'error', }; -const getText = (strength: TStrength) => { - switch (strength) { - case 'strong': +const getText = (score: ZXCVBNScore) => { + switch (score) { + case 4: + return 'Very strong password'; + case 3: return 'Strong password'; - case 'medium': - return 'Medium strength password'; - case 'weak': + case 2: + return 'Average password'; + case 1: return 'Weak password'; + case 0: + return 'Very weak password'; default: - return 'Password strength'; + return ''; } }; -const getTextColor = (strength: TStrength) => { - switch (strength) { - case 'strong': +const getColor = (score: ZXCVBNScore) => { + switch (score) { + case 4: return 'success.main'; - case 'medium': + case 3: + return 'success.main'; + case 2: return 'warning.main'; - case 'weak': + case 1: + return 'error.main'; + case 0: return 'error.main'; default: return 'grey.500'; } }; -const getPasswordStrength = (strength: TStrength) => { - switch (strength) { - case 'strong': +const getPasswordStrength = (score: ZXCVBNScore) => { + switch (score) { + case 4: return 100; - case 'medium': + case 3: + return 75; + case 2: return 50; + case 1: + return 25; default: return 0; } @@ -54,47 +63,32 @@ const getPasswordStrength = (strength: TStrength) => { export const PasswordStrength = ({ password, - onChange, + withWarnings, + handleIsSafePassword, }: { password: string; - onChange: (isStrong: boolean) => void; + withWarnings?: boolean; + handleIsSafePassword: (isSafe: boolean) => void; }) => { - const [strength, setStrength] = useState<TStrength>('init'); + const result = zxcvbn(password); - useEffect(() => { - if (password.length === 0) { - setStrength('init'); - return; - } + handleIsSafePassword(result.score > 1); - if (password.match(strong)) { - setStrength('strong'); - return; - } - - if (password.match(medium)) { - setStrength('medium'); - return; - } - setStrength('weak'); - }, [password]); - - useEffect(() => { - if (strength === 'strong') { - onChange(true); - } else { - onChange(false); - } - }, [strength]); + if (!password.length) return null; return ( <Stack spacing={0.5}> - <LinearProgress variant="determinate" color={colorMap[strength]} value={getPasswordStrength(strength)} /> - <Box display="flex" alignItems="center"> - <LockOutlined sx={{ fontSize: 15, color: getTextColor(strength) }} /> - <Typography variant="caption" sx={{ ml: 0.5, color: getTextColor(strength) }}> - {getText(strength)} - </Typography> + <LinearProgress variant="determinate" color={colorMap[result.score]} value={getPasswordStrength(result.score)} /> + <Box display="flex" alignItems="center" justifyContent="space-between"> + <Box display="flex" alignItems="center"> + <LockOutlined sx={{ fontSize: 15, color: getColor(result.score) }} /> + <Typography variant="caption" sx={{ ml: 0.5, color: getColor(result.score) }}> + {getText(result.score)} + </Typography> + </Box> + {withWarnings && result.feedback.warning && ( + <Typography variant="caption">{result.feedback.warning}</Typography> + )} </Box> </Stack> ); diff --git a/nym-wallet/src/pages/auth/components/passwordStrength.stories.tsx b/nym-wallet/src/pages/auth/components/passwordStrength.stories.tsx new file mode 100644 index 0000000000..35d6270c68 --- /dev/null +++ b/nym-wallet/src/pages/auth/components/passwordStrength.stories.tsx @@ -0,0 +1,59 @@ +import * as React from 'react'; +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import { Box, Stack, TextField } from '@mui/material'; +import { PasswordStrength } from './password-strength'; + +export default { + title: 'Wallet / Password Strength', + component: PasswordStrength, +} as ComponentMeta<typeof PasswordStrength>; + +const Template: ComponentStory<typeof PasswordStrength> = (args) => { + const [password, setPassword] = React.useState(args.password); + return ( + <Stack alignContent="center"> + <TextField value={password} onChange={(e) => setPassword(e.target.value)} sx={{ mb: 0.5 }} /> + {!!password.length && <PasswordStrength {...args} password={password} />} + </Stack> + ); +}; + +export const VeryStrong = Template.bind({}); +VeryStrong.args = { password: 'fedgklnrf34£', withWarnings: true, handleIsSafePassword: () => undefined }; + +export const Strong = Template.bind({}); +Strong.args = { password: '"56%abc123?@', withWarnings: true, handleIsSafePassword: () => undefined }; + +export const Average = Template.bind({}); +Average.args = { password: '"abc123?', withWarnings: true, handleIsSafePassword: () => undefined }; + +export const Weak = Template.bind({}); +Weak.args = { password: 'abc123?', withWarnings: true, handleIsSafePassword: () => undefined }; + +export const VeryWeak = Template.bind({}); +VeryWeak.args = { + password: 'abc123', + withWarnings: true, + handleIsSafePassword: () => undefined, +}; + +export const WithName = Template.bind({}); +WithName.args = { + password: 'fred', + withWarnings: true, + handleIsSafePassword: () => undefined, +}; + +export const WithSequence = Template.bind({}); +WithSequence.args = { + password: '121212', + withWarnings: true, + handleIsSafePassword: () => undefined, +}; + +export const Default = Template.bind({}); +Default.args = { + password: 'abc123', + withWarnings: true, + handleIsSafePassword: () => undefined, +}; diff --git a/nym-wallet/src/pages/auth/pages/connect-password.tsx b/nym-wallet/src/pages/auth/pages/connect-password.tsx index 133d0a27cb..476f0a9aca 100644 --- a/nym-wallet/src/pages/auth/pages/connect-password.tsx +++ b/nym-wallet/src/pages/auth/pages/connect-password.tsx @@ -9,9 +9,8 @@ import { Subtitle, Title, PasswordStrength } from '../components'; export const ConnectPassword = () => { const [confirmedPassword, setConfirmedPassword] = useState<string>(''); - const [isStrongPassword, setIsStrongPassword] = useState(false); const [isLoading, setIsLoading] = useState(false); - + const [isSafePassword, setIsSafePassword] = useState(false); const { mnemonic, password, setPassword, resetState } = useContext(AuthContext); const navigate = useNavigate(); @@ -49,7 +48,7 @@ export const ConnectPassword = () => { label="Password" autoFocus /> - <PasswordStrength password={password} onChange={(isStrong) => setIsStrongPassword(isStrong)} /> + <PasswordStrength password={password} handleIsSafePassword={setIsSafePassword} withWarnings /> </> <PasswordInput password={confirmedPassword} @@ -59,7 +58,7 @@ export const ConnectPassword = () => { <Button size="large" variant="contained" - disabled={password !== confirmedPassword || password.length === 0 || !isStrongPassword || isLoading} + disabled={password !== confirmedPassword || password.length === 0 || isLoading || !isSafePassword} onClick={storePassword} > {isLoading ? <CircularProgress size={25} /> : 'Create password'} diff --git a/nym-wallet/src/pages/auth/pages/create-password.tsx b/nym-wallet/src/pages/auth/pages/create-password.tsx index cf894f20c4..e071c6dcea 100644 --- a/nym-wallet/src/pages/auth/pages/create-password.tsx +++ b/nym-wallet/src/pages/auth/pages/create-password.tsx @@ -10,8 +10,8 @@ import { Subtitle, Title, PasswordStrength } from '../components'; export const CreatePassword = () => { const { password, setPassword, resetState, mnemonic } = useContext(AuthContext); const [confirmedPassword, setConfirmedPassword] = useState<string>(''); - const [isStrongPassword, setIsStrongPassword] = useState(false); const [isLoading, setIsLoading] = useState(false); + const [isSafePassword, setIsSafePassword] = useState(false); const navigate = useNavigate(); @@ -48,7 +48,7 @@ export const CreatePassword = () => { label="Password" autoFocus /> - <PasswordStrength password={password} onChange={(isStrong) => setIsStrongPassword(isStrong)} /> + <PasswordStrength password={password} handleIsSafePassword={setIsSafePassword} withWarnings /> </> <PasswordInput password={confirmedPassword} @@ -58,7 +58,7 @@ export const CreatePassword = () => { <Button size="large" variant="contained" - disabled={password !== confirmedPassword || password.length === 0 || !isStrongPassword || isLoading} + disabled={password !== confirmedPassword || password.length === 0 || isLoading || !isSafePassword} onClick={storePassword} > Next diff --git a/nym-wallet/src/pages/bonding/Bonding.tsx b/nym-wallet/src/pages/bonding/Bonding.tsx index 1eae1d3924..957f603d0e 100644 --- a/nym-wallet/src/pages/bonding/Bonding.tsx +++ b/nym-wallet/src/pages/bonding/Bonding.tsx @@ -17,6 +17,7 @@ import { AppContext, urls } from 'src/context/main'; import { isGateway, isMixnode, TBondGatewayArgs, TBondMixNodeArgs, TBondMoreArgs } from 'src/types'; import { BondedGateway } from 'src/components/Bonding/BondedGateway'; import { RedeemRewardsModal } from 'src/components/Bonding/modals/RedeemRewardsModal'; +import { Console } from 'src/utils/console'; import { BondingContextProvider, useBondingContext } from '../../context'; import { getMixnodeStakeSaturation } from '../../requests'; @@ -104,7 +105,7 @@ const Bonding = () => { } return { isOverSaturated: false, saturationPercentage: undefined }; } catch (e) { - console.error('Error fetching the saturation, error:', e); + Console.error('Error fetching the saturation, error:', e); return { isOverSaturated: false, saturationPercentage: undefined }; } }; diff --git a/nym-wallet/src/pages/bonding/node-settings/apy-playground/index.tsx b/nym-wallet/src/pages/bonding/node-settings/apy-playground/index.tsx index efac9050cb..65edb35bc5 100644 --- a/nym-wallet/src/pages/bonding/node-settings/apy-playground/index.tsx +++ b/nym-wallet/src/pages/bonding/node-settings/apy-playground/index.tsx @@ -7,6 +7,7 @@ import { CalculateArgs, Inputs } from 'src/components/RewardsPlayground/Inputs'; import { TBondedMixnode } from 'src/context'; import { useSnackbar } from 'notistack'; import { LoadingModal } from 'src/components/Modals/LoadingModal'; +import { Console } from 'src/utils/console'; import { computeEstimate, computeStakeSaturation, handleCalculatePeriodRewards } from './utils'; export type DefaultInputValues = { @@ -99,7 +100,7 @@ export const ApyPlayground = ({ bondedNode }: { bondedNode: TBondedMixnode }) => setStakeSaturation(computedStakeSaturation); setResults(estimationResult); } catch (e) { - console.log(e); + Console.log(e); } }; diff --git a/nym-wallet/src/pages/bonding/node-settings/settings-pages/general-settings/ParametersSettings.tsx b/nym-wallet/src/pages/bonding/node-settings/settings-pages/general-settings/ParametersSettings.tsx index a4e2bac152..0bff6c3ea3 100644 --- a/nym-wallet/src/pages/bonding/node-settings/settings-pages/general-settings/ParametersSettings.tsx +++ b/nym-wallet/src/pages/bonding/node-settings/settings-pages/general-settings/ParametersSettings.tsx @@ -56,7 +56,7 @@ export const ParametersSettings = ({ bondedNode }: { bondedNode: TBondedMixnode const { nextInterval } = await getIntervalAsDate(); setIntervalTime(nextInterval); } catch { - console.log('cant retrieve next interval'); + Console.log('cant retrieve next interval'); } }; diff --git a/nym-wallet/src/requests/queries.ts b/nym-wallet/src/requests/queries.ts index e80fd313fa..be74041f33 100644 --- a/nym-wallet/src/requests/queries.ts +++ b/nym-wallet/src/requests/queries.ts @@ -59,9 +59,5 @@ export const computeMixnodeRewardEstimation = async (args: { totalDelegation: number; profitMarginPercent: string; intervalOperatingCost: { denom: 'unym'; amount: string }; -}) => { - console.log(args); - - return invokeWrapper<RewardEstimationResponse>('compute_mixnode_reward_estimation', args); -}; +}) => invokeWrapper<RewardEstimationResponse>('compute_mixnode_reward_estimation', args); export const getMixnodeUptime = async (mixId: number) => invokeWrapper<number>('get_mixnode_uptime', { mixId }); diff --git a/yarn.lock b/yarn.lock index 3e0a888957..4c86e6287c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5338,6 +5338,11 @@ dependencies: "@types/yargs-parser" "*" +"@types/zxcvbn@^4.4.1": + version "4.4.1" + resolved "https://registry.yarnpkg.com/@types/zxcvbn/-/zxcvbn-4.4.1.tgz#46e42cbdcee681b22181478feaf4af2bc4c1abd2" + integrity sha512-3NoqvZC2W5gAC5DZbTpCeJ251vGQmgcWIHQJGq2J240HY6ErQ9aWKkwfoKJlHLx+A83WPNTZ9+3cd2ILxbvr1w== + "@typescript-eslint/eslint-plugin@^5.13.0", "@typescript-eslint/eslint-plugin@^5.7.0": version "5.49.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.49.0.tgz#d0b4556f0792194bf0c2fb297897efa321492389" @@ -19750,3 +19755,8 @@ zwitch@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7" integrity sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A== + +zxcvbn@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/zxcvbn/-/zxcvbn-4.4.2.tgz#28ec17cf09743edcab056ddd8b1b06262cc73c30" + integrity sha512-Bq0B+ixT/DMyG8kgX2xWcI5jUvCwqrMxSFam7m0lAf78nf04hv6lNCsyLYdyYTrCVMqNDY/206K7eExYCeSyUQ== From 726a406797c7f0d3a2daa3db449b9b751919b116 Mon Sep 17 00:00:00 2001 From: Fouad <fmtabbara@hotmail.co.uk> Date: Mon, 13 Feb 2023 10:55:53 +0000 Subject: [PATCH 3/9] update add account instructions (#2981) * update add account instructions --- nym-wallet/src/components/Accounts/MultiAccountHowTo.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/nym-wallet/src/components/Accounts/MultiAccountHowTo.tsx b/nym-wallet/src/components/Accounts/MultiAccountHowTo.tsx index c23f392bbe..62eb3a4643 100644 --- a/nym-wallet/src/components/Accounts/MultiAccountHowTo.tsx +++ b/nym-wallet/src/components/Accounts/MultiAccountHowTo.tsx @@ -5,11 +5,12 @@ import { SimpleModal } from '../Modals/SimpleModal'; import { Warning } from '../Warning'; const passwordCreationSteps = [ - 'Log out of your wallet', + 'Log out from the wallet', 'Sign in using “Sign in with mnemonic” button', - 'On the next screen select “Create a password for your account”', - 'Sign in to the wallet with your new password', - 'Then come back here to import or create new accounts', + 'On the next screen select “Create a password"', + 'Type in the mnemonic you want to create a password for and follow the next steps', + 'Sign back in the wallet using your new password', + 'Come back to this page to import or create new accounts', ]; // TODO add the link href value From 9348722b84d145178dab050ed4fb066aacca2656 Mon Sep 17 00:00:00 2001 From: Fouad <fmtabbara@hotmail.co.uk> Date: Mon, 13 Feb 2023 22:47:48 +0000 Subject: [PATCH 4/9] Feature/nym connect pick a gateway (#3008) * Add new route and initial UI * allow IdentityKeyFormField to have a small size option * add disabled prop to the shared IdentityKeyFormField component * defined custom gateway type * use custom gateway in state * set and validate custom gateway in settings page * validate user gateway when moving away from page * use storage * hide gateway input when inactive * add explorer link to settings page --- nym-connect/src/components/AppWindowFrame.tsx | 20 ++++- nym-connect/src/components/CustomTitleBar.tsx | 12 ++- nym-connect/src/context/main.tsx | 51 +++++++++-- nym-connect/src/context/mocks/main.tsx | 2 + nym-connect/src/pages/menu/Settings.tsx | 85 +++++++++++++++++++ nym-connect/src/pages/menu/index.tsx | 5 +- nym-connect/src/routes/index.tsx | 2 + nym-connect/src/theme/mui-theme.d.ts | 1 + nym-connect/src/theme/theme.tsx | 1 + nym-connect/src/types/gateway.ts | 4 + .../mixnodes/IdentityKeyFormField.tsx | 6 ++ 11 files changed, 176 insertions(+), 13 deletions(-) create mode 100644 nym-connect/src/pages/menu/Settings.tsx create mode 100644 nym-connect/src/types/gateway.ts diff --git a/nym-connect/src/components/AppWindowFrame.tsx b/nym-connect/src/components/AppWindowFrame.tsx index 4b407c3e7b..929b0f269f 100644 --- a/nym-connect/src/components/AppWindowFrame.tsx +++ b/nym-connect/src/components/AppWindowFrame.tsx @@ -1,10 +1,28 @@ import React from 'react'; import { Box } from '@mui/material'; import { useLocation } from 'react-router-dom'; +import { useClientContext } from 'src/context/main'; import { CustomTitleBar } from './CustomTitleBar'; export const AppWindowFrame: FCWithChildren = ({ children }) => { const location = useLocation(); + const { userDefinedGateway, setUserDefinedGateway } = useClientContext(); + + // defined functions to be used when moving away from pages + const onBack = () => { + switch (location.pathname) { + case '/menu/settings': + return () => { + // when the user moves away from the settings page and the gateway is not valid + // set isActive to false + if (!userDefinedGateway?.gateway) { + setUserDefinedGateway((current) => ({ ...current, isActive: false })); + } + }; + default: + return undefined; + } + }; return ( <Box @@ -14,7 +32,7 @@ export const AppWindowFrame: FCWithChildren = ({ children }) => { height: '100vh', }} > - <CustomTitleBar path={location.pathname} /> + <CustomTitleBar path={location.pathname} onBack={onBack()} /> <Box style={{ padding: '16px' }}>{children}</Box> </Box> ); diff --git a/nym-connect/src/components/CustomTitleBar.tsx b/nym-connect/src/components/CustomTitleBar.tsx index e7d81aecfa..d88b603873 100644 --- a/nym-connect/src/components/CustomTitleBar.tsx +++ b/nym-connect/src/components/CustomTitleBar.tsx @@ -29,9 +29,13 @@ const MenuIcon = () => { return <CustomButton Icon={Menu} onClick={() => navigate('/menu')} />; }; -const ArrowBackIcon = () => { +const ArrowBackIcon = ({ onBack }: { onBack?: () => void }) => { const navigate = useNavigate(); - return <CustomButton Icon={ArrowBack} onClick={() => navigate(-1)} />; + const handleBack = () => { + onBack?.(); + navigate(-1); + }; + return <CustomButton Icon={ArrowBack} onClick={handleBack} />; }; const getTitleIcon = (path: string) => { @@ -46,10 +50,10 @@ const getTitleIcon = (path: string) => { return <NymWordmark width={36} />; }; -export const CustomTitleBar = ({ path = '/' }: { path?: string }) => ( +export const CustomTitleBar = ({ path = '/', onBack }: { path?: string; onBack?: () => void }) => ( <Box data-tauri-drag-region style={customTitleBarStyles.titlebar}> {/* set width to keep logo centered */} - <Box sx={{ width: '40px' }}>{path === '/' ? <MenuIcon /> : <ArrowBackIcon />}</Box> + <Box sx={{ width: '40px' }}>{path === '/' ? <MenuIcon /> : <ArrowBackIcon onBack={onBack} />}</Box> {getTitleIcon(path)} <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}> <CustomButton Icon={Minimize} onClick={() => appWindow.minimize()} /> diff --git a/nym-connect/src/context/main.tsx b/nym-connect/src/context/main.tsx index 8c02df4e41..a933a8c36f 100644 --- a/nym-connect/src/context/main.tsx +++ b/nym-connect/src/context/main.tsx @@ -4,10 +4,14 @@ import { invoke } from '@tauri-apps/api'; import { Error } from 'src/types/error'; import { getVersion } from '@tauri-apps/api/app'; import { useEvents } from 'src/hooks/events'; +import { UserDefinedGateway } from 'src/types/gateway'; +import { forage } from '@tauri-apps/tauri-forage'; import { ConnectionStatusKind, GatewayPerformance } from '../types'; import { ConnectionStatsItem } from '../components/ConnectionStats'; import { ServiceProvider } from '../types/directory'; +const FORAGE_KEY = 'nym-connect-user-gateway'; + type ModeType = 'light' | 'dark'; export type TClientContext = { @@ -20,6 +24,7 @@ export type TClientContext = { gatewayPerformance: GatewayPerformance; selectedProvider?: ServiceProvider; showInfoModal: boolean; + userDefinedGateway?: UserDefinedGateway; setMode: (mode: ModeType) => void; clearError: () => void; setConnectionStatus: (connectionStatus: ConnectionStatusKind) => void; @@ -29,6 +34,7 @@ export type TClientContext = { setRandomSerivceProvider: () => void; startConnecting: () => Promise<void>; startDisconnecting: () => Promise<void>; + setUserDefinedGateway: React.Dispatch<React.SetStateAction<UserDefinedGateway>>; }; export const ClientContext = createContext({} as TClientContext); @@ -44,19 +50,43 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => { const [appVersion, setAppVersion] = useState<string>(); const [gatewayPerformance, setGatewayPerformance] = useState<GatewayPerformance>('Good'); const [showInfoModal, setShowInfoModal] = useState(false); + const [userDefinedGateway, setUserDefinedGateway] = useState<UserDefinedGateway>({ isActive: false, gateway: '' }); const getAppVersion = async () => { const version = await getVersion(); return version; }; + const setUserGatewayInStorage = async (gateway: UserDefinedGateway) => { + try { + await forage.setItem({ + key: FORAGE_KEY, + value: gateway, + } as any)(); + } catch (e) { + console.warn(e); + } + return undefined; + }; + + const getUserGatewayFromStorage = async (): Promise<UserDefinedGateway | undefined> => { + try { + const gatewayFromStorage = await forage.getItem({ key: FORAGE_KEY })(); + return gatewayFromStorage; + } catch (e) { + console.warn(e); + } + return undefined; + }; + const initialiseApp = async () => { const services = await invoke('get_services'); const AppVersion = await getAppVersion(); - console.log(services); + const storedUserDefinedGateway = await getUserGatewayFromStorage(); setAppVersion(AppVersion); setServiceProviders(services as ServiceProvider[]); + if (storedUserDefinedGateway) setUserDefinedGateway(storedUserDefinedGateway); }; useEvents({ @@ -94,15 +124,19 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => { } }, []); - const setServiceProvider = async (newServiceProvider?: ServiceProvider) => { - if (newServiceProvider) { - await invoke('set_gateway', { gateway: newServiceProvider.gateway }); - await invoke('set_service_provider', { serviceProvider: newServiceProvider.address }); - } + const shouldUseUserGateway = !!userDefinedGateway.gateway && userDefinedGateway.isActive; + + const setServiceProvider = async (newServiceProvider: ServiceProvider) => { + await invoke('set_gateway', { + gateway: newServiceProvider.gateway, + }); + await invoke('set_service_provider', { serviceProvider: newServiceProvider.address }); }; const getRandomSPFromList = (services: ServiceProvider[]) => { const randomSelection = services[Math.floor(Math.random() * services.length)]; + + if (shouldUseUserGateway) return { ...randomSelection, gateway: userDefinedGateway.gateway } as ServiceProvider; return randomSelection; }; @@ -110,8 +144,10 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => { if (serviceProviders) { const randomServiceProvider = getRandomSPFromList(serviceProviders); await setServiceProvider(randomServiceProvider); + await setUserGatewayInStorage(userDefinedGateway); setSelectedProvider(randomServiceProvider); } + return undefined; }; const clearError = () => setError(undefined); @@ -136,6 +172,8 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => { startDisconnecting, gatewayPerformance, setShowInfoModal, + userDefinedGateway, + setUserDefinedGateway, }), [ mode, @@ -148,6 +186,7 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => { connectedSince, gatewayPerformance, selectedProvider, + userDefinedGateway, ], ); diff --git a/nym-connect/src/context/mocks/main.tsx b/nym-connect/src/context/mocks/main.tsx index ea86bb365d..6d0f7d9a82 100644 --- a/nym-connect/src/context/mocks/main.tsx +++ b/nym-connect/src/context/mocks/main.tsx @@ -9,6 +9,7 @@ const mockValues: TClientContext = { selectedProvider: { id: '1', description: 'Keybase service provider', gateway: 'abc123', address: '123abc' }, gatewayPerformance: 'Good', showInfoModal: false, + userDefinedGateway: { isActive: false, gateway: '' }, setShowInfoModal: () => {}, setMode: () => {}, clearError: () => {}, @@ -18,6 +19,7 @@ const mockValues: TClientContext = { startConnecting: async () => {}, startDisconnecting: async () => {}, setRandomSerivceProvider: () => {}, + setUserDefinedGateway: () => {}, }; export const MockProvider: FCWithChildren<{ diff --git a/nym-connect/src/pages/menu/Settings.tsx b/nym-connect/src/pages/menu/Settings.tsx new file mode 100644 index 0000000000..bc3716d20e --- /dev/null +++ b/nym-connect/src/pages/menu/Settings.tsx @@ -0,0 +1,85 @@ +import React, { ChangeEvent, useState } from 'react'; +import { IdentityKeyFormField } from '@nymproject/react/mixnodes/IdentityKeyFormField'; +import { Box, FormControl, FormControlLabel, FormHelperText, Link, Stack, Switch, Typography } from '@mui/material'; +import { useClientContext } from 'src/context/main'; +import { ConnectionStatusKind } from 'src/types'; +import { AppVersion } from 'src/components/AppVersion'; + +export const Settings = () => { + const { userDefinedGateway, setUserDefinedGateway } = useClientContext(); + const [gatewayKey, setGatewayKey] = useState<string | undefined>(userDefinedGateway?.gateway); + + const handleIsValidGatewayKey = (isValid: boolean) => { + let gateway: string | undefined; + + if (isValid) { + gateway = gatewayKey; + } + + setUserDefinedGateway((current) => ({ ...current, gateway })); + }; + + const handleChange = (e: ChangeEvent<HTMLInputElement>) => { + setUserDefinedGateway((current) => ({ ...current, isActive: e.target.checked })); + }; + + const { connectionStatus } = useClientContext(); + + return ( + <Box height="100%"> + <Stack justifyContent="space-between" height="100%"> + <Box> + <Typography fontWeight="bold" variant="body2" mb={1}> + Select your Gateway + </Typography> + <Typography color="grey.300" variant="body2" mb={2}> + Use a gateway of your choice + </Typography> + <FormControl fullWidth> + <FormControlLabel + control={ + <Switch + checked={userDefinedGateway?.isActive} + onChange={handleChange} + disabled={connectionStatus === ConnectionStatusKind.connected} + size="small" + sx={{ ml: 1 }} + /> + } + label={userDefinedGateway?.isActive ? 'On' : 'Off'} + /> + {connectionStatus === ConnectionStatusKind.connected && ( + <FormHelperText sx={{ m: 0, my: 1 }}>This setting is disabled during an active connection</FormHelperText> + )} + {userDefinedGateway?.isActive && ( + <IdentityKeyFormField + size="small" + placeholder="Gateway identity key" + onChanged={setGatewayKey} + initialValue={gatewayKey} + onValidate={handleIsValidGatewayKey} + sx={{ mt: 1 }} + disabled={connectionStatus === 'connected' || !userDefinedGateway?.isActive} + /> + )} + </FormControl> + </Box> + <Box> + <Typography variant="body2" mb={3}> + To find a gateway go to the{' '} + <Link + underline="none" + target="_blank" + href="https://explorer.nymtech.net/network-components/gateways" + sx={{ cursor: 'pointer' }} + color="nym.cta" + > + Network Explorer + </Link> + </Typography> + <AppVersion /> + </Box> + </Stack> + </Box> + ); +}; diff --git a/nym-connect/src/pages/menu/index.tsx b/nym-connect/src/pages/menu/index.tsx index a4cac1bf20..67b3dc0131 100644 --- a/nym-connect/src/pages/menu/index.tsx +++ b/nym-connect/src/pages/menu/index.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Apps, HelpOutline } from '@mui/icons-material'; +import { Apps, HelpOutline, Settings } from '@mui/icons-material'; import { Stack, Link, List, ListItem, ListItemButton, ListItemIcon, ListItemText } from '@mui/material'; import { Link as RouterLink } from 'react-router-dom'; import { AppVersion } from 'src/components/AppVersion'; @@ -7,13 +7,14 @@ import { AppVersion } from 'src/components/AppVersion'; const menuSchema = [ { title: 'Supported apps', icon: Apps, path: 'apps' }, { title: 'How to connect guide', icon: HelpOutline, path: 'guide' }, + { title: 'Settings', icon: Settings, path: 'settings' }, ]; export const Menu = () => ( <Stack justifyContent="space-between" height="100%"> <List dense disablePadding> {menuSchema.map((item) => ( - <Link component={RouterLink} to={item.path} underline="none" color="white"> + <Link component={RouterLink} to={item.path} underline="none" color="white" key={item.title}> <ListItem disablePadding> <ListItemButton> <ListItemIcon sx={{ minWidth: 25 }}> diff --git a/nym-connect/src/routes/index.tsx b/nym-connect/src/routes/index.tsx index ffb0881876..ec24080c6c 100644 --- a/nym-connect/src/routes/index.tsx +++ b/nym-connect/src/routes/index.tsx @@ -4,6 +4,7 @@ import { ConnectionPage } from 'src/pages/connection'; import { Menu } from 'src/pages/menu'; import { CompatibleApps } from 'src/pages/menu/Apps'; import { HelpGuide } from 'src/pages/menu/Guide'; +import { Settings } from 'src/pages/menu/Settings'; export const AppRoutes = () => ( <Routes> @@ -12,6 +13,7 @@ export const AppRoutes = () => ( <Route index element={<Menu />} /> <Route path="apps" element={<CompatibleApps />} /> <Route path="guide" element={<HelpGuide />} /> + <Route path="settings" element={<Settings />} /> </Route> </Routes> ); diff --git a/nym-connect/src/theme/mui-theme.d.ts b/nym-connect/src/theme/mui-theme.d.ts index 6c4d88fe39..76db4b1a99 100644 --- a/nym-connect/src/theme/mui-theme.d.ts +++ b/nym-connect/src/theme/mui-theme.d.ts @@ -29,6 +29,7 @@ declare module '@mui/material/styles' { */ interface NymPalette { highlight: string; + cta: string; success: string; warning: string; info: string; diff --git a/nym-connect/src/theme/theme.tsx b/nym-connect/src/theme/theme.tsx index 18678fce98..977b0c9dfd 100644 --- a/nym-connect/src/theme/theme.tsx +++ b/nym-connect/src/theme/theme.tsx @@ -21,6 +21,7 @@ import { const nymPalette: NymPalette = { /** emphasises important elements */ highlight: '#21D072', + cta: '#FB6E4E', success: '#21D073', info: '#60D7EF', warning: '#FFE600', diff --git a/nym-connect/src/types/gateway.ts b/nym-connect/src/types/gateway.ts new file mode 100644 index 0000000000..735a3cdb03 --- /dev/null +++ b/nym-connect/src/types/gateway.ts @@ -0,0 +1,4 @@ +export interface UserDefinedGateway { + isActive: boolean; + gateway?: string; +} diff --git a/ts-packages/react-components/src/components/mixnodes/IdentityKeyFormField.tsx b/ts-packages/react-components/src/components/mixnodes/IdentityKeyFormField.tsx index ec721408bf..4417bbffe5 100644 --- a/ts-packages/react-components/src/components/mixnodes/IdentityKeyFormField.tsx +++ b/ts-packages/react-components/src/components/mixnodes/IdentityKeyFormField.tsx @@ -19,7 +19,9 @@ export const IdentityKeyFormField: FCWithChildren<{ onValidate?: (isValid: boolean, error?: string) => void; textFieldProps?: TextFieldProps; errorText?: string; + size?: 'small' | 'medium'; sx?: SxProps; + disabled?: boolean; }> = ({ required, fullWidth, @@ -33,6 +35,8 @@ export const IdentityKeyFormField: FCWithChildren<{ onValidate, textFieldProps, showTickOnValid = true, + size, + disabled, }) => { const [value, setValue] = React.useState<string | undefined>(initialValue); const [validationError, setValidationError] = React.useState<string | undefined>(); @@ -100,6 +104,8 @@ export const IdentityKeyFormField: FCWithChildren<{ defaultValue={initialValue} onChange={handleChange} InputLabelProps={{ shrink: true }} + size={size} + disabled={disabled} /> ); }; From 3d500c25c5e7d691c36aa11b79939387e0c0c6cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= <bogdan@nymtech.net> Date: Wed, 8 Feb 2023 13:00:58 +0200 Subject: [PATCH 5/9] Hide coconut runtime flags (#2990) --- clients/native/src/commands/init.rs | 4 ++-- clients/native/src/commands/run.rs | 4 ++-- clients/socks5/src/commands/init.rs | 4 ++-- clients/socks5/src/commands/run.rs | 4 ++-- gateway/src/commands/init.rs | 5 +++-- gateway/src/commands/run.rs | 5 +++-- nym-api/src/support/cli/mod.rs | 9 +++++++-- 7 files changed, 21 insertions(+), 14 deletions(-) diff --git a/clients/native/src/commands/init.rs b/clients/native/src/commands/init.rs index b56e570ce7..6680f5401b 100644 --- a/clients/native/src/commands/init.rs +++ b/clients/native/src/commands/init.rs @@ -31,7 +31,7 @@ pub(crate) struct Init { force_register_gateway: bool, /// Comma separated list of rest endpoints of the nyxd validators - #[clap(long, alias = "nymd_validators", value_delimiter = ',')] + #[clap(long, alias = "nymd_validators", value_delimiter = ',', hide = true)] nyxd_urls: Option<Vec<url::Url>>, /// Comma separated list of rest endpoints of the API validators @@ -62,7 +62,7 @@ pub(crate) struct Init { /// Set this client to work in a enabled credentials mode that would attempt to use gateway /// with bandwidth credential requirement. - #[clap(long)] + #[clap(long, hide = true)] enabled_credentials_mode: Option<bool>, /// Save a summary of the initialization to a json file diff --git a/clients/native/src/commands/run.rs b/clients/native/src/commands/run.rs index ab9a04427e..e2e90082b3 100644 --- a/clients/native/src/commands/run.rs +++ b/clients/native/src/commands/run.rs @@ -23,7 +23,7 @@ pub(crate) struct Run { id: String, /// Comma separated list of rest endpoints of the nyxd validators - #[clap(long, alias = "nymd_validators", value_delimiter = ',')] + #[clap(long, alias = "nymd_validators", value_delimiter = ',', hide = true)] nyxd_urls: Option<Vec<url::Url>>, /// Comma separated list of rest endpoints of the API validators @@ -59,7 +59,7 @@ pub(crate) struct Run { /// Set this client to work in a enabled credentials mode that would attempt to use gateway /// with bandwidth credential requirement. - #[clap(long)] + #[clap(long, hide = true)] enabled_credentials_mode: Option<bool>, } diff --git a/clients/socks5/src/commands/init.rs b/clients/socks5/src/commands/init.rs index 38df141afe..6d96277619 100644 --- a/clients/socks5/src/commands/init.rs +++ b/clients/socks5/src/commands/init.rs @@ -43,7 +43,7 @@ pub(crate) struct Init { force_register_gateway: bool, /// Comma separated list of rest endpoints of the nyxd validators - #[clap(long, alias = "nymd_validators", value_delimiter = ',')] + #[clap(long, alias = "nymd_validators", value_delimiter = ',', hide = true)] nyxd_urls: Option<Vec<url::Url>>, /// Comma separated list of rest endpoints of the API validators @@ -66,7 +66,7 @@ pub(crate) struct Init { /// Set this client to work in a enabled credentials mode that would attempt to use gateway /// with bandwidth credential requirement. - #[clap(long)] + #[clap(long, hide = true)] enabled_credentials_mode: Option<bool>, /// Save a summary of the initialization to a json file diff --git a/clients/socks5/src/commands/run.rs b/clients/socks5/src/commands/run.rs index cfb71032ba..80bbd02c47 100644 --- a/clients/socks5/src/commands/run.rs +++ b/clients/socks5/src/commands/run.rs @@ -43,7 +43,7 @@ pub(crate) struct Run { gateway: Option<identity::PublicKey>, /// Comma separated list of rest endpoints of the nyxd validators - #[clap(long, alias = "nymd_validators", value_delimiter = ',')] + #[clap(long, alias = "nymd_validators", value_delimiter = ',', hide = true)] nyxd_urls: Option<Vec<url::Url>>, /// Comma separated list of rest endpoints of the Nym APIs @@ -65,7 +65,7 @@ pub(crate) struct Run { /// Set this client to work in a enabled credentials mode that would attempt to use gateway /// with bandwidth credential requirement. - #[clap(long)] + #[clap(long, hide = true)] enabled_credentials_mode: Option<bool>, } diff --git a/gateway/src/commands/init.rs b/gateway/src/commands/init.rs index 45548d7cd8..046269dfe5 100644 --- a/gateway/src/commands/init.rs +++ b/gateway/src/commands/init.rs @@ -55,7 +55,8 @@ pub struct Init { long, alias = "validators", alias = "nymd_validators", - value_delimiter = ',' + value_delimiter = ',', + hide = true )] // the alias here is included for backwards compatibility (1.1.4 and before) nyxd_urls: Option<Vec<url::Url>>, @@ -66,7 +67,7 @@ pub struct Init { /// Set this gateway to work only with coconut credentials; that would disallow clients to /// bypass bandwidth credential requirement - #[clap(long)] + #[clap(long, hide = true)] only_coconut_credentials: Option<bool>, /// Enable/disable gateway anonymized statistics that get sent to a statistics aggregator server diff --git a/gateway/src/commands/run.rs b/gateway/src/commands/run.rs index d7d864193c..3f149b42fe 100644 --- a/gateway/src/commands/run.rs +++ b/gateway/src/commands/run.rs @@ -53,7 +53,8 @@ pub struct Run { long, alias = "validators", alias = "nymd_validators", - value_delimiter = ',' + value_delimiter = ',', + hide = true )] // the alias here is included for backwards compatibility (1.1.4 and before) nyxd_urls: Option<Vec<url::Url>>, @@ -64,7 +65,7 @@ pub struct Run { /// Set this gateway to work only with coconut credentials; that would disallow clients to /// bypass bandwidth credential requirement - #[clap(long)] + #[clap(long, hide = true)] only_coconut_credentials: Option<bool>, /// Enable/disable gateway anonymized statistics that get sent to a statistics aggregator server diff --git a/nym-api/src/support/cli/mod.rs b/nym-api/src/support/cli/mod.rs index 7e74b58e3c..292c7e9047 100644 --- a/nym-api/src/support/cli/mod.rs +++ b/nym-api/src/support/cli/mod.rs @@ -93,11 +93,16 @@ pub(crate) struct CliArgs { pub(crate) enabled_credentials_mode: Option<bool>, /// Announced address where coconut clients will connect. - #[clap(long)] + #[clap(long, hide = true)] pub(crate) announce_address: Option<url::Url>, /// Flag to indicate whether coconut signer authority is enabled on this API - #[clap(long, requires = "mnemonic", requires = "announce_address")] + #[clap( + long, + requires = "mnemonic", + requires = "announce_address", + hide = true + )] pub(crate) enable_coconut: Option<bool>, } From d23fb366e4e9d657abc5f6dc80298e3a452247ef Mon Sep 17 00:00:00 2001 From: Fouad <fmtabbara@hotmail.co.uk> Date: Tue, 14 Feb 2023 10:46:10 +0000 Subject: [PATCH 6/9] update changelog and fix lint errors (#3023) add unreleased tag into NC changelog --- nym-connect/CHANGELOG.md | 11 +++++++---- nym-wallet/CHANGELOG.md | 7 +++++++ nym-wallet/src/components/Mnemonic.tsx | 5 ++--- .../auth/components/passwordStrength.stories.tsx | 12 +++++++----- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/nym-connect/CHANGELOG.md b/nym-connect/CHANGELOG.md index 39b13e201f..2d3331f27e 100644 --- a/nym-connect/CHANGELOG.md +++ b/nym-connect/CHANGELOG.md @@ -1,11 +1,14 @@ # Changelog +## UNRELEASED + ## [nym-connect-v1.1.9](https://github.com/nymtech/nym/tree/nym-connect-v1.1.9) (2023-02-07) -- NC - Button animations ([#2949]) -- NC - add effect when the button is clicked ([#2947]) -- NC - UI to select gateways based on some performance criteria by checking gateways' routing score from nym-api ([#2942]) -- NC - client health check when connecting ([#2859]) +- Button animations ([#2949]) +- add effect when the button is clicked ([#2947]) +- UI to select gateways based on some performance criteria by checking gateways' routing score from nym-api ([#2942]) +- client health check when connecting ([#2859]) +- allow user to select own gateway [#2949]: https://github.com/nymtech/nym/issues/2949 [#2947]: https://github.com/nymtech/nym/issues/2947 diff --git a/nym-wallet/CHANGELOG.md b/nym-wallet/CHANGELOG.md index 6cff0c274a..4acc10ce22 100644 --- a/nym-wallet/CHANGELOG.md +++ b/nym-wallet/CHANGELOG.md @@ -2,6 +2,13 @@ ## UNRELEASED +## [nym-wallet-v1.1.9](https://github.com/nymtech/nym/releases/tag/nym-wallet-v1.1.9) (2023-02-14) + +- Allow more flexibility for user when setting passwords +- User feedback on weak passwords +- User no longer has to copy mnemonic to continune account creation +- Updated instructional steps for creating accounts with a password + ## [nym-wallet-v1.1.8](https://github.com/nymtech/nym/releases/tag/nym-wallet-v1.1.8) (2023-01-24) - Fix delegations sorting ([#2885]) diff --git a/nym-wallet/src/components/Mnemonic.tsx b/nym-wallet/src/components/Mnemonic.tsx index ac222d2cef..7e592c1902 100644 --- a/nym-wallet/src/components/Mnemonic.tsx +++ b/nym-wallet/src/components/Mnemonic.tsx @@ -1,8 +1,7 @@ import React from 'react'; -import { Checkbox, FormControlLabel, Stack, TextField, Typography } from '@mui/material'; -import { Warning } from './Warning'; +import { Box, Checkbox, FormControlLabel, Stack, TextField, Typography } from '@mui/material'; import { Title } from 'src/pages/auth/components/heading'; -import { Box } from '@mui/system'; +import { Warning } from './Warning'; export const Mnemonic = ({ mnemonic, diff --git a/nym-wallet/src/pages/auth/components/passwordStrength.stories.tsx b/nym-wallet/src/pages/auth/components/passwordStrength.stories.tsx index 35d6270c68..3746b2015a 100644 --- a/nym-wallet/src/pages/auth/components/passwordStrength.stories.tsx +++ b/nym-wallet/src/pages/auth/components/passwordStrength.stories.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { ComponentMeta, ComponentStory } from '@storybook/react'; -import { Box, Stack, TextField } from '@mui/material'; +import { Stack, TextField } from '@mui/material'; import { PasswordStrength } from './password-strength'; export default { @@ -8,12 +8,14 @@ export default { component: PasswordStrength, } as ComponentMeta<typeof PasswordStrength>; -const Template: ComponentStory<typeof PasswordStrength> = (args) => { - const [password, setPassword] = React.useState(args.password); +const Template: ComponentStory<typeof PasswordStrength> = ({ password, withWarnings, handleIsSafePassword }) => { + const [value, setValue] = React.useState(password); return ( <Stack alignContent="center"> - <TextField value={password} onChange={(e) => setPassword(e.target.value)} sx={{ mb: 0.5 }} /> - {!!password.length && <PasswordStrength {...args} password={password} />} + <TextField value={value} onChange={(e) => setValue(e.target.value)} sx={{ mb: 0.5 }} /> + {!!password.length && ( + <PasswordStrength handleIsSafePassword={handleIsSafePassword} withWarnings={withWarnings} password={password} /> + )} </Stack> ); }; From a925c396427fc60b4063d2e8193de01ca45ec4e2 Mon Sep 17 00:00:00 2001 From: Fouad <fmtabbara@hotmail.co.uk> Date: Tue, 14 Feb 2023 12:13:19 +0000 Subject: [PATCH 7/9] Wallet - Fix operator cost in playground (#3021) * remove upper limit restriction * update validation --- .../components/RewardsPlayground/inputsValidationSchema.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/nym-wallet/src/components/RewardsPlayground/inputsValidationSchema.ts b/nym-wallet/src/components/RewardsPlayground/inputsValidationSchema.ts index ef5d9ecc0d..2e44ec4cb5 100644 --- a/nym-wallet/src/components/RewardsPlayground/inputsValidationSchema.ts +++ b/nym-wallet/src/components/RewardsPlayground/inputsValidationSchema.ts @@ -35,7 +35,9 @@ export const inputValidationSchema = Yup.object().shape({ .test('Is valid operator cost value', (value, ctx) => { const stringValueToNumber = Math.round(Number(value)); - if (isGreaterThan(stringValueToNumber, -1) && isLessThan(stringValueToNumber, 101)) return true; - return ctx.createError({ message: 'Operator cost must be a valid number' }); + if (isLessThan(stringValueToNumber, 0)) + return ctx.createError({ message: 'Operator cost must be a valid number' }); + + return true; }), }); From bc55c10e19c6478368a8e11d2c4f44f120a9f775 Mon Sep 17 00:00:00 2001 From: farbanas <arbanasfran@gmail.com> Date: Tue, 14 Feb 2023 07:18:03 -0500 Subject: [PATCH 8/9] bumped versions for release/v1.1.9 --- clients/client-core/Cargo.toml | 2 +- clients/native/Cargo.toml | 2 +- clients/socks5/Cargo.toml | 2 +- explorer-api/Cargo.toml | 2 +- explorer/package.json | 2 +- gateway/Cargo.toml | 2 +- mixnode/Cargo.toml | 2 +- nym-api/Cargo.toml | 2 +- nym-connect/package.json | 2 +- nym-connect/src-tauri/Cargo.toml | 2 +- nym-connect/src-tauri/tauri.conf.json | 2 +- nym-wallet/package.json | 4 ++-- nym-wallet/src-tauri/Cargo.toml | 2 +- nym-wallet/src-tauri/tauri.conf.json | 17 ++++++++++++----- service-providers/network-requester/Cargo.toml | 2 +- service-providers/network-statistics/Cargo.toml | 2 +- tools/nym-cli/Cargo.toml | 2 +- 17 files changed, 29 insertions(+), 22 deletions(-) diff --git a/clients/client-core/Cargo.toml b/clients/client-core/Cargo.toml index f9802bc367..5196587ba7 100644 --- a/clients/client-core/Cargo.toml +++ b/clients/client-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "client-core" -version = "1.1.8" +version = "1.1.9" authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"] edition = "2021" rust-version = "1.66" diff --git a/clients/native/Cargo.toml b/clients/native/Cargo.toml index 255c89da61..df2f9dad8d 100644 --- a/clients/native/Cargo.toml +++ b/clients/native/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-client" -version = "1.1.8" +version = "1.1.9" authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"] description = "Implementation of the Nym Client" edition = "2021" diff --git a/clients/socks5/Cargo.toml b/clients/socks5/Cargo.toml index da121b4ad0..050a1b0380 100644 --- a/clients/socks5/Cargo.toml +++ b/clients/socks5/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-socks5-client" -version = "1.1.8" +version = "1.1.9" authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"] description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address" edition = "2021" diff --git a/explorer-api/Cargo.toml b/explorer-api/Cargo.toml index 5d09ccb5c3..dcfc34eb35 100644 --- a/explorer-api/Cargo.toml +++ b/explorer-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "explorer-api" -version = "1.1.8" +version = "1.1.9" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/explorer/package.json b/explorer/package.json index c4b82c7a78..f2ca75b38b 100644 --- a/explorer/package.json +++ b/explorer/package.json @@ -1,6 +1,6 @@ { "name": "@nym/network-explorer", - "version": "1.0.4", + "version": "1.0.5", "private": true, "license": "Apache-2.0", "dependencies": { diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index 5b1fd14ccf..52d4f36733 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-gateway" -version = "1.1.8" +version = "1.1.9" authors = [ "Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>", diff --git a/mixnode/Cargo.toml b/mixnode/Cargo.toml index 69b4deb6e2..146335cd69 100644 --- a/mixnode/Cargo.toml +++ b/mixnode/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-mixnode" -version = "1.1.9" +version = "1.1.10" authors = [ "Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>", diff --git a/nym-api/Cargo.toml b/nym-api/Cargo.toml index 6db7cfa812..6378976a15 100644 --- a/nym-api/Cargo.toml +++ b/nym-api/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-api" -version = "1.1.9" +version = "1.1.10" authors = [ "Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>", diff --git a/nym-connect/package.json b/nym-connect/package.json index 127ac38de1..b124d71730 100644 --- a/nym-connect/package.json +++ b/nym-connect/package.json @@ -1,6 +1,6 @@ { "name": "@nym/nym-connect", - "version": "1.1.8", + "version": "1.1.9", "main": "index.js", "license": "MIT", "scripts": { diff --git a/nym-connect/src-tauri/Cargo.toml b/nym-connect/src-tauri/Cargo.toml index 93e21710bb..d80662fd18 100644 --- a/nym-connect/src-tauri/Cargo.toml +++ b/nym-connect/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-connect" -version = "1.1.8" +version = "1.1.9" description = "nym-connect" authors = ["Nym Technologies SA"] license = "" diff --git a/nym-connect/src-tauri/tauri.conf.json b/nym-connect/src-tauri/tauri.conf.json index deff29513f..8642c2e26c 100644 --- a/nym-connect/src-tauri/tauri.conf.json +++ b/nym-connect/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "package": { "productName": "nym-connect", - "version": "1.1.8" + "version": "1.1.9" }, "build": { "distDir": "../dist", diff --git a/nym-wallet/package.json b/nym-wallet/package.json index 65ebc83226..b1eda933fd 100644 --- a/nym-wallet/package.json +++ b/nym-wallet/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/nym-wallet-app", - "version": "1.1.8", + "version": "1.1.9", "main": "index.js", "license": "MIT", "scripts": { @@ -122,4 +122,4 @@ "webpack-favicons": "^1.3.8", "webpack-merge": "^5.8.0" } -} +} \ No newline at end of file diff --git a/nym-wallet/src-tauri/Cargo.toml b/nym-wallet/src-tauri/Cargo.toml index fe3d203aa9..1be9d6eb28 100644 --- a/nym-wallet/src-tauri/Cargo.toml +++ b/nym-wallet/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym_wallet" -version = "1.1.8" +version = "1.1.9" description = "Nym Native Wallet" authors = ["Nym Technologies SA"] license = "" diff --git a/nym-wallet/src-tauri/tauri.conf.json b/nym-wallet/src-tauri/tauri.conf.json index 08cc4b3383..8b14c1d304 100644 --- a/nym-wallet/src-tauri/tauri.conf.json +++ b/nym-wallet/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "package": { "productName": "nym-wallet", - "version": "1.1.8" + "version": "1.1.9" }, "build": { "distDir": "../dist", @@ -14,7 +14,13 @@ "active": true, "targets": "all", "identifier": "net.nymtech.wallet", - "icon": ["icons/32x32.png", "icons/128x128.png", "icons/128x128@2x.png", "icons/icon.icns", "icons/icon.ico"], + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ], "resources": [], "externalBin": [], "copyright": "Copyright © 2021-2022 Nym Technologies SA", @@ -27,7 +33,6 @@ "macOS": { "frameworks": [], "minimumSystemVersion": "", - "exceptionDomain": "", "signingIdentity": "Developer ID Application: Nym Technologies SA (VW5DZLFHM5)", "entitlements": null @@ -40,7 +45,9 @@ }, "updater": { "active": true, - "endpoints": ["https://nymtech.net/.wellknown/wallet/updater.json"], + "endpoints": [ + "https://nymtech.net/.wellknown/wallet/updater.json" + ], "dialog": true, "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IENCNzQ2M0E5N0VFODE2NApSV1JrZ2U2WE9rYTNETTg1OTBKdE5uWUEra0hML2syOVUvQ2lxZmFZRzZ1T3NWbGM0eVRzUTVhVwo=" }, @@ -67,4 +74,4 @@ "csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self' img-src: 'self'" } } -} +} \ No newline at end of file diff --git a/service-providers/network-requester/Cargo.toml b/service-providers/network-requester/Cargo.toml index bc48c72adb..fd30ecf554 100644 --- a/service-providers/network-requester/Cargo.toml +++ b/service-providers/network-requester/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-network-requester" -version = "1.1.8" +version = "1.1.9" authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"] edition = "2021" rust-version = "1.65" diff --git a/service-providers/network-statistics/Cargo.toml b/service-providers/network-statistics/Cargo.toml index accdccc977..18c482c3c0 100644 --- a/service-providers/network-statistics/Cargo.toml +++ b/service-providers/network-statistics/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-network-statistics" -version = "1.1.8" +version = "1.1.9" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tools/nym-cli/Cargo.toml b/tools/nym-cli/Cargo.toml index 7680ea44fe..ef0c22404b 100644 --- a/tools/nym-cli/Cargo.toml +++ b/tools/nym-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-cli" -version = "1.1.8" +version = "1.1.9" authors.workspace = true edition = "2021" From 3c97d0d16b71bdafca6a100ae0dec6e06f20b27f Mon Sep 17 00:00:00 2001 From: farbanas <arbanasfran@gmail.com> Date: Tue, 14 Feb 2023 07:28:59 -0500 Subject: [PATCH 9/9] Updated changelogs --- CHANGELOG.md | 14 ++++++-------- explorer/CHANGELOG.md | 2 +- nym-connect/CHANGELOG.md | 5 +++-- nym-wallet/CHANGELOG.md | 12 ++++++++---- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e67f596aac..38048653c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,19 +7,17 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// # [v1.1.9] (2023-02-07) ### Added - -- Separate `nym-api` endpoints with values of "total-supply" and "circulating-supply" in `nym` ([#2964]) -- Add `host` option to client init ([#2912]) - Remove Coconut feature flag ([#2793]) -- Don't drop in mixnet connection handler ([#2963]) +- Separate `nym-api` endpoints with values of "total-supply" and "circulating-supply" in `nym` ([#2964]) ### Changed -- native-client: is now capable of listening for requests on sockets different than `127.0.0.1` ([#2939]). This can be specified via `--host` flag during `init` or `run`. Alternatively a custom `host` can be set in `config.toml` file under `socket` section. +- native-client: is now capable of listening for requests on sockets different than `127.0.0.1` ([#2912]). This can be specified via `--host` flag during `init` or `run`. Alternatively a custom `host` can be set in `config.toml` file under `socket` section. - mixnode, gateway: fix unexpected shutdown on corrupted connection ([#2963]) -[#2939]: https://github.com/nymtech/nym/pull/2939 -[#2963]: https://github.com/nymtech/nym/pull/2963 - +[#2793]: https://github.com/nymtech/nym/issues/2793 +[#2912]: https://github.com/nymtech/nym/issues/2912 +[#2964]: https://github.com/nymtech/nym/issues/2964 +[#2963]: https://github.com/nymtech/nym/issues/3017 # [v1.1.8] (2023-01-31) diff --git a/explorer/CHANGELOG.md b/explorer/CHANGELOG.md index 0098db042d..5d5a40da22 100644 --- a/explorer/CHANGELOG.md +++ b/explorer/CHANGELOG.md @@ -2,7 +2,7 @@ - nothing yet -## [nym-explorer-v1.0.5](https://github.com/nymtech/nym/tree/nym-explorer-v1.0.5) (2023-02-07) +## [nym-explorer-v1.0.5](https://github.com/nymtech/nym/tree/nym-explorer-v1.0.5) (2023-02-14) - NE - link `Owner` field on the node detail page to the account details on NG explorer ([#2923]) - NE - Upgrade Sandbox and make below changes: ([#2332]) diff --git a/nym-connect/CHANGELOG.md b/nym-connect/CHANGELOG.md index 2d3331f27e..7c67f24f36 100644 --- a/nym-connect/CHANGELOG.md +++ b/nym-connect/CHANGELOG.md @@ -2,14 +2,15 @@ ## UNRELEASED -## [nym-connect-v1.1.9](https://github.com/nymtech/nym/tree/nym-connect-v1.1.9) (2023-02-07) +## [nym-connect-v1.1.9](https://github.com/nymtech/nym/tree/nym-connect-v1.1.9) (2023-02-14) - Button animations ([#2949]) - add effect when the button is clicked ([#2947]) - UI to select gateways based on some performance criteria by checking gateways' routing score from nym-api ([#2942]) - client health check when connecting ([#2859]) -- allow user to select own gateway +- allow user to select own gateway ([#2952]) +[#2952]: https://github.com/nymtech/nym/issues/2952 [#2949]: https://github.com/nymtech/nym/issues/2949 [#2947]: https://github.com/nymtech/nym/issues/2947 [#2942]: https://github.com/nymtech/nym/issues/2942 diff --git a/nym-wallet/CHANGELOG.md b/nym-wallet/CHANGELOG.md index 4acc10ce22..8dd815a758 100644 --- a/nym-wallet/CHANGELOG.md +++ b/nym-wallet/CHANGELOG.md @@ -4,10 +4,14 @@ ## [nym-wallet-v1.1.9](https://github.com/nymtech/nym/releases/tag/nym-wallet-v1.1.9) (2023-02-14) -- Allow more flexibility for user when setting passwords -- User feedback on weak passwords -- User no longer has to copy mnemonic to continune account creation -- Updated instructional steps for creating accounts with a password +- Allow more flexibility for user when setting passwords ([#2993]) +- User feedback on weak passwords ([#2993]) +- User no longer has to copy mnemonic to continune account creation ([#2948]) +- Updated instructional steps for creating accounts with a password ([#2962]) + +[#2948]: https://github.com/nymtech/nym/issues/2948 +[#2993]: https://github.com/nymtech/nym/issues/2993 +[#2962]: https://github.com/nymtech/nym/issues/2962 ## [nym-wallet-v1.1.8](https://github.com/nymtech/nym/releases/tag/nym-wallet-v1.1.8) (2023-01-24)