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
2 changes: 1 addition & 1 deletion packages/connect-examples/electron-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "hardware-example",
"productName": "HardwareExample",
"executableName": "onekey-hardware-example",
"version": "1.0.24-alpha.2",
"version": "1.0.24-alpha.4",
"author": "OneKey",
"description": "End-to-end encrypted workspaces for teams",
"main": "dist/index.js",
Expand Down
2 changes: 2 additions & 0 deletions packages/connect-examples/expo-example/locale/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@
"message__no_device": "No device",
"message__current_selector_device": "Current selector device: ",
"message__search_device_and_connect_device": "Search device and connect device",
"message__connection_type": "Connection Type",
"message__use_webusb": "Use WebUSB",

"message__check_latest_ui_resource": "Check latest Ui resource...",
"message__download_latest_ui_resource": "Download latest Ui resource...",
Expand Down
2 changes: 2 additions & 0 deletions packages/connect-examples/expo-example/locale/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@
"message__no_device": "未连接设备",
"message__current_selector_device": "当前选择的设备:",
"message__search_device_and_connect_device": "搜索设备并连接设备",
"message__connection_type": "连接方式",
"message__use_webusb": "使用 WebUSB",

"message__check_latest_ui_resource": "检查最新 UI 资源...",
"message__download_latest_ui_resource": "下载最新 UI 资源中...",
Expand Down
10 changes: 5 additions & 5 deletions packages/connect-examples/expo-example/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "expo-example",
"version": "1.0.24-alpha.2",
"version": "1.0.24-alpha.4",
"scripts": {
"start": "CONNECT_SRC=https://localhost:8087/ yarn expo start --dev-client",
"android": "yarn expo run:android",
Expand All @@ -19,10 +19,10 @@
"@noble/ed25519": "^2.1.0",
"@noble/hashes": "^1.3.3",
"@noble/secp256k1": "^1.7.1",
"@onekeyfe/hd-ble-sdk": "^1.0.24-alpha.2",
"@onekeyfe/hd-common-connect-sdk": "^1.0.24-alpha.2",
"@onekeyfe/hd-core": "^1.0.24-alpha.2",
"@onekeyfe/hd-web-sdk": "^1.0.24-alpha.2",
"@onekeyfe/hd-ble-sdk": "^1.0.24-alpha.4",
"@onekeyfe/hd-common-connect-sdk": "^1.0.24-alpha.4",
"@onekeyfe/hd-core": "^1.0.24-alpha.4",
"@onekeyfe/hd-web-sdk": "^1.0.24-alpha.4",
"@onekeyfe/react-native-ble-plx": "3.0.0",
"@polkadot/util-crypto": "13.1.1",
"@react-native-async-storage/async-storage": "1.21.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { atom } from 'jotai';

// Connection type atom: 'bridge' | 'webusb'
export type ConnectionType = 'bridge' | 'webusb';

// Create an atom to store the connection type
export const connectionTypeAtom = atom<ConnectionType>('bridge');
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,15 @@ export default function CommonParamsView() {
onToggle={value => handleSetParam('useEmptyPassphrase', value)}
/>
<SwitchInput
// TODO: i18n
label="detectBootloaderDevice"
value={!!commonParams.detectBootloaderDevice}
onToggle={value => handleSetParam('detectBootloaderDevice', value)}
/>
<SwitchInput
label="skipWebDevicePrompt"
value={!!commonParams.skipWebDevicePrompt}
onToggle={value => handleSetParam('skipWebDevicePrompt', value)}
/>
</Stack>
</PanelView>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ import {
useState,
} from 'react';

import { ListItem, Text, View } from 'tamagui';
import { ListItem, Text, View, XStack } from 'tamagui';
import { FlatList, Platform } from 'react-native';
import { Picker } from '@react-native-picker/picker';
import { Check } from '@tamagui/lucide-icons';
import { useIntl } from 'react-intl';
import { useAtom } from 'jotai';
import type { Features } from '@onekeyfe/hd-transport';
import HardwareSDKContext from '../provider/HardwareSDKContext';
import { Button } from './ui/Button';
import PanelView from './ui/Panel';
import { getItem, removeItem, setItem } from '../utils/storeUtil';
import { connectionTypeAtom, ConnectionType } from '../atoms/deviceConnectAtoms';

export type Device = {
connectId: string;
Expand Down Expand Up @@ -98,6 +101,7 @@ function DeviceListFC(
const { sdk } = useContext(HardwareSDKContext);
const [selectedId, setSelectedId] = useState<string | null>(null);
const [devices, setDevices] = useState<Device[]>([]);
const [connectionType, setConnectionType] = useAtom(connectionTypeAtom);

useEffect(() => {
if (disableSaveDevice) return;
Expand All @@ -124,8 +128,7 @@ function DeviceListFC(
if (!sdk) return alert(intl.formatMessage({ id: 'tip__sdk_not_ready' }));

let response;
const env = 'webusb';
if (env === 'webusb') {
if (connectionType === 'webusb') {
const promptResponse = await sdk.promptWebDeviceAccess();
console.log('promptResponse:====>>>::: ', promptResponse);
response = promptResponse.success
Expand All @@ -140,13 +143,24 @@ function DeviceListFC(
const device = foundDevices[0];
selectDevice(device);
}
}, [intl, sdk, selectDevice]);
}, [intl, sdk, selectDevice, connectionType]);

const handleRemoveSelected = useCallback(() => {
removeSelectedId();
setSelectedId(null);
}, []);

const onSwitchConnectionType = useCallback(
async (value: ConnectionType) => {
console.log('value:====>>>::: ', value);
setConnectionType(value);
// @ts-expect-error
const res = await sdk?.switchTransport(value);
console.log('switchTransport res:====>>>::: ', res);
},
[sdk, setConnectionType]
);

useImperativeHandle(
ref,
() => ({
Expand Down Expand Up @@ -187,6 +201,20 @@ function DeviceListFC(
</View>
)}

<XStack marginVertical="$2" alignItems="center" gap={12}>
<Text fontSize={15} marginBottom="$1">
{intl.formatMessage({ id: 'message__connection_type' })}
</Text>
<Picker
selectedValue={connectionType}
onValueChange={onSwitchConnectionType}
style={{ width: 120, height: 44 }}
>
<Picker.Item label="Bridge" value="bridge" />
<Picker.Item label="WebUSB" value="webusb" />
</Picker>
</XStack>

<Button variant="primary" size="large" onPress={searchDevices}>
{intl.formatMessage({ id: 'action__search_device' })}
</Button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ export default function HandleSDKEvents() {
if (!SDK) return;

HardwareLowLevelSDK?.addHardwareGlobalEventListener(params => {
if (params.event === LOG_EVENT) {
console.log(params.payload.join(' '));
}
SDK.emit?.(params.event, { ...params });
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const defaultParams: CommonParams = {
passphraseState: '',
initSession: false,
detectBootloaderDevice: false,
skipWebDevicePrompt: false,
};

const CommonParamsContext = createContext<{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import memoizee from 'memoizee';
import { Platform } from 'react-native';
import { ConnectSettings, CoreApi, LowLevelCoreApi } from '@onekeyfe/hd-core';
import { importSdk } from './importSdk';
import { importSdk, importLowLevelSDK } from './importSdk';
import { CONNECT_SRC } from '../constants/connect';

// eslint-disable-next-line import/no-mutable-exports
let HardwareSDK: CoreApi;
let HardwareLowLevelSDK: LowLevelCoreApi;
let initialized = false;
const isNodeEnvironments = false;

export const getHardwareSDKInstance = memoizee(
async () =>
Expand All @@ -22,7 +21,6 @@ export const getHardwareSDKInstance = memoizee(
async (resolve, reject) => {
const useLowLevelApi = false;
if (initialized) {
// @ts-expect-error
resolve({ HardwareSDK, HardwareLowLevelSDK, useLowLevelApi });
return;
}
Expand All @@ -32,17 +30,14 @@ export const getHardwareSDKInstance = memoizee(
fetchConfig: true,
};

HardwareSDK = await importSdk({
useCommonSdk: true,
});
// HardwareSDK = await importTopLevelSdk();
HardwareSDK = await importSdk();
console.log(HardwareSDK);

if (Platform.OS === 'web') {
settings.connectSrc = CONNECT_SRC;
settings.env = 'webusb';
settings.env = 'web';
settings.preRelease = false;
// HardwareLowLevelSDK = await importLowLevelSDK();
HardwareLowLevelSDK = await importLowLevelSDK();

// Override Connect src
// @ts-expect-error
Expand All @@ -58,7 +53,6 @@ export const getHardwareSDKInstance = memoizee(
console.log('HardwareSDK initialized success');
initialized = true;

// @ts-expect-error
resolve({ HardwareSDK, HardwareLowLevelSDK, useLowLevelApi });
} catch (e) {
reject(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ interface ISdkImportOptions {
useCommonSdk?: boolean;
}

export const importSdk = async (options: ISdkImportOptions) => {
if (options.useCommonSdk) {
export const importSdk = async (options?: ISdkImportOptions) => {
if (options?.useCommonSdk) {
return (await import('@onekeyfe/hd-common-connect-sdk')).default as unknown as CoreApi;
}
return (await import('@onekeyfe/hd-web-sdk')).default.HardwareWebSdk as unknown as CoreApi;
};

export const importTopLevelSdk = async (options: ISdkImportOptions) => {
if (options.useCommonSdk) {
export const importTopLevelSdk = async (options?: ISdkImportOptions) => {
if (options?.useCommonSdk) {
return (await import('@onekeyfe/hd-common-connect-sdk')).default as unknown as CoreApi;
}
return (await import('@onekeyfe/hd-web-sdk')).default.HardwareSDKTopLevel as unknown as CoreApi;
Expand Down
6 changes: 3 additions & 3 deletions packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/hd-core",
"version": "1.0.24-alpha.2",
"version": "1.0.24-alpha.4",
"description": "> TODO: description",
"author": "OneKey",
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
Expand All @@ -25,8 +25,8 @@
"url": "https://github.com/OneKeyHQ/hardware-js-sdk/issues"
},
"dependencies": {
"@onekeyfe/hd-shared": "^1.0.24-alpha.2",
"@onekeyfe/hd-transport": "^1.0.24-alpha.2",
"@onekeyfe/hd-shared": "^1.0.24-alpha.4",
"@onekeyfe/hd-transport": "^1.0.24-alpha.4",
"axios": "^0.27.2",
"bignumber.js": "^9.0.2",
"bytebuffer": "^5.0.1",
Expand Down
23 changes: 21 additions & 2 deletions packages/core/src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,9 @@ function initDevice(method: BaseMethod) {
if (!device) {
const env = DataManager.getSettings('env');
if (DataManager.isWebUsbConnect(env)) {
postMessage(createUiMessage(UI_REQUEST.WEB_DEVICE_PROMPT_ACCESS_PERMISSION));
if (!method.payload.skipWebDevicePrompt) {
postMessage(createUiMessage(UI_REQUEST.WEB_DEVICE_PROMPT_ACCESS_PERMISSION));
}
throw ERRORS.TypedError(HardwareErrorCode.WebDeviceNotFoundOrNeedsPermission);
}
throw ERRORS.TypedError(HardwareErrorCode.DeviceNotFound);
Expand Down Expand Up @@ -727,7 +729,7 @@ const createUiPromise = <T extends UiPromiseResponse['type']>(promiseEvent: T, d
};

const findUiPromise = <T extends UiPromiseResponse['type']>(promiseEvent: T) =>
_uiPromises.find(p => p.id === promiseEvent) as UiPromise<T> | undefined;
_uiPromises.find(p => p.id === promiseEvent);

const removeUiPromise = (promise: Deferred<any>) => {
_uiPromises = _uiPromises.filter(p => p !== promise);
Expand Down Expand Up @@ -828,3 +830,20 @@ export const init = async (
Log.error('core init', error);
}
};

export const switchTransport = ({
env,
Transport,
plugin,
}: {
env: ConnectSettings['env'];
Transport: any;
plugin?: LowlevelTransportSharedPlugin;
}) => {
DataManager.updateEnv(env);
TransportManager.setTransport(Transport, plugin);
_deviceList = undefined;
DevicePool.resetState();
_connector = undefined;
initConnector();
};
13 changes: 13 additions & 0 deletions packages/core/src/data-manager/DataManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,19 @@ export default class DataManager {
}
}

static updateEnv(newEnv: ConnectSettings['env']) {
if (this.settings) {
const prevEnv = this.settings.env;
this.settings = {
...this.settings,
env: newEnv,
};

// Log the environment change
console.debug(`DataManager env updated: ${prevEnv} -> ${newEnv}`);
}
}

static async checkAndReloadData() {
if (getTimeStamp() - this.lastCheckTimestamp > 1000 * 60 * 60 * 3) {
await this.load(this.settings).then(() => {
Expand Down
7 changes: 0 additions & 7 deletions packages/core/src/device/DeviceCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,14 +273,7 @@ export class DeviceCommands {
// TODO: EntropyRequest
}

const isWebusbEnv = DataManager.getSettings('env') === 'webusb';

if (res.type === 'PinMatrixRequest') {
if (isWebusbEnv) {
return Promise.reject(
ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'Please unlock your device')
);
}
return this._promptPin(res.message.type).then(
pin => {
if (pin === '@@ONEKEY_INPUT_PIN_IN_DEVICE') {
Expand Down
13 changes: 13 additions & 0 deletions packages/core/src/device/DevicePool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,4 +247,17 @@ export class DevicePool extends EventEmitter {

this.disconnectPool.push(descriptor);
}

static resetState() {
this.current = null;
this.upcoming = [];
this.connectedPool = [];
this.disconnectPool = [];
this.devicesCache = {};

// Clear all event listeners but keep the emitter instance
this.emitter.removeAllListeners();

Log.debug('DevicePool state has been reset');
}
}
8 changes: 7 additions & 1 deletion packages/core/src/events/call.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { serializeError } from '@onekeyfe/hd-shared';
import { IFRAME } from './iframe';
import { CommonParams, CoreApi } from '../types';
import { CommonParams, CoreApi, ConnectSettings } from '../types';

type UnwrappedResponse<T> = T extends Promise<infer R>
? R extends { success: true; payload: infer P }
Expand Down Expand Up @@ -52,6 +52,12 @@ export interface IFrameCancelMessage {
payload: { connectId?: string };
}

export interface IFrameSwitchTransportMessage {
event: typeof IFRAME.SWITCH_TRANSPORT;
type: typeof IFRAME.SWITCH_TRANSPORT;
payload: { env: ConnectSettings['env'] };
}

export const RESPONSE_EVENT = 'RESPONSE_EVENT';

export interface MethodResponseMessage {
Expand Down
Loading
Loading