Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
23 changes: 17 additions & 6 deletions packages/neuron-ui/src/components/CellManagement/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CkbAppNotFoundException, DeviceNotFoundException } from 'exceptions'
import { CkbAppNotFoundException, DeviceNotFoundException, DeviceNotMatchWalletException } from 'exceptions'
import { TFunction } from 'i18next'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { useNavigate } from 'react-router-dom'
Expand Down Expand Up @@ -415,7 +415,10 @@ export const useHardWallet = ({ wallet, t }: { wallet: State.WalletIdentity; t:
}, [])
const [error, setError] = useState<ErrorCode | string | undefined>()
const isNotAvailable = useMemo(() => {
return error === ErrorCode.DeviceNotFound || error === ErrorCode.CkbAppNotFound
return (
typeof error === 'number' &&
[ErrorCode.DeviceNotFound, ErrorCode.CkbAppNotFound, ErrorCode.DeviceNotMatchWallet].includes(error)
)
}, [error])

const [deviceInfo, setDeviceInfo] = useState(wallet.device)
Expand All @@ -424,14 +427,16 @@ export const useHardWallet = ({ wallet, t }: { wallet: State.WalletIdentity; t:
const ensureDeviceAvailable = useCallback(
async (device: State.DeviceInfo) => {
try {
const connectionRes = await connectDevice(device)
const connectionRes = await connectDevice({ ...device, walletID: wallet.id })
Comment thread
Keith-CY marked this conversation as resolved.
let { descriptor } = device
if (!isSuccessResponse(connectionRes)) {
// for win32, opening or closing the ckb app changes the HID descriptor(deviceInfo),
// so if we can't connect to the device, we need to re-search device automatically.
// for unix, the descriptor never changes unless user plugs the device into another USB port,
// in that case, mannauly re-search device one time will do.
if (isWin32) {
if (connectionRes.status === ErrorCode.DeviceNotMatchWallet) {
throw new DeviceNotMatchWalletException()
} else if (isWin32) {
setIsReconnecting(true)
const devicesRes = await getDevices(device)
setIsReconnecting(false)
Expand Down Expand Up @@ -467,13 +472,17 @@ export const useHardWallet = ({ wallet, t }: { wallet: State.WalletIdentity; t:
setError(undefined)
return true
} catch (err) {
if (err instanceof CkbAppNotFoundException || err instanceof DeviceNotFoundException) {
if (
err instanceof CkbAppNotFoundException ||
err instanceof DeviceNotFoundException ||
err instanceof DeviceNotMatchWalletException
) {
setError(err.code)
}
return false
}
},
[isWin32]
[isWin32, wallet]
)

const reconnect = useCallback(async () => {
Expand Down Expand Up @@ -515,6 +524,8 @@ export const useHardWallet = ({ wallet, t }: { wallet: State.WalletIdentity; t:
return t('hardware-verify-address.status.disconnect')
case ErrorCode.CkbAppNotFound:
return t(CkbAppNotFoundException.message)
case ErrorCode.DeviceNotMatchWallet:
return t(DeviceNotMatchWalletException.message)
default:
return error
}
Expand Down
15 changes: 10 additions & 5 deletions packages/neuron-ui/src/components/HardwareSign/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CkbAppNotFoundException, DeviceNotFoundException } from 'exceptions'
import { CkbAppNotFoundException, DeviceNotFoundException, DeviceNotMatchWalletException } from 'exceptions'
import { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useNavigate } from 'react-router-dom'
Expand Down Expand Up @@ -69,9 +69,10 @@ export default ({
const userInputStatus = t('hardware-sign.status.user-input')
const disconnectStatus = t('hardware-sign.status.disconnect')
const ckbAppNotFoundStatus = t(CkbAppNotFoundException.message)
const deviceNotMatchWalletStatus = t(DeviceNotMatchWalletException.message)
const isNotAvailableToSign = useMemo(() => {
return status === disconnectStatus || status === ckbAppNotFoundStatus
}, [status, disconnectStatus, ckbAppNotFoundStatus])
return status === disconnectStatus || status === ckbAppNotFoundStatus || status === deviceNotMatchWalletStatus
}, [status, disconnectStatus, ckbAppNotFoundStatus, deviceNotMatchWalletStatus])
const [error, setError] = useState('')
const [deviceInfo, setDeviceInfo] = useState(wallet.device!)
const [isReconnecting, setIsReconnecting] = useState(false)
Expand Down Expand Up @@ -162,14 +163,16 @@ export default ({
const ensureDeviceAvailable = useCallback(
async (device: DeviceInfo) => {
try {
const connectionRes = await connectDevice(device)
const connectionRes = await connectDevice({ ...device, walletID: wallet.id })
let { descriptor } = device
if (!isSuccessResponse(connectionRes)) {
// for win32, opening or closing the ckb app changes the HID descriptor(deviceInfo),
// so if we can't connect to the device, we need to re-search device automatically.
// for unix, the descriptor never changes unless user plugs the device into another USB port,
// in that case, mannauly re-search device one time will do.
if (isWin32) {
if (connectionRes.status === ErrorCode.DeviceNotMatchWallet) {
throw new DeviceNotMatchWalletException()
} else if (isWin32) {
setIsReconnecting(true)
const devicesRes = await getDevices(device)
setIsReconnecting(false)
Expand Down Expand Up @@ -206,6 +209,8 @@ export default ({
} catch (err) {
if (err instanceof CkbAppNotFoundException) {
setStatus(ckbAppNotFoundStatus)
} else if (err instanceof DeviceNotMatchWalletException) {
setStatus(deviceNotMatchWalletStatus)
} else {
setStatus(disconnectStatus)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
getPlatform,
} from 'services/remote'
import { ErrorCode, clsx, errorFormatter, isSuccessResponse, addressToAddress, useDidMount } from 'utils'
import { CkbAppNotFoundException, DeviceNotFoundException } from 'exceptions'
import { CkbAppNotFoundException, DeviceNotFoundException, DeviceNotMatchWalletException } from 'exceptions'
import Alert from 'widgets/Alert'
import styles from './receive.module.scss'

Expand Down Expand Up @@ -42,9 +42,14 @@ const VerifyHardwareAddress = ({ address, wallet, onClose = () => {} }: VerifyHa
const userInputStatus = t('hardware-verify-address.status.user-input')
const disconnectStatus = t('hardware-verify-address.status.disconnect')
const ckbAppNotFoundStatus = t(CkbAppNotFoundException.message)
const deviceNotMatchWalletStatus = t(DeviceNotMatchWalletException.message)
const isNotAvailableToVerify = useMemo(() => {
return status?.message === disconnectStatus || status?.message === ckbAppNotFoundStatus
}, [status, disconnectStatus, ckbAppNotFoundStatus])
return (
status?.message === disconnectStatus ||
status?.message === ckbAppNotFoundStatus ||
status?.message === deviceNotMatchWalletStatus
)
}, [status, disconnectStatus, ckbAppNotFoundStatus, deviceNotMatchWalletStatus])

const [deviceInfo, setDeviceInfo] = useState(wallet.device!)
const [isReconnecting, setIsReconnecting] = useState(false)
Expand All @@ -55,14 +60,16 @@ const VerifyHardwareAddress = ({ address, wallet, onClose = () => {} }: VerifyHa
const ensureDeviceAvailable = useCallback(
async (device: DeviceInfo) => {
try {
const connectionRes = await connectDevice(device)
const connectionRes = await connectDevice({ ...device, walletID: wallet.id })
let { descriptor } = device
if (!isSuccessResponse(connectionRes)) {
// for win32, opening or closing the ckb app changes the HID descriptor(deviceInfo),
// so if we can't connect to the device, we need to re-search device automatically.
// for unix, the descriptor never changes unless user plugs the device into another USB port,
// in that case, mannauly re-search device one time will do.
if (isWin32) {
if (connectionRes.status === ErrorCode.DeviceNotMatchWallet) {
throw new DeviceNotMatchWalletException()
} else if (isWin32) {
setIsReconnecting(true)
const devicesRes = await getDevices(device)
setIsReconnecting(false)
Expand Down Expand Up @@ -99,12 +106,14 @@ const VerifyHardwareAddress = ({ address, wallet, onClose = () => {} }: VerifyHa
} catch (err) {
if (err instanceof CkbAppNotFoundException) {
setStatus({ type: 'error', message: ckbAppNotFoundStatus })
} else if (err instanceof DeviceNotMatchWalletException) {
setStatus({ type: 'error', message: deviceNotMatchWalletStatus })
} else {
setStatus({ type: 'error', message: disconnectStatus })
}
}
},
[disconnectStatus, ckbAppNotFoundStatus, isWin32]
[disconnectStatus, ckbAppNotFoundStatus, isWin32, wallet]
)

const reconnect = useCallback(async () => {
Expand Down
10 changes: 10 additions & 0 deletions packages/neuron-ui/src/exceptions/hardware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,13 @@ export class MultiDeviceException extends Error {
super(`${I18N_PATH}${ErrorCode.MultiDevice}`)
}
}

export class DeviceNotMatchWalletException extends Error {
public code = ErrorCode.DeviceNotMatchWallet

static message = `${I18N_PATH}${ErrorCode.DeviceNotMatchWallet}`

constructor() {
super(DeviceNotMatchWalletException.message)
}
}
1 change: 1 addition & 0 deletions packages/neuron-ui/src/locales/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,7 @@
"402": "تطبيق CKB غير مفتوح. يرجى فتح تطبيق CKB على جهازك.",
"403": "لم يتم اكتشاف أي جهاز. يرجى توصيل جهازك",
"404": "تم اكتشاف أجهزة متعددة. يمكن توصيل جهاز واحد فقط من نفس الطراز.",
"408": "المحفظة الصلبة المتصلة حاليًا لا تتطابق مع المحفظة الحالية.",
"600": "يرجى التأكد من أن المزامنة قد انتهت قبل القيام بأي عملية متعلقة بالمعاملات."
}
},
Expand Down
1 change: 1 addition & 0 deletions packages/neuron-ui/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,7 @@
"402": "CKB App does not open. Please open the CKB App on your device.",
"403": "No device detected. Please connect your device",
"404": "Multiple device detected. Only one device of the same model can be connected.",
"408": "The hardware wallet currently connected does not match the current wallet.",
"600": "Please make sure the sync has finalized before you do any transaction related operation."
}
},
Expand Down
1 change: 1 addition & 0 deletions packages/neuron-ui/src/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,7 @@
"402": "La aplicación CKB no se abre. Abra la aplicación CKB en su dispositivo.",
"403": "No se detectó ningún dispositivo. Por favor conecte su dispositivo",
"404": "Se detectaron varios dispositivos. Sólo se puede conectar un dispositivo del mismo modelo.",
"408": "La billetera de hardware conectada actualmente no coincide con la billetera actual.",
"600": "Asegúrese de que la sincronización haya finalizado antes de realizar cualquier operación relacionada con transacciones."
}
},
Expand Down
1 change: 1 addition & 0 deletions packages/neuron-ui/src/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,7 @@
"402": "L'application CKB n'est pas ouverte. Veuillez ouvrir l'application CKB sur votre appareil.",
"403": "Aucun appareil détecté. Veuillez connecter votre appareil",
"404": "Plusieurs appareils détectés. Un seul appareil du même modèle peut être connecté.",
"408": "Le portefeuille matériel actuellement connecté ne correspond pas au portefeuille actuel.",
"600": "Veuillez vous assurer que la synchronisation est finalisée avant d'effectuer toute opération liée à une transaction."
}
},
Expand Down
1 change: 1 addition & 0 deletions packages/neuron-ui/src/locales/zh-tw.json
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,7 @@
"402": "CKB 應用未打開。請在妳的設備打開 CKB 應用。",
"403": "未檢測到設備,請檢查妳的設備連接",
"404": "檢測到多個設備,同一型號的設備只能同時連接一個。",
"408": "當前連接的硬體錢包與當前錢包不匹配。",
"600": "做任何交易相關的錢包操作前請先確保同步已完成。"
}
},
Expand Down
1 change: 1 addition & 0 deletions packages/neuron-ui/src/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,7 @@
"402": "CKB 应用未打开。请在你的设备打开 CKB 应用。",
"403": "未检测到设备,请检查你的设备连接",
"404": "检查到多个设备,同一型号的设备只能同时连接一个。",
"408": "当前连接的硬件钱包与当前钱包不匹配。",
"600": "做任何交易相关的钱包操作前请先确保同步已完成。"
}
},
Expand Down
2 changes: 1 addition & 1 deletion packages/neuron-ui/src/services/remote/hardware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const getDevices = remoteApi<Model | null, DeviceInfo[]>('detect-device')
export const getDeviceCkbAppVersion = remoteApi<Descriptor, Version>('get-device-ckb-app-version')
export const getDeviceExtendedPublickey = remoteApi<void, ExtendedPublicKey>('get-device-extended-public-key')
export const getDevicePublicKey = remoteApi<void, PublicKey>('get-device-public-key')
export const connectDevice = remoteApi<DeviceInfo, void>('connect-device')
export const connectDevice = remoteApi<DeviceInfo & { walletID?: string }, void>('connect-device')
export const createHardwareWallet = remoteApi<ExtendedPublicKey & { walletName: string }, State.Wallet>(
'create-hardware-wallet'
)
1 change: 1 addition & 0 deletions packages/neuron-ui/src/utils/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ export enum ErrorCode {
UnknownError = 405,
SignMessageFailed = 406,
UnsupportedManufacturer = 407,
DeviceNotMatchWallet = 408,
// offline
DeviceInSleep = 501,
// active warning
Expand Down
4 changes: 2 additions & 2 deletions packages/neuron-wallet/src/controllers/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -945,8 +945,8 @@ export default class ApiController {
})

// Hardware wallet
handle('connect-device', async (_, deviceInfo: DeviceInfo) => {
await this.#hardwareController.connectDevice(deviceInfo)
handle('connect-device', async (_, params: DeviceInfo & { walletID?: string }) => {
await this.#hardwareController.connectDevice(params)
})

handle('detect-device', async (_, model: Pick<DeviceInfo, 'manufacturer' | 'product'>) => {
Expand Down
14 changes: 12 additions & 2 deletions packages/neuron-wallet/src/controllers/hardware.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
import { DeviceInfo, ExtendedPublicKey, PublicKey } from '../services/hardware/common'
import { ResponseCode } from '../utils/const'
import HardwareWalletService from '../services/hardware'
import { connectDeviceFailed } from '../exceptions'
import WalletService from '../services/wallets'
import { connectDeviceFailed, DeviceNotMatchWallet } from '../exceptions'
import { hd } from '@ckb-lumos/lumos'

export default class HardwareController {
public async connectDevice(deviceInfo: DeviceInfo): Promise<Controller.Response<void>> {
public async connectDevice(params: DeviceInfo & { walletID?: string }): Promise<Controller.Response<void>> {
const { walletID, ...deviceInfo } = params
const device = await HardwareWalletService.getInstance().initHardware(deviceInfo)
try {
await device!.connect()
} catch (error) {
throw new connectDeviceFailed(error.message)
}

if (walletID) {
const walletPK = WalletService.getInstance().get(walletID).accountExtendedPublicKey()
const devicePK = await device.getExtendedPublicKey()
if (!walletPK.publicKey.includes(devicePK.publicKey)) {
throw new DeviceNotMatchWallet()
}
}

return {
status: ResponseCode.Success,
}
Expand Down
4 changes: 4 additions & 0 deletions packages/neuron-wallet/src/exceptions/hardware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,7 @@ export class UnsupportedManufacturer extends Error {
super(t('messages.unsupported-manufacturer', { manufacturer }))
}
}

export class DeviceNotMatchWallet extends Error {
public code = 408
}