Skip to content

Commit

Permalink
feat: Optimize the process of importing wallets via phrase seeds (#3200)
Browse files Browse the repository at this point in the history
* feat: Optimize the process of importing wallets via phrase seeds

* feat: update

* fix: comments
  • Loading branch information
devchenyan authored Jul 15, 2024
1 parent 79df3c0 commit 6b9b2bc
Show file tree
Hide file tree
Showing 11 changed files with 274 additions and 51 deletions.
1 change: 1 addition & 0 deletions packages/neuron-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"@ckb-lumos/rpc": "0.21.1",
"@ckb-lumos/base": "0.21.1",
"@ckb-lumos/codec": "0.21.1",
"@ckb-lumos/hd": "0.21.1",
"@ckb-lumos/helpers": "0.21.1",
"@ckb-lumos/config-manager": "0.21.1",
"@ckb-lumos/common-scripts": "0.21.1",
Expand Down
26 changes: 24 additions & 2 deletions packages/neuron-ui/src/components/WalletWizard/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,34 @@
import { useState, useCallback } from 'react'

const MNEMONIC_SENTENCE_WORDS = 12

export const useInputWords = () => {
const [inputsWords, setInputsWords] = useState<string[]>(new Array(12).fill(''))
const [inputsWords, setInputsWords] = useState<string[]>(new Array(MNEMONIC_SENTENCE_WORDS).fill(''))
const onChangeInput = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
(
e:
| React.ChangeEvent<HTMLInputElement>
| {
target: {
dataset: { idx: string }
value: string
}
}
) => {
const idx = Number(e.target.dataset.idx)
if (Number.isNaN(idx)) return
const { value } = e.target
if (Number(idx) === 0) {
const list = value
.trim()
.replace(/[^0-9a-z]+/g, ' ')
.split(' ')
if (list.length === MNEMONIC_SENTENCE_WORDS) {
setInputsWords(list)
return
}
}

setInputsWords(v => {
const newWords = [...v]
newWords[idx] = value
Expand Down
51 changes: 37 additions & 14 deletions packages/neuron-ui/src/components/WalletWizard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import i18n from 'utils/i18n'
import MnemonicInput from 'widgets/MnemonicInput'
import ReplaceDuplicateWalletDialog, { useReplaceDuplicateWallet } from 'components/ReplaceDuplicateWalletDialog'
import Alert from 'widgets/Alert'
import { Loading } from 'widgets/Icons/icon'
import { Loading, SuccessInfo, Error as ErrorIcon } from 'widgets/Icons/icon'
import TextField from 'widgets/TextField'
import { showGlobalAlertDialog, useDispatch } from 'states'
import { importedWalletDialogShown } from 'services/localCache'
Expand Down Expand Up @@ -182,26 +182,26 @@ const Welcome = ({ rootPath = '/wizard/', wallets = [], dispatch }: WizardElemen

Welcome.displayName = 'Welcome'

const typeHits: Record<MnemonicAction, string> = {
[MnemonicAction.Create]: 'wizard.write-down-seed',
[MnemonicAction.Verify]: 'wizard.input-seed-verify',
[MnemonicAction.Import]: '',
}

const Mnemonic = ({ state = initState, rootPath = '/wizard/', dispatch }: WizardElementProps) => {
const { generated, imported } = state
const navigate = useNavigate()
const { type = MnemonicAction.Create } = useParams<{ type: MnemonicAction }>()
const [t] = useTranslation()
const isCreate = type === MnemonicAction.Create
const message = isCreate ? 'wizard.your-wallet-seed-is' : 'wizard.input-your-seed'
const message = {
[MnemonicAction.Create]: 'wizard.your-wallet-seed-is',
[MnemonicAction.Verify]: 'wizard.replenish-your-seed',
[MnemonicAction.Import]: 'wizard.input-your-seed',
}[type]
const { inputsWords, onChangeInput, setInputsWords } = useInputWords()
const [searchParams] = useSearchParams()
const disableNext =
(type === MnemonicAction.Import && inputsWords.some(v => !v)) ||
(type === MnemonicAction.Verify && generated !== inputsWords.join(' '))

const [step, changeStep] = useState(0)
const [blankIndexes, setBlankIndexes] = useState<number[]>([])

useEffect(() => {
if (type === MnemonicAction.Create) {
generateMnemonic().then(res => {
Expand All @@ -210,7 +210,15 @@ const Mnemonic = ({ state = initState, rootPath = '/wizard/', dispatch }: Wizard
type: 'generated',
payload: res.result,
})
setInputsWords(new Array(12).fill(''))
const uniqueRandomArray = new Set<number>()
while (uniqueRandomArray.size < 3) {
const randomInt = Math.floor(Math.random() * 12)
uniqueRandomArray.add(randomInt)
}
const nums = [...uniqueRandomArray]
const list = res.result.split(' ').map((item: string, index: number) => (nums.includes(index) ? '' : item))
setBlankIndexes(nums)
setInputsWords(list)
}
})
} else {
Expand All @@ -219,7 +227,7 @@ const Mnemonic = ({ state = initState, rootPath = '/wizard/', dispatch }: Wizard
payload: '',
})
}
}, [dispatch, type, navigate])
}, [dispatch, type, navigate, setBlankIndexes])

const globalDispatch = useDispatch()

Expand Down Expand Up @@ -285,17 +293,32 @@ const Mnemonic = ({ state = initState, rootPath = '/wizard/', dispatch }: Wizard
</div>
)}
<div className={styles.text}>{t(message)}</div>
{type === MnemonicAction.Import ? (
<CreateFirstWalletNav />
) : (
<div className={styles.hint}>{t(typeHits[type])}</div>
{type === MnemonicAction.Import && <CreateFirstWalletNav />}
{type === MnemonicAction.Create && (
<div className={styles.createCommend}>
<div className={styles.commendItem}>
<SuccessInfo type="success" />
{t('wizard.handwritten-recommended')}
</div>
<div className={styles.commendItem}>
<ErrorIcon />
{t('wizard.do-not-copy')}
</div>
<div className={styles.commendItem}>
<ErrorIcon />
{t('wizard.do-not-save-scrrenshots')}
</div>
</div>
)}
{type === MnemonicAction.Verify && <div className={styles.hint}>{t('wizard.input-seed-verify')}</div>}
<MnemonicInput
disabled={isCreate}
words={generated}
inputsWords={inputsWords}
onChangeInputWord={onChangeInput}
blankIndexes={MnemonicAction.Import ? undefined : blankIndexes}
/>
{type === MnemonicAction.Import && <div className={styles.tips}>{t('wizard.input-seed-first-empty-space')}</div>}
<div className={styles.actions}>
<Button type="submit" label={t('wizard.next')} onClick={onNext} disabled={disableNext} />
<Button type="text" label={t('wizard.back')} onClick={onBack} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,27 @@ $line-gap: 15px;
.actions {
@include form-footer;
}
.createCommend {
margin: 24px 0 34px;
display: flex;
width: 100%;
justify-content: center;
align-items: center;
gap: 32px;
.commendItem {
display: flex;
gap: 4px;
align-items: center;
color: var(--error-color);
&:first-child {
color: var(--secondary-text-color);
}
svg {
width: 16px;
height: 16px;
}
}
}
}

@keyframes rotating {
Expand All @@ -110,12 +131,16 @@ $line-gap: 15px;

.title {
@include header-title;
margin-bottom: 16px;
max-width: 611px;
margin: 0 auto 16px;
}

.input {
width: 500px;
margin: 0 auto;
input {
font-family: 'Inter-Regular';
}
}

.inputNotice {
Expand All @@ -141,16 +166,22 @@ $line-gap: 15px;

.hint {
font-size: 16px;
font-weight: 500;
line-height: 22px;
color: var(--secondary-text-color);
margin-top: 16px;
margin-bottom: 40px;
& > a {
color: var(--link-color);
text-decoration: none;
}
}

.tips {
font-size: 14px;
color: var(--secondary-text-color);
margin-top: 12px;
}

.steps {
display: flex;
flex-direction: row;
Expand Down
14 changes: 9 additions & 5 deletions packages/neuron-ui/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -182,15 +182,19 @@
"input-your-seed": "Please input your wallet seed",
"password": "Password",
"confirm-password": "Confirm Password",
"set-wallet-name-and-password": "Name your new wallet, and choose a strong password to protect it",
"set-wallet-name": "Give your new wallet a name",
"set-a-strong-password-to-protect-your-wallet": "Create a strong password to protect your wallet",
"set-wallet-name-and-password": "Please name your wallet on this device and choose a strong password to protect it",
"set-wallet-name": "Set a name for the wallet",
"set-a-strong-password-to-protect-your-wallet": "Please set a strong password to protect your wallet",
"wallet-suffix": "Wallet {{suffix}}",
"write-down-seed": "Write down your wallet seed and save it in a safe place",
"handwritten-recommended": "Handwritten transcription recommended",
"do-not-copy": "Do not copy",
"do-not-save-scrrenshots": "Do not save scrrenshots",
"replenish-your-seed": "Please replenish your wallet seed",
"new-name": "Use an unused name for the new wallet",
"complex-password": "The password should be 8 to 50 characters long containing at least three character categories among the following: uppercase letters, lowercase letters, numbers, and special symbols.",
"same-password": "The password and confirm password should match",
"input-seed-verify": "Input created seed to verify",
"input-seed-verify": "Please enter the correct wallet seed or click back to recreate the wallet",
"input-seed-first-empty-space": "You can paste the entire wallet seed to the first empty space",
"no-wallet": "No wallet?",
"create-wallet": "Create Wallet",
"repeat-password": "Repeat Password",
Expand Down
14 changes: 9 additions & 5 deletions packages/neuron-ui/src/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,19 @@
"input-your-seed": "Por favor introduce la frase semilla de tu billetera",
"password": "Contraseña",
"confirm-password": "Confirmar Contraseña",
"set-wallet-name-and-password": "Nombra tu nueva billetera y elige una contraseña segura para protegerla",
"set-wallet-name": "Dale un nombre a tu nueva billetera",
"set-a-strong-password-to-protect-your-wallet": "Crea una contraseña segura para proteger tu billetera",
"set-wallet-name-and-password": "Por favor, nombra tu billetera en este dispositivo y elige una contraseña fuerte para protegerla",
"set-wallet-name": "Establece un nombre para la billetera",
"set-a-strong-password-to-protect-your-wallet": "Por favor, establece una contraseña fuerte para proteger tu billetera",
"wallet-suffix": "Billetera {{suffix}}",
"write-down-seed": "Escribe la frase semilla de tu billetera y guárdala en un lugar seguro",
"handwritten-recommended": "Se recomienda transcripción a mano",
"do-not-copy": "No copiar",
"do-not-save-scrrenshots": "No guardar capturas de pantalla",
"replenish-your-seed": "Por favor, repón la semilla de tu billetera",
"new-name": "Usa un nombre no usado previamente para la nueva billetera",
"complex-password": "La contraseña debe tener entre 8 y 50 caracteres y contener al menos tres categorías de caracteres entre las siguientes: letras en mayúscula, letras en minúscula, números y símbolos especiales.",
"same-password": "La contraseña y la confirmación de contraseña deben coincidir",
"input-seed-verify": "Ingresa la frase semilla creada para verificar",
"input-seed-verify": "Por favor, ingresa la semilla correcta de la billetera o haz clic en regresar para recrear la billetera",
"input-seed-first-empty-space": "Puede pegar toda la semilla del monedero en el primer espacio vacío",
"no-wallet": "¿No tienes una billetera?",
"create-wallet": "Crear Billetera",
"repeat-password": "Repetir Contraseña",
Expand Down
14 changes: 9 additions & 5 deletions packages/neuron-ui/src/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -182,15 +182,19 @@
"input-your-seed": "Veuillez entrer votre graine de Wallet",
"password": "Mot de passe",
"confirm-password": "Confirmer le mot de passe",
"set-wallet-name-and-password": "Nommez votre nouveau Wallet et choisissez un mot de passe fort pour le protéger",
"set-wallet-name": "Donnez un nom à votre nouveau Wallet",
"set-a-strong-password-to-protect-your-wallet": "Créez un mot de passe fort pour protéger votre Wallet",
"set-wallet-name-and-password": "Veuillez nommer votre portefeuille sur cet appareil et choisir un mot de passe fort pour le protéger",
"set-wallet-name": "Définissez un nom pour le portefeuille",
"set-a-strong-password-to-protect-your-wallet": "Veuillez définir un mot de passe fort pour protéger votre portefeuille",
"wallet-suffix": "Wallet {{suffix}}",
"write-down-seed": "Notez votre graine de Wallet et enregistrez-la dans un endroit sûr",
"handwritten-recommended": "Transcription manuscrite recommandée",
"do-not-copy": "Ne pas copier",
"do-not-save-scrrenshots": "Ne pas sauvegarder de captures d'écran",
"replenish-your-seed": "Veuillez reconstituer la graine de votre portefeuille",
"new-name": "Utilisez un nom inutilisé pour le nouveau Wallet",
"complex-password": "Le mot de passe doit contenir entre 8 et 50 caractères, comprenant au moins trois catégories parmi les suivantes : lettres majuscules, lettres minuscules, chiffres et symboles spéciaux.",
"same-password": "Le mot de passe et la confirmation du mot de passe doivent correspondre",
"input-seed-verify": "Saisissez la graine créée pour vérification",
"input-seed-verify": "Veuillez entrer la graine correcte du portefeuille ou cliquez sur retour pour recréer le portefeuille",
"input-seed-first-empty-space": "Vous pouvez coller l'intégralité de la graine du portefeuille dans le premier espace vide",
"no-wallet": "Pas de Wallet ?",
"create-wallet": "Créer un Wallet",
"repeat-password": "Répéter le mot de passe",
Expand Down
14 changes: 9 additions & 5 deletions packages/neuron-ui/src/locales/zh-tw.json
Original file line number Diff line number Diff line change
Expand Up @@ -176,15 +176,19 @@
"input-your-seed": "請輸入您的助記詞",
"password": "密碼",
"confirm-password": "確認密碼",
"set-wallet-name-and-password": "為新錢包命名,並設置密碼",
"set-wallet-name": "為錢包設定名稱",
"set-a-strong-password-to-protect-your-wallet": "請設定一個强密碼用於保護您的錢包",
"set-wallet-name-and-password": "請在此設備上為您的錢包命名,並選擇一個強密碼來保護它",
"set-wallet-name": "為錢包設置一個名稱",
"set-a-strong-password-to-protect-your-wallet": "請設置一個強密碼來保護您的錢包",
"wallet-suffix": "錢包 {{suffix}}",
"write-down-seed": "請記下您的助記詞並保存到安全的地方",
"handwritten-recommended": "推薦手寫抄錄",
"do-not-copy": "不要複製",
"do-not-save-scrrenshots": "不要保存截圖",
"replenish-your-seed": "請補充您的助記詞",
"new-name": "輸入新的錢包名稱",
"complex-password": "密碼為 8 至 50 字元由大寫字母、小寫字母、數位、特殊符號中至少三種字元組成的字串。",
"same-password": "兩次輸入密碼應一致",
"input-seed-verify": "輸入新生成的助記詞進行驗證",
"input-seed-verify": "請輸入正確的助記詞或點擊返回重新創建錢包",
"input-seed-first-empty-space": "您可以將整個錢包助記詞粘貼到第一個空格處",
"no-wallet": "還沒有錢包?",
"create-wallet": "立即創建新錢包",
"repeat-password": "重復密碼",
Expand Down
14 changes: 9 additions & 5 deletions packages/neuron-ui/src/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,19 @@
"input-your-seed": "请输入您的助记词",
"password": "密码",
"confirm-password": "确认密码",
"set-wallet-name-and-password": "为新钱包命名, 并设置密码",
"set-wallet-name": "为钱包设置名称",
"set-a-strong-password-to-protect-your-wallet": "请设置一个强密码用于保护您的钱包",
"set-wallet-name-and-password": "请在此设备上为您的钱包命名,并选择一个强密码来保护它",
"set-wallet-name": "为钱包设置一个名称",
"set-a-strong-password-to-protect-your-wallet": "请设置一个强密码来保护您的钱包",
"wallet-suffix": "钱包 {{suffix}}",
"write-down-seed": "请记下您的助记词并保存到安全的地方",
"handwritten-recommended": "推荐手写抄录",
"do-not-copy": "不要复制",
"do-not-save-scrrenshots": "不要保存截图",
"replenish-your-seed": "请补充您的助记词",
"new-name": "输入新的钱包名称",
"complex-password": "密码为 8 至 50 位由大写字母、小写字母、数字、特殊符号中至少三类字符组成的字符串。",
"same-password": "两次输入密码应一致",
"input-seed-verify": "输入新生成的助记词进行验证",
"input-seed-verify": "请输入正确的助记词或点击返回重新创建钱包",
"input-seed-first-empty-space": "您可以将整个钱包助记词粘贴到第一个空格处",
"no-wallet": "还没有钱包?",
"create-wallet": "立即创建新钱包",
"repeat-password": "重复密码",
Expand Down
Loading

2 comments on commit 6b9b2bc

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Packaging for test is done in 9936271480

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Packaging for test is done in 9936271634

Please sign in to comment.