Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specific package for ledger #3277

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
feat: Support import hardware wallet 24-bit seed (#3275)
  • Loading branch information
yanguoyu authored Dec 12, 2024
commit 9dca6ebd0d47cdead090ec3056523ae4e3bd3d0b
5 changes: 3 additions & 2 deletions packages/neuron-ui/src/components/Receive/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,9 @@ export const AddressQrCodeWithCopyZone = ({
const Receive = ({ onClose, address }: { onClose?: () => void; address?: string }) => {
const [t] = useTranslation()
const { wallet } = useGlobalState()
const { addresses } = wallet
const { addresses, isHD } = wallet
const isSingleAddress = addresses.length === 1
const isHardwareWallet = !isHD && isSingleAddress

const accountAddress = useMemo(() => {
if (isSingleAddress) {
Expand Down Expand Up @@ -128,7 +129,7 @@ const Receive = ({ onClose, address }: { onClose?: () => void; address?: string
onClick={() => setIsInShortFormat(is => !is)}
/>

{isSingleAddress && <VerifyHardwareAddress address={accountAddress} wallet={wallet} onClose={onClose} />}
{isHardwareWallet && <VerifyHardwareAddress address={accountAddress} wallet={wallet} onClose={onClose} />}
</div>
</Dialog>
)
Expand Down
9 changes: 6 additions & 3 deletions packages/neuron-ui/src/components/WalletWizard/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useState, useCallback } from 'react'
import { useState, useCallback, useEffect } from 'react'

const MNEMONIC_SENTENCE_WORDS = 12

export const useInputWords = () => {
const [inputsWords, setInputsWords] = useState<string[]>(new Array(MNEMONIC_SENTENCE_WORDS).fill(''))
export const useInputWords = (wordsCount: number = MNEMONIC_SENTENCE_WORDS) => {
const [inputsWords, setInputsWords] = useState<string[]>(new Array(wordsCount).fill(''))
const onChangeInput = useCallback(
(
e:
Expand Down Expand Up @@ -37,6 +37,9 @@ export const useInputWords = () => {
},
[setInputsWords]
)
useEffect(() => {
setInputsWords(new Array(wordsCount).fill(''))
}, [wordsCount])
return {
inputsWords,
onChangeInput,
Expand Down
18 changes: 16 additions & 2 deletions packages/neuron-ui/src/components/WalletWizard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ const initState: WithWizardState = {
password: '',
confirmPassword: '',
name: '',
isHardware: false,
}

const submissionInputs = [
Expand Down Expand Up @@ -182,6 +183,8 @@ const Welcome = ({ rootPath = '/wizard/', wallets = [], dispatch }: WizardElemen

Welcome.displayName = 'Welcome'

const LEDGER_WORDS_COUNT = 24

const Mnemonic = ({ state = initState, rootPath = '/wizard/', dispatch }: WizardElementProps) => {
const { generated, imported } = state
const navigate = useNavigate()
Expand All @@ -193,8 +196,9 @@ const Mnemonic = ({ state = initState, rootPath = '/wizard/', dispatch }: Wizard
[MnemonicAction.Verify]: 'wizard.replenish-your-seed',
[MnemonicAction.Import]: 'wizard.input-your-seed',
}[type]
const { inputsWords, onChangeInput, setInputsWords } = useInputWords()
const [searchParams] = useSearchParams()
const isHardware = searchParams.get('isHardware') === 'true'
const { inputsWords, onChangeInput, setInputsWords } = useInputWords(isHardware ? LEDGER_WORDS_COUNT : undefined)
const disableNext =
(type === MnemonicAction.Import && inputsWords.some(v => !v)) ||
(type === MnemonicAction.Verify && generated !== inputsWords.join(' '))
Expand Down Expand Up @@ -228,6 +232,14 @@ const Mnemonic = ({ state = initState, rootPath = '/wizard/', dispatch }: Wizard
})
}
}, [dispatch, type, navigate, setBlankIndexes])
useEffect(() => {
if (isHardware) {
dispatch({
type: 'isHardware',
payload: true,
})
}
}, [dispatch, isHardware])

const globalDispatch = useDispatch()

Expand Down Expand Up @@ -317,6 +329,7 @@ const Mnemonic = ({ state = initState, rootPath = '/wizard/', dispatch }: Wizard
inputsWords={inputsWords}
onChangeInputWord={onChangeInput}
blankIndexes={MnemonicAction.Import ? undefined : blankIndexes}
wordsCount={isHardware ? LEDGER_WORDS_COUNT : undefined}
/>
{type === MnemonicAction.Import && <div className={styles.tips}>{t('wizard.input-seed-first-empty-space')}</div>}
<div className={styles.actions}>
Expand All @@ -337,7 +350,7 @@ export const getAlertStatus = (fieldInit: boolean, success: boolean) => {
}

const Submission = ({ state = initState, wallets = [], dispatch }: WizardElementProps) => {
const { name, password, confirmPassword, imported } = state
const { name, password, confirmPassword, imported, isHardware } = state
const navigate = useNavigate()
const { type = MnemonicAction.Create } = useParams<{ type: MnemonicAction }>()
const [t] = useTranslation()
Expand Down Expand Up @@ -396,6 +409,7 @@ const Submission = ({ state = initState, wallets = [], dispatch }: WizardElement
name,
password,
mnemonic: imported,
isHardware,
}
openDialog()
setTimeout(() => {
Expand Down
12 changes: 9 additions & 3 deletions packages/neuron-ui/src/components/withWizard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,14 @@ export interface Element {
comp: React.FC<any>
}

export interface WithWizardState {
[key: string]: string
export type WithWizardState = {
generated: string
imported: string
password: string
confirmPassword: string
name: string
isHardware: boolean
[propName: string]: any
}

export interface WizardProps {
Expand All @@ -27,7 +33,7 @@ export interface WizardElementProps {
}

const reducer = (
state: { [key: string]: string },
state: WithWizardState,
{
type,
payload,
Expand Down
1 change: 1 addition & 0 deletions packages/neuron-ui/src/types/Controller/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ declare namespace Controller {
name: string
mnemonic: string
password: string
isHardware?: boolean
}

interface ImportKeystoreParams {
Expand Down
8 changes: 6 additions & 2 deletions packages/neuron-ui/src/widgets/MnemonicInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const MnemonicInput = ({
inputsWords,
onChangeInputWord,
blankIndexes,
wordsCount,
}: {
disabled?: boolean
words: string
Expand All @@ -23,10 +24,13 @@ const MnemonicInput = ({
}
}
) => void

wordsCount?: number
blankIndexes?: number[]
}) => {
const wordList = useMemo(() => Object.assign(new Array(12).fill(''), words?.split(' ')), [words])
const wordList = useMemo(
() => Object.assign(new Array(wordsCount ?? 12).fill(''), words?.split(' ')),
[words, wordsCount]
)
const [focusIndex, setFocusIndex] = useState(-1)
const mounted = useRef(true)
const root = useRef<HTMLDivElement>(null)
Expand Down
9 changes: 6 additions & 3 deletions packages/neuron-wallet/src/controllers/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -368,9 +368,12 @@ export default class ApiController {
return this.#walletsController.activate(id)
})

handle('import-mnemonic', async (_, params: { name: string; password: string; mnemonic: string }) => {
return this.#walletsController.importMnemonic(params)
})
handle(
'import-mnemonic',
async (_, params: { name: string; password: string; mnemonic: string; isHardware?: boolean }) => {
return this.#walletsController.importMnemonic(params)
}
)

handle('import-keystore', async (_, params: { name: string; password: string; keystorePath: string }) => {
return this.#walletsController.importKeystore(params)
Expand Down
7 changes: 7 additions & 0 deletions packages/neuron-wallet/src/controllers/app/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,13 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => {
importHardware(URL.ImportHardware)
},
},
{
id: 'import-hardware-seed',
label: t('application-menu.wallet.import-hardware-mnemonic'),
click: () => {
importHardware(`${URL.ImportMnemonic}?isHardware=true`)
},
},
],
},
separator,
Expand Down
7 changes: 6 additions & 1 deletion packages/neuron-wallet/src/controllers/wallets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,14 @@ export default class WalletsController {
name,
password,
mnemonic,
isHardware,
}: {
name: string
password: string
mnemonic: string
isHardware?: boolean
}): Promise<Controller.Response<Omit<WalletProperties, 'extendedKey'>>> {
return await this.createByMnemonic({ name, password, mnemonic, isImporting: true })
return await this.createByMnemonic({ name, password, mnemonic, isImporting: true, isHardware })
}

public async create({
Expand All @@ -95,11 +97,13 @@ export default class WalletsController {
password,
mnemonic,
isImporting,
isHardware,
}: {
name: string
password: string
mnemonic: string
isImporting: boolean
isHardware?: boolean
}): Promise<Controller.Response<Omit<WalletProperties, 'extendedKey'>>> {
if (!validateMnemonic(mnemonic)) {
throw new InvalidMnemonic()
Expand Down Expand Up @@ -139,6 +143,7 @@ export default class WalletsController {
extendedKey: accountExtendedPublicKey.serialize(),
keystore,
startBlockNumber: startBlockNumber,
hardwareFromSeed: isHardware,
})

wallet.checkAndGenerateAddresses(isImporting)
Expand Down
1 change: 1 addition & 0 deletions packages/neuron-wallet/src/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export default {
'import-keystore': 'Import from Keystore',
'import-xpubkey': 'Import Extended Public Key',
'import-hardware': 'Import Hardware Wallet',
'import-hardware-mnemonic': 'Import Hardware Wallet Seed',
},
edit: {
label: 'Edit',
Expand Down
1 change: 1 addition & 0 deletions packages/neuron-wallet/src/locales/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export default {
'import-keystore': 'Importar desde Keystore',
'import-xpubkey': 'Importar Clave Pública Extendida',
'import-hardware': 'Importar Billetera de Hardware',
'import-hardware-mnemonic': 'Importar semilla de billetera de hardware',
},
edit: {
label: 'Editar',
Expand Down
1 change: 1 addition & 0 deletions packages/neuron-wallet/src/locales/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export default {
'import-keystore': 'Importer depuis le fichier Keystore',
'import-xpubkey': 'Importer la clé publique étendue',
'import-hardware': 'Importer un Wallet matériel',
'import-hardware-mnemonic': 'Importer des semences de portefeuille matériel',
},
edit: {
label: 'Édition',
Expand Down
1 change: 1 addition & 0 deletions packages/neuron-wallet/src/locales/zh-tw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export default {
'import-keystore': '導入 Keystore 檔案',
'import-xpubkey': '導入 Extended Public Key',
'import-hardware': '導入硬體錢包',
'import-hardware-mnemonic': '導入硬體錢包助記詞',
},
edit: {
label: '編輯',
Expand Down
1 change: 1 addition & 0 deletions packages/neuron-wallet/src/locales/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export default {
'import-keystore': '导入 Keystore 文件',
'import-xpubkey': '导入 Extended Public Key',
'import-hardware': '导入硬件钱包',
'import-hardware-mnemonic': '导入硬件钱包助记词',
},
edit: {
label: '编辑',
Expand Down
4 changes: 4 additions & 0 deletions packages/neuron-wallet/src/models/keys/hd-public-key-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { scriptToAddress } from '../../utils/scriptAndAddress'
import SystemScriptInfo from '../../models/system-script-info'
import NetworksService from '../../services/networks'

export const ROOT_ADDRESS_INDEX = -1
export default class HdPublicKeyInfoModel {
public walletId: string
public addressType: hd.AddressType
Expand All @@ -22,6 +23,9 @@ export default class HdPublicKeyInfoModel {
}

public get path(): string {
if (this.addressIndex === ROOT_ADDRESS_INDEX) {
return hd.AccountExtendedPublicKey.ckbAccountPath
}
return hd.AccountExtendedPublicKey.pathFor(this.addressType, this.addressIndex)
}

Expand Down
Loading
Loading