@onekeyfe/hd-core 1.2.8-alpha.9 → 1.2.10-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -0
- package/__tests__/allNetworkGetAddress-privacy-networks.test.ts +78 -0
- package/__tests__/btc-derive-context-hash.test.ts +200 -0
- package/__tests__/core-dispose.test.ts +114 -1
- package/__tests__/core-error-output.test.ts +21 -0
- package/__tests__/device-connector-protocol.test.ts +5 -2
- package/__tests__/device-lifecycle-events.test.ts +127 -10
- package/__tests__/firmware-update/firmware-artifact-source.test.ts +11 -0
- package/__tests__/logBlockEvent.test.ts +331 -9
- package/__tests__/logger.test.ts +18 -0
- package/__tests__/monero-get-address.test.ts +147 -0
- package/__tests__/monero-key-image-sync.test.ts +272 -0
- package/__tests__/monero-sign-transaction.test.ts +436 -0
- package/__tests__/protocol-v2-resources.test.ts +14 -0
- package/__tests__/protocol-v2.test.ts +845 -3
- package/__tests__/protocolV2FileWrite.test.ts +454 -7
- package/__tests__/search-devices.test.ts +36 -0
- package/__tests__/sol-sign-offchain-message.test.ts +8 -0
- package/__tests__/usb-identity-probe.test.ts +358 -0
- package/__tests__/zcash-protobuf.test.ts +141 -0
- package/__tests__/zcash-sign-pczt.test.ts +446 -0
- package/dist/api/BaseMethod.d.ts.map +1 -1
- package/dist/api/FileWrite.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +5 -0
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/SearchDevices.d.ts +21 -1
- package/dist/api/SearchDevices.d.ts.map +1 -1
- package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
- package/dist/api/btc/BTCDeriveContextHash.d.ts +16 -0
- package/dist/api/btc/BTCDeriveContextHash.d.ts.map +1 -0
- package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +1 -1
- package/dist/api/helpers/pathUtils.d.ts +1 -0
- package/dist/api/helpers/pathUtils.d.ts.map +1 -1
- package/dist/api/helpers/protocolV2FileWrite.d.ts +5 -1
- package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
- package/dist/api/index.d.ts +7 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/monero/MoneroGetAddress.d.ts +11 -0
- package/dist/api/monero/MoneroGetAddress.d.ts.map +1 -0
- package/dist/api/monero/MoneroGetWatchKey.d.ts +11 -0
- package/dist/api/monero/MoneroGetWatchKey.d.ts.map +1 -0
- package/dist/api/monero/MoneroKeyImageSync.d.ts +20 -0
- package/dist/api/monero/MoneroKeyImageSync.d.ts.map +1 -0
- package/dist/api/monero/MoneroSignTransaction.d.ts +17 -0
- package/dist/api/monero/MoneroSignTransaction.d.ts.map +1 -0
- package/dist/api/monero/helpers.d.ts +5 -0
- package/dist/api/monero/helpers.d.ts.map +1 -0
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -1
- package/dist/api/zcash/ZcashGetAddress.d.ts +12 -0
- package/dist/api/zcash/ZcashGetAddress.d.ts.map +1 -0
- package/dist/api/zcash/ZcashSignPczt.d.ts +16 -0
- package/dist/api/zcash/ZcashSignPczt.d.ts.map +1 -0
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/device/Device.d.ts +1 -0
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts +4 -4
- package/dist/events/logBlockEvent.d.ts +10 -0
- package/dist/events/logBlockEvent.d.ts.map +1 -1
- package/dist/events/ui-request.d.ts +2 -0
- package/dist/events/ui-request.d.ts.map +1 -1
- package/dist/index.d.ts +192 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5751 -4191
- package/dist/inject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/resources.d.ts +1 -0
- package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
- package/dist/types/api/allNetworkGetAddress.d.ts +5 -1
- package/dist/types/api/allNetworkGetAddress.d.ts.map +1 -1
- package/dist/types/api/btcDeriveContextHash.d.ts +10 -0
- package/dist/types/api/btcDeriveContextHash.d.ts.map +1 -0
- package/dist/types/api/export.d.ts +7 -0
- package/dist/types/api/export.d.ts.map +1 -1
- package/dist/types/api/index.d.ts +14 -0
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/moneroGetAddress.d.ts +15 -0
- package/dist/types/api/moneroGetAddress.d.ts.map +1 -0
- package/dist/types/api/moneroGetWatchKey.d.ts +15 -0
- package/dist/types/api/moneroGetWatchKey.d.ts.map +1 -0
- package/dist/types/api/moneroKeyImageSync.d.ts +24 -0
- package/dist/types/api/moneroKeyImageSync.d.ts.map +1 -0
- package/dist/types/api/moneroSignTransaction.d.ts +32 -0
- package/dist/types/api/moneroSignTransaction.d.ts.map +1 -0
- package/dist/types/api/zcashGetAddress.d.ts +22 -0
- package/dist/types/api/zcashGetAddress.d.ts.map +1 -0
- package/dist/types/api/zcashSignPczt.d.ts +9 -0
- package/dist/types/api/zcashSignPczt.d.ts.map +1 -0
- package/dist/types/device.d.ts +10 -0
- package/dist/types/device.d.ts.map +1 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/patch.d.ts +1 -1
- package/dist/utils/patch.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/BaseMethod.ts +2 -0
- package/src/api/FileWrite.ts +7 -1
- package/src/api/FirmwareUpdateV4.ts +358 -74
- package/src/api/SearchDevices.ts +172 -7
- package/src/api/allnetwork/AllNetworkGetAddressBase.ts +38 -1
- package/src/api/btc/BTCDeriveContextHash.ts +90 -0
- package/src/api/firmware/FirmwareArtifactSource.ts +12 -3
- package/src/api/helpers/pathUtils.ts +23 -0
- package/src/api/helpers/protocolV2FileWrite.ts +382 -111
- package/src/api/index.ts +8 -0
- package/src/api/monero/MoneroGetAddress.ts +71 -0
- package/src/api/monero/MoneroGetWatchKey.ts +69 -0
- package/src/api/monero/MoneroKeyImageSync.ts +164 -0
- package/src/api/monero/MoneroSignTransaction.ts +319 -0
- package/src/api/monero/helpers.ts +28 -0
- package/src/api/protocol-v2/DeviceUploadNft.ts +6 -1
- package/src/api/protocol-v2/DeviceUploadWallpaper.ts +15 -1
- package/src/api/zcash/ZcashGetAddress.ts +119 -0
- package/src/api/zcash/ZcashSignPczt.ts +152 -0
- package/src/core/index.ts +49 -17
- package/src/data/messages/messages-protocol-v2.json +138 -1
- package/src/data/messages/messages.json +51 -0
- package/src/device/Device.ts +21 -3
- package/src/device/DeviceConnector.ts +4 -4
- package/src/events/logBlockEvent.ts +57 -3
- package/src/events/ui-request.ts +2 -0
- package/src/index.ts +1 -0
- package/src/inject.ts +15 -0
- package/src/protocols/protocol-v2/resources.ts +6 -1
- package/src/types/api/allNetworkGetAddress.ts +9 -1
- package/src/types/api/btcDeriveContextHash.ts +15 -0
- package/src/types/api/export.ts +16 -0
- package/src/types/api/index.ts +22 -0
- package/src/types/api/moneroGetAddress.ts +27 -0
- package/src/types/api/moneroGetWatchKey.ts +28 -0
- package/src/types/api/moneroKeyImageSync.ts +45 -0
- package/src/types/api/moneroSignTransaction.ts +54 -0
- package/src/types/api/zcashGetAddress.ts +35 -0
- package/src/types/api/zcashSignPczt.ts +18 -0
- package/src/types/device.ts +18 -0
- package/src/utils/logger.ts +4 -0
package/src/api/SearchDevices.ts
CHANGED
|
@@ -5,10 +5,20 @@ import TransportManager from '../data-manager/TransportManager';
|
|
|
5
5
|
import { DataManager } from '../data-manager';
|
|
6
6
|
import { LoggerNames, getDeviceTypeByBleName, getLogger } from '../utils';
|
|
7
7
|
import { DevicePool } from '../device/DevicePool';
|
|
8
|
+
import { buildProtocolV1FeaturesPayload } from '../deviceProfile/buildDeviceFeatures';
|
|
9
|
+
import { mapProtocolV2DeviceInfoToState } from '../device/DeviceStateMapper';
|
|
10
|
+
import { getSupportProtocolV1MessageSchema } from '../utils/deviceFeaturesUtils';
|
|
11
|
+
import { PROTOCOL_V2_FEATURES_DEVICE_INFO_REQUEST } from '../protocols/protocol-v2/features';
|
|
8
12
|
|
|
9
|
-
import type { SearchDevice } from '../types/device';
|
|
13
|
+
import type { SearchDevice, UsbDeviceIdentity } from '../types/device';
|
|
14
|
+
import type { PROTO } from '../constants';
|
|
10
15
|
import type DeviceConnector from '../device/DeviceConnector';
|
|
11
|
-
import type {
|
|
16
|
+
import type {
|
|
17
|
+
AcquireInput,
|
|
18
|
+
OneKeyDeviceInfo as DeviceDescriptor,
|
|
19
|
+
ProtocolV2DeviceInfo,
|
|
20
|
+
Transport,
|
|
21
|
+
} from '@onekeyfe/hd-transport';
|
|
12
22
|
import type { Device } from '../device/Device';
|
|
13
23
|
|
|
14
24
|
const Log = getLogger(LoggerNames.DevicePool);
|
|
@@ -18,7 +28,10 @@ type RequestQueueLookup = {
|
|
|
18
28
|
getTask: (requestId: number) => { method: { device?: Device } } | undefined;
|
|
19
29
|
};
|
|
20
30
|
|
|
21
|
-
|
|
31
|
+
export type UsbIdentityProbeDescriptor = Pick<DeviceDescriptor, 'path' | 'commType'> &
|
|
32
|
+
Partial<Pick<DeviceDescriptor, 'id' | 'session'>>;
|
|
33
|
+
|
|
34
|
+
const getDescriptorKeys = (descriptor: UsbIdentityProbeDescriptor) =>
|
|
22
35
|
[descriptor.path, descriptor.id].filter(
|
|
23
36
|
(key): key is string => typeof key === 'string' && key.length > 0
|
|
24
37
|
);
|
|
@@ -33,11 +46,11 @@ const isOwnedByActiveWebUsbRequest = (
|
|
|
33
46
|
);
|
|
34
47
|
};
|
|
35
48
|
|
|
36
|
-
const getUsbHandle = (descriptor?:
|
|
49
|
+
const getUsbHandle = (descriptor?: UsbIdentityProbeDescriptor) =>
|
|
37
50
|
(descriptor as { device?: unknown } | undefined)?.device;
|
|
38
51
|
|
|
39
52
|
const getOwningRequestDevice = (
|
|
40
|
-
descriptor:
|
|
53
|
+
descriptor: UsbIdentityProbeDescriptor,
|
|
41
54
|
requestQueue?: RequestQueueLookup
|
|
42
55
|
) => {
|
|
43
56
|
if (!requestQueue) return undefined;
|
|
@@ -60,6 +73,158 @@ const getOwningRequestDevice = (
|
|
|
60
73
|
return undefined;
|
|
61
74
|
};
|
|
62
75
|
|
|
76
|
+
export const getOwnedUsbDeviceIdentity = (
|
|
77
|
+
descriptor: UsbIdentityProbeDescriptor,
|
|
78
|
+
requestQueue: RequestQueueLookup
|
|
79
|
+
): UsbDeviceIdentity | undefined => {
|
|
80
|
+
const owner = getOwningRequestDevice(descriptor, requestQueue);
|
|
81
|
+
if (!owner || descriptor.commType !== 'webusb' || owner.originalDescriptor?.commType !== 'webusb')
|
|
82
|
+
return undefined;
|
|
83
|
+
return {
|
|
84
|
+
path: descriptor.path,
|
|
85
|
+
serialNo: owner.getCurrentSerialNo() || null,
|
|
86
|
+
deviceId: owner.getCurrentDeviceId() || null,
|
|
87
|
+
deviceType: owner.getCurrentDeviceType(),
|
|
88
|
+
connectProtocol: owner.getProtocol(),
|
|
89
|
+
commType: 'webusb',
|
|
90
|
+
mode: owner.features?.mode ?? undefined,
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export type UsbIdentityProbeTransport = Pick<
|
|
95
|
+
Transport,
|
|
96
|
+
'release' | 'call' | 'getProtocolType' | 'configureProtocolV2'
|
|
97
|
+
> & {
|
|
98
|
+
init: (logger: object) => unknown;
|
|
99
|
+
enumerate: () => Promise<UsbIdentityProbeDescriptor[]>;
|
|
100
|
+
acquire: (input: AcquireInput) => Promise<string | undefined>;
|
|
101
|
+
configure: (signedData: string) => void | Promise<void>;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// Identity discovery must not publish device events or log raw Features/session data.
|
|
105
|
+
const identityProbeLogger = {
|
|
106
|
+
debug: () => undefined,
|
|
107
|
+
log: () => undefined,
|
|
108
|
+
info: () => undefined,
|
|
109
|
+
warn: () => undefined,
|
|
110
|
+
error: () => undefined,
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/** Runs on a separate transport; never initializes or switches the current Core. */
|
|
114
|
+
export const probeUsbDeviceIdentitiesWithTransport = async (
|
|
115
|
+
transport: UsbIdentityProbeTransport,
|
|
116
|
+
commType: UsbDeviceIdentity['commType'],
|
|
117
|
+
getOwnedIdentity?: (descriptor: UsbIdentityProbeDescriptor) => UsbDeviceIdentity | undefined
|
|
118
|
+
): Promise<UsbDeviceIdentity[]> => {
|
|
119
|
+
if (commType !== 'webusb') return [];
|
|
120
|
+
await transport.init(identityProbeLogger);
|
|
121
|
+
const defaultMessages = JSON.stringify(DataManager.getProtobufMessages());
|
|
122
|
+
await transport.configure(defaultMessages);
|
|
123
|
+
await transport.configureProtocolV2?.(
|
|
124
|
+
JSON.stringify(DataManager.getProtobufMessages('v2Schema'))
|
|
125
|
+
);
|
|
126
|
+
const descriptors = await transport.enumerate();
|
|
127
|
+
const identities: UsbDeviceIdentity[] = [];
|
|
128
|
+
const readIdentity = async (
|
|
129
|
+
descriptor: UsbIdentityProbeDescriptor
|
|
130
|
+
): Promise<UsbDeviceIdentity | undefined> => {
|
|
131
|
+
const { path } = descriptor;
|
|
132
|
+
if (!path || descriptor.commType !== commType) return undefined;
|
|
133
|
+
if (descriptors.filter(candidate => candidate.path === path).length !== 1) return undefined;
|
|
134
|
+
const owner = getOwnedIdentity?.(descriptor);
|
|
135
|
+
if (owner) {
|
|
136
|
+
return owner;
|
|
137
|
+
}
|
|
138
|
+
// Do not borrow a browser handle or replace a Bridge session owned by another call.
|
|
139
|
+
if (descriptor.session || (getUsbHandle(descriptor) as USBDevice | undefined)?.opened)
|
|
140
|
+
return undefined;
|
|
141
|
+
|
|
142
|
+
let session: string | undefined;
|
|
143
|
+
let identified: UsbDeviceIdentity | undefined;
|
|
144
|
+
try {
|
|
145
|
+
await transport.configure(defaultMessages);
|
|
146
|
+
session = await transport.acquire({ path, previous: null, forceProtocolDetection: true });
|
|
147
|
+
if (!session) return undefined;
|
|
148
|
+
const protocol = transport.getProtocolType(path);
|
|
149
|
+
if (protocol === 'V1') {
|
|
150
|
+
const response = await transport.call(session, 'GetFeatures', {}, { timeoutMs: 3000 });
|
|
151
|
+
if (response.type !== 'Features') return undefined;
|
|
152
|
+
let features = buildProtocolV1FeaturesPayload(response.message as PROTO.Features);
|
|
153
|
+
// Classic-family loaders expose their supported information in Features.
|
|
154
|
+
// Touch/Pro retain their existing vendor-feature query.
|
|
155
|
+
if (
|
|
156
|
+
!features.serialNo &&
|
|
157
|
+
(features.mode !== 'bootloader' ||
|
|
158
|
+
features.deviceType === EDeviceType.Touch ||
|
|
159
|
+
features.deviceType === EDeviceType.Pro)
|
|
160
|
+
) {
|
|
161
|
+
const { messages, protocolV1MessageSchema } = getSupportProtocolV1MessageSchema(features);
|
|
162
|
+
// Legacy V1 has no OnekeyGetFeatures; keep the identity confirmed by GetFeatures.
|
|
163
|
+
if (protocolV1MessageSchema === 'v1CurrentSchema') {
|
|
164
|
+
if (messages) await transport.configure(JSON.stringify(messages));
|
|
165
|
+
const vendor = await transport.call(
|
|
166
|
+
session,
|
|
167
|
+
'OnekeyGetFeatures',
|
|
168
|
+
{},
|
|
169
|
+
{ timeoutMs: 3000 }
|
|
170
|
+
);
|
|
171
|
+
if (vendor.type === 'OnekeyFeatures') {
|
|
172
|
+
features = buildProtocolV1FeaturesPayload({
|
|
173
|
+
...response.message,
|
|
174
|
+
...vendor.message,
|
|
175
|
+
} as PROTO.Features);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
identified = {
|
|
180
|
+
path,
|
|
181
|
+
serialNo: features.serialNo || null,
|
|
182
|
+
deviceId: features.deviceId || null,
|
|
183
|
+
deviceType: features.deviceType,
|
|
184
|
+
connectProtocol: 'V1',
|
|
185
|
+
commType,
|
|
186
|
+
mode: features.mode ?? undefined,
|
|
187
|
+
};
|
|
188
|
+
} else if (protocol === 'V2') {
|
|
189
|
+
const response = await transport.call(
|
|
190
|
+
session,
|
|
191
|
+
'DeviceInfoGet',
|
|
192
|
+
PROTOCOL_V2_FEATURES_DEVICE_INFO_REQUEST,
|
|
193
|
+
{ timeoutMs: 3000 }
|
|
194
|
+
);
|
|
195
|
+
if (response.type !== 'DeviceInfo') return undefined;
|
|
196
|
+
const { identity } = mapProtocolV2DeviceInfoToState(
|
|
197
|
+
response.message as ProtocolV2DeviceInfo
|
|
198
|
+
);
|
|
199
|
+
identified = {
|
|
200
|
+
path,
|
|
201
|
+
serialNo: identity?.serialNo || null,
|
|
202
|
+
deviceId: identity?.deviceId || null,
|
|
203
|
+
deviceType: identity?.deviceType ?? EDeviceType.Unknown,
|
|
204
|
+
connectProtocol: 'V2',
|
|
205
|
+
commType,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
} catch {
|
|
209
|
+
// Discovery is best effort; a busy/disconnected device cannot confirm identity.
|
|
210
|
+
} finally {
|
|
211
|
+
if (session) {
|
|
212
|
+
try {
|
|
213
|
+
await transport.release(session, false);
|
|
214
|
+
} catch {
|
|
215
|
+
identified = undefined;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return identified;
|
|
220
|
+
};
|
|
221
|
+
for (const descriptor of descriptors) {
|
|
222
|
+
const identity = await readIdentity(descriptor);
|
|
223
|
+
if (identity) identities.push(identity);
|
|
224
|
+
}
|
|
225
|
+
return identities;
|
|
226
|
+
};
|
|
227
|
+
|
|
63
228
|
// A USB path is a routing key (the USB serial, a synthesized usb-vid-pid-name, or the
|
|
64
229
|
// bootloader placeholder), not a hardware identity, so it never fills uuid/serialNo.
|
|
65
230
|
const toSearchDeviceFromDescriptor = (descriptor: DeviceDescriptor): SearchDevice => {
|
|
@@ -81,7 +246,7 @@ const toSearchDevice = (device: Device): SearchDevice | null => {
|
|
|
81
246
|
};
|
|
82
247
|
|
|
83
248
|
export default class SearchDevices extends BaseMethod {
|
|
84
|
-
connector?: DeviceConnector;
|
|
249
|
+
connector?: DeviceConnector = undefined;
|
|
85
250
|
|
|
86
251
|
init() {
|
|
87
252
|
this.useDevice = false;
|
|
@@ -130,7 +295,7 @@ export default class SearchDevices extends BaseMethod {
|
|
|
130
295
|
// BLE discovery cannot provide a physical-device identity before initialization.
|
|
131
296
|
uuid: '',
|
|
132
297
|
deviceId: null,
|
|
133
|
-
name: bleName || device.name,
|
|
298
|
+
name: bleName || device.name || '',
|
|
134
299
|
deviceType: getDeviceTypeByBleName(bleName),
|
|
135
300
|
});
|
|
136
301
|
}
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
|
|
10
10
|
import { serializedPath, toHardened } from '../helpers/pathUtils';
|
|
11
11
|
import { BaseMethod } from '../BaseMethod';
|
|
12
|
-
import { validateParams } from '../helpers/paramsValidator';
|
|
12
|
+
import { invalidParameter, validateParams } from '../helpers/paramsValidator';
|
|
13
13
|
import { PROTO } from '../../constants';
|
|
14
14
|
import { findMethod } from '../utils';
|
|
15
15
|
import { DEVICE, IFRAME, createUiMessage } from '../../events';
|
|
@@ -35,6 +35,12 @@ import type {
|
|
|
35
35
|
|
|
36
36
|
const Mainnet = 'mainnet';
|
|
37
37
|
|
|
38
|
+
const MoneroNetworkTypes = new Map<string, number>([
|
|
39
|
+
[Mainnet, PROTO.MoneroNetworkType.MAINNET],
|
|
40
|
+
['testnet', PROTO.MoneroNetworkType.TESTNET],
|
|
41
|
+
['stagenet', PROTO.MoneroNetworkType.STAGENET],
|
|
42
|
+
]);
|
|
43
|
+
|
|
38
44
|
export type NetworkConfig = {
|
|
39
45
|
methodName: keyof CoreApi;
|
|
40
46
|
getParams?: (baseParams: AllNetworkAddressParams, chainName?: string, methodName?: string) => any;
|
|
@@ -246,6 +252,37 @@ const networkConfigMap: NetworkConfigMap = {
|
|
|
246
252
|
stellar: {
|
|
247
253
|
methodName: 'stellarGetAddress',
|
|
248
254
|
},
|
|
255
|
+
xmr: {
|
|
256
|
+
methodName: 'moneroGetAddress',
|
|
257
|
+
getParams: (baseParams: AllNetworkAddressParams, chainName?: string) => {
|
|
258
|
+
const { path, showOnOneKey } = baseParams;
|
|
259
|
+
const networkType = MoneroNetworkTypes.get(chainName ?? Mainnet);
|
|
260
|
+
if (networkType === undefined) {
|
|
261
|
+
throw invalidParameter(`Unsupported Monero chainName: ${chainName}`);
|
|
262
|
+
}
|
|
263
|
+
return {
|
|
264
|
+
path,
|
|
265
|
+
networkType,
|
|
266
|
+
showOnOneKey,
|
|
267
|
+
};
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
zcash: {
|
|
271
|
+
methodName: 'zcashGetAddress',
|
|
272
|
+
// The account's unified address with the keys a wallet needs to watch it.
|
|
273
|
+
getParams: (baseParams: AllNetworkAddressParams) => {
|
|
274
|
+
const { path, showOnOneKey } = baseParams;
|
|
275
|
+
return {
|
|
276
|
+
path,
|
|
277
|
+
showOnOneKey,
|
|
278
|
+
addressType: PROTO.ZcashAddressType.UNIFIED_ORCHARD,
|
|
279
|
+
scope: PROTO.ZcashAddressScope.EXTERNAL,
|
|
280
|
+
diversifierIndex: 0,
|
|
281
|
+
includeUfvk: true,
|
|
282
|
+
includeSeedFingerprint: true,
|
|
283
|
+
};
|
|
284
|
+
},
|
|
285
|
+
},
|
|
249
286
|
};
|
|
250
287
|
|
|
251
288
|
type MethodParams = {
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
2
|
+
import { Buffer } from 'buffer';
|
|
3
|
+
|
|
4
|
+
import { BaseMethod } from '../BaseMethod';
|
|
5
|
+
import { invalidParameter, validateParams } from '../helpers/paramsValidator';
|
|
6
|
+
import { getScriptType, validatePath } from '../helpers/pathUtils';
|
|
7
|
+
|
|
8
|
+
import type { BabylonDeriveContextHash, CanonicalBitcoinNetwork } from '@onekeyfe/hd-transport';
|
|
9
|
+
import type { BTCDeriveContextHashParams } from '../../types';
|
|
10
|
+
|
|
11
|
+
const NETWORKS: Record<BTCDeriveContextHashParams['network'], CanonicalBitcoinNetwork> = {
|
|
12
|
+
'bitcoin-mainnet': 'BITCOIN_MAINNET',
|
|
13
|
+
'bitcoin-testnet': 'BITCOIN_TESTNET',
|
|
14
|
+
'bitcoin-signet': 'BITCOIN_SIGNET',
|
|
15
|
+
'bitcoin-regtest': 'BITCOIN_REGTEST',
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default class BTCDeriveContextHash extends BaseMethod<BabylonDeriveContextHash> {
|
|
19
|
+
strictCheckDeviceSupport = true;
|
|
20
|
+
|
|
21
|
+
init() {
|
|
22
|
+
this.checkDeviceId = true;
|
|
23
|
+
this.allowUsePreInitialize = true;
|
|
24
|
+
|
|
25
|
+
validateParams(this.payload, [
|
|
26
|
+
{ name: 'path', required: true },
|
|
27
|
+
{ name: 'appName', type: 'string', required: true },
|
|
28
|
+
{ name: 'context', type: 'string', required: true },
|
|
29
|
+
{ name: 'network', type: 'string', required: true },
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
const { path, appName, context, network } = this.payload;
|
|
33
|
+
if (typeof appName !== 'string' || !/^[a-z0-9-]{1,64}$/.test(appName)) {
|
|
34
|
+
throw invalidParameter(
|
|
35
|
+
'appName must contain 1..64 ASCII lowercase letters, digits or hyphens'
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
if (typeof context !== 'string' || !/^(?:[0-9a-f]{2}){1,1024}$/.test(context)) {
|
|
39
|
+
throw invalidParameter('context must be 1..1024 bytes of lowercase hex without a prefix');
|
|
40
|
+
}
|
|
41
|
+
if (typeof network !== 'string' || !Object.prototype.hasOwnProperty.call(NETWORKS, network)) {
|
|
42
|
+
throw invalidParameter('Unsupported Bitcoin network');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Reject malformed or overflowing indices before validatePath can truncate them.
|
|
46
|
+
if (
|
|
47
|
+
(typeof path === 'string' &&
|
|
48
|
+
(!/^m(?:\/\d+'?)+$/i.test(path) ||
|
|
49
|
+
path
|
|
50
|
+
.split('/')
|
|
51
|
+
.slice(1)
|
|
52
|
+
.some(index => Number(index.replace(/'/g, '')) >= 0x80000000))) ||
|
|
53
|
+
(Array.isArray(path) &&
|
|
54
|
+
path.findIndex(index => !Number.isInteger(index) || index < 0 || index > 0xffffffff) !== -1)
|
|
55
|
+
) {
|
|
56
|
+
throw invalidParameter('Not a valid BIP-32 path');
|
|
57
|
+
}
|
|
58
|
+
const addressN = validatePath(path, 3);
|
|
59
|
+
|
|
60
|
+
this.params = {
|
|
61
|
+
address_n: addressN,
|
|
62
|
+
script_type: getScriptType(addressN),
|
|
63
|
+
app_name: Buffer.from(appName, 'ascii').toString('hex'),
|
|
64
|
+
context,
|
|
65
|
+
network: NETWORKS[network as BTCDeriveContextHashParams['network']],
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
getVersionRange() {
|
|
70
|
+
return {
|
|
71
|
+
classic1s: { min: '3.21.0' },
|
|
72
|
+
classicpure: { min: '3.21.0' },
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async run() {
|
|
77
|
+
const { message } = await this.device.commands.typedCall(
|
|
78
|
+
'BabylonDeriveContextHash',
|
|
79
|
+
'BabylonDerivedContextHash',
|
|
80
|
+
this.params
|
|
81
|
+
);
|
|
82
|
+
if (typeof message.secret !== 'string' || !/^[0-9a-f]{64}$/.test(message.secret)) {
|
|
83
|
+
throw ERRORS.TypedError(
|
|
84
|
+
HardwareErrorCode.CallMethodError,
|
|
85
|
+
'Invalid Babylon context hash response'
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
return message;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -212,17 +212,26 @@ export const readVerifiedFirmwareArtifact = async ({
|
|
|
212
212
|
}): Promise<ArrayBuffer> => {
|
|
213
213
|
assertFirmwareArtifactReference(artifact);
|
|
214
214
|
const source = await ReaderFirmwareByteSource.open(artifact, reader);
|
|
215
|
+
const hasher = sha256.create();
|
|
215
216
|
try {
|
|
216
|
-
const
|
|
217
|
-
|
|
217
|
+
const bytes = new Uint8Array(source.size);
|
|
218
|
+
let offset = 0;
|
|
219
|
+
while (offset < source.size) {
|
|
220
|
+
const length = Math.min(MAX_FIRMWARE_ARTIFACT_READ_BYTES, source.size - offset);
|
|
221
|
+
bytes.set(new Uint8Array(await source.readAt(offset, length)), offset);
|
|
222
|
+
hasher.update(bytes.subarray(offset, offset + length));
|
|
223
|
+
offset += length;
|
|
224
|
+
}
|
|
225
|
+
const actualSha256 = bytesToHex(hasher.digest());
|
|
218
226
|
if (actualSha256 !== artifact.sha256.toLowerCase()) {
|
|
219
227
|
return artifactError(
|
|
220
228
|
'FirmwareArtifactReceiptMismatch',
|
|
221
229
|
'Firmware artifact bytes do not match the approved SHA-256 receipt'
|
|
222
230
|
);
|
|
223
231
|
}
|
|
224
|
-
return
|
|
232
|
+
return bytes.buffer;
|
|
225
233
|
} finally {
|
|
234
|
+
hasher.destroy();
|
|
226
235
|
await source.close().catch(() => undefined);
|
|
227
236
|
}
|
|
228
237
|
};
|
|
@@ -143,3 +143,26 @@ export const validatePath = (
|
|
|
143
143
|
if (length > 0 && valid.length < length) throw PATH_NOT_VALID;
|
|
144
144
|
return base ? valid.splice(0, 3) : valid;
|
|
145
145
|
};
|
|
146
|
+
|
|
147
|
+
const isTextIndex = (part: string) => {
|
|
148
|
+
const digits = /^(\d+)'?$/.exec(part)?.[1];
|
|
149
|
+
return digits !== undefined && Number(digits) < HD_HARDENED;
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const isUint32 = (n: number) => Number.isInteger(n) && n >= 0 && n <= 0xffffffff;
|
|
153
|
+
|
|
154
|
+
// validatePath lets parseInt and 32-bit hardening alias fractional or oversized
|
|
155
|
+
// components to another index: 0.5' and 4294967296' both become 0'.
|
|
156
|
+
export const validateStrictPath = (path: string | Array<number>, length = 0): Array<number> => {
|
|
157
|
+
const addressN = validatePath(path, length);
|
|
158
|
+
const isStrict =
|
|
159
|
+
typeof path === 'string'
|
|
160
|
+
? path
|
|
161
|
+
.toLowerCase()
|
|
162
|
+
.split('/')
|
|
163
|
+
.filter(p => p !== 'm' && p !== '')
|
|
164
|
+
.every(isTextIndex)
|
|
165
|
+
: path.every(isUint32);
|
|
166
|
+
if (!isStrict) throw PATH_NOT_VALID;
|
|
167
|
+
return addressN;
|
|
168
|
+
};
|