@onekeyfe/hd-core 1.2.0-alpha.40 → 1.2.0-alpha.41
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/__tests__/AllNetworkGetAddressBase.tracing.test.ts +0 -78
- package/__tests__/DeviceEventRegistration.test.ts +0 -6
- package/__tests__/connectSettings.test.ts +47 -5
- package/__tests__/firmware-update/check-all-firmware-release.test.ts +175 -0
- package/__tests__/firmware-update/firmware-artifact-source.test.ts +119 -0
- package/__tests__/firmware-update/firmware-host-binding.test.ts +70 -0
- package/__tests__/firmware-update/firmware-preparation-error.test.ts +27 -0
- package/__tests__/firmware-update/firmware-update-capabilities.test.ts +13 -0
- package/__tests__/firmware-update/firmware-update-plan.test.ts +593 -0
- package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +213 -0
- package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +59 -31
- package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +58 -0
- package/__tests__/firmware-update/firmware-upload-source.test.ts +70 -0
- package/__tests__/get-device-state.test.ts +12 -132
- package/__tests__/homescreen.test.ts +1 -41
- package/__tests__/logBlockEvent.test.ts +1 -1
- package/__tests__/open-wallet-session.test.ts +18 -259
- package/__tests__/protocol-v2-unlock-policy.test.ts +35 -86
- package/__tests__/protocol-v2.test.ts +632 -333
- package/__tests__/public-pro2-api-boundary.test.ts +0 -1
- package/dist/api/BaseMethod.d.ts +1 -3
- package/dist/api/BaseMethod.d.ts.map +1 -1
- package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV2.d.ts +11 -0
- package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV3.d.ts +7 -3
- package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +22 -5
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/GetPassphraseState.d.ts.map +1 -1
- package/dist/api/OpenWalletSession.d.ts.map +1 -1
- package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
- package/dist/api/device/DeviceUpdateBootloader.d.ts +5 -1
- package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareArtifactSource.d.ts +25 -0
- package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +1 -0
- package/dist/api/firmware/FirmwareHostBinding.d.ts +6 -0
- package/dist/api/firmware/FirmwareHostBinding.d.ts.map +1 -0
- package/dist/api/firmware/FirmwarePreparationError.d.ts +3 -0
- package/dist/api/firmware/FirmwarePreparationError.d.ts.map +1 -0
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +8 -0
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +3 -0
- package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +1 -0
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts +25 -0
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -0
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +30 -0
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -0
- package/dist/api/firmware/getBinary.d.ts +7 -0
- package/dist/api/firmware/getBinary.d.ts.map +1 -1
- package/dist/api/firmware/progressThrottle.d.ts +3 -0
- package/dist/api/firmware/progressThrottle.d.ts.map +1 -0
- package/dist/api/firmware/updateBootloader.d.ts +2 -0
- package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
- package/dist/api/firmware/uploadFirmware.d.ts +9 -1
- package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
- package/dist/api/helpers/protocolV2FileWrite.d.ts +0 -2
- package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
- package/dist/api/index.d.ts +0 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -1
- package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
- package/dist/core/deviceEventRegistration.d.ts +0 -2
- package/dist/core/deviceEventRegistration.d.ts.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/data-manager/DataManager.d.ts +1 -0
- package/dist/data-manager/DataManager.d.ts.map +1 -1
- package/dist/data-manager/connectSettings.d.ts.map +1 -1
- package/dist/device/Device.d.ts +4 -22
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/events/device.d.ts +0 -4
- package/dist/events/device.d.ts.map +1 -1
- package/dist/events/logBlockEvent.d.ts.map +1 -1
- package/dist/events/ui-request.d.ts +2 -27
- package/dist/events/ui-request.d.ts.map +1 -1
- package/dist/index.d.ts +181 -88
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3162 -1614
- package/dist/inject.d.ts.map +1 -1
- package/dist/lowLevelInject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/lockedError.d.ts +2 -0
- package/dist/protocols/protocol-v2/lockedError.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/uiInteraction.d.ts +3 -3
- package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockPolicy.d.ts +3 -1
- package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockRetry.d.ts +10 -0
- package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/walletSession.d.ts +1 -4
- package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
- package/dist/topLevelInject.d.ts.map +1 -1
- package/dist/types/api/checkAllFirmwareRelease.d.ts +4 -0
- package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/deviceUpdateBootloader.d.ts +6 -0
- package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
- package/dist/types/api/export.d.ts +4 -1
- package/dist/types/api/export.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdate.d.ts +69 -0
- package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdateCapabilities.d.ts +9 -0
- package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +1 -0
- package/dist/types/api/firmwareUpdatePlan.d.ts +28 -0
- package/dist/types/api/firmwareUpdatePlan.d.ts.map +1 -0
- package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +42 -0
- package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +1 -0
- package/dist/types/api/index.d.ts +10 -3
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/protocolV2.d.ts +0 -3
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/settings.d.ts +13 -0
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesUtils.d.ts +0 -2
- package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
- package/dist/utils/homescreen.d.ts +0 -4
- package/dist/utils/homescreen.d.ts.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/patch.d.ts +1 -1
- package/dist/utils/patch.d.ts.map +1 -1
- package/dist/utils/pro2Wallpaper.d.ts +0 -10
- package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/BaseMethod.ts +10 -8
- package/src/api/CheckAllFirmwareRelease.ts +51 -6
- package/src/api/FirmwareUpdateV2.ts +298 -120
- package/src/api/FirmwareUpdateV3.ts +263 -57
- package/src/api/FirmwareUpdateV4.ts +748 -281
- package/src/api/GetPassphraseState.ts +1 -7
- package/src/api/OpenWalletSession.ts +17 -54
- package/src/api/allnetwork/AllNetworkGetAddressBase.ts +11 -32
- package/src/api/device/DeviceUnlock.ts +1 -1
- package/src/api/device/DeviceUpdateBootloader.ts +122 -6
- package/src/api/firmware/FirmwareArtifactSource.ts +278 -0
- package/src/api/firmware/FirmwareHostBinding.ts +100 -0
- package/src/api/firmware/FirmwarePreparationError.ts +12 -0
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +57 -0
- package/src/api/firmware/FirmwareUpdateCapabilities.ts +9 -0
- package/src/api/firmware/FirmwareUpdatePlan.ts +745 -0
- package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +392 -0
- package/src/api/firmware/progressThrottle.ts +44 -0
- package/src/api/firmware/updateBootloader.ts +19 -4
- package/src/api/firmware/uploadFirmware.ts +140 -22
- package/src/api/helpers/protocolV2FileWrite.ts +4 -11
- package/src/api/index.ts +0 -1
- package/src/api/protocol-v2/ProtocolInfoRequest.ts +1 -3
- package/src/core/deviceEventRegistration.ts +0 -4
- package/src/core/index.ts +75 -118
- package/src/data/messages/messages-protocol-v2.json +0 -10
- package/src/data-manager/DataManager.ts +33 -33
- package/src/data-manager/connectSettings.ts +11 -0
- package/src/device/Device.ts +21 -193
- package/src/events/device.ts +0 -4
- package/src/events/logBlockEvent.ts +0 -1
- package/src/events/ui-request.ts +2 -32
- package/src/index.ts +5 -0
- package/src/inject.ts +22 -3
- package/src/lowLevelInject.ts +5 -1
- package/src/protocols/protocol-v2/features.ts +2 -9
- package/src/protocols/protocol-v2/lockedError.ts +10 -0
- package/src/protocols/protocol-v2/uiInteraction.ts +5 -31
- package/src/protocols/protocol-v2/unlockPolicy.ts +105 -1
- package/src/protocols/protocol-v2/unlockRetry.ts +109 -0
- package/src/protocols/protocol-v2/walletSession.ts +18 -93
- package/src/topLevelInject.ts +5 -1
- package/src/types/api/checkAllFirmwareRelease.ts +4 -0
- package/src/types/api/deviceUpdateBootloader.ts +6 -0
- package/src/types/api/export.ts +18 -0
- package/src/types/api/firmwareUpdate.ts +76 -0
- package/src/types/api/firmwareUpdateCapabilities.ts +9 -0
- package/src/types/api/firmwareUpdatePlan.ts +38 -0
- package/src/types/api/firmwareUpdatePreparedPlan.ts +53 -0
- package/src/types/api/index.ts +14 -2
- package/src/types/api/protocolV2.ts +0 -13
- package/src/types/settings.ts +13 -0
- package/src/utils/deviceFeaturesUtils.ts +0 -4
- package/src/utils/homescreen.ts +6 -32
- package/src/utils/index.ts +1 -6
- package/src/utils/pro2Wallpaper.ts +8 -35
- package/__tests__/deviceUploadNft.test.ts +0 -187
- package/__tests__/pro2Nft.test.ts +0 -108
- package/__tests__/protocol-v2-ui-lifecycle.test.ts +0 -56
- package/__tests__/uiProgressThrottle.test.ts +0 -74
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts +0 -30
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +0 -1
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +0 -22
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +0 -1
- package/dist/utils/pro2Nft.d.ts +0 -29
- package/dist/utils/pro2Nft.d.ts.map +0 -1
- package/dist/utils/uiProgressThrottle.d.ts +0 -3
- package/dist/utils/uiProgressThrottle.d.ts.map +0 -1
- package/src/api/protocol-v2/DeviceUploadNft.ts +0 -166
- package/src/protocols/protocol-v2/unlockPolicyRunner.ts +0 -117
- package/src/utils/pro2Nft.ts +0 -91
- package/src/utils/uiProgressThrottle.ts +0 -63
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { UI_REQUEST, createUiMessage } from '../../events';
|
|
2
2
|
|
|
3
|
-
import type { CoreMessage,
|
|
3
|
+
import type { CoreMessage, ProtocolV2UiCompletion } from '../../events';
|
|
4
4
|
import type { Device } from '../../device/Device';
|
|
5
5
|
import type { KnownDevice } from '../../types';
|
|
6
6
|
|
|
@@ -28,15 +28,7 @@ type ProtocolV2InteractionMethod = {
|
|
|
28
28
|
protocolV2UiInteraction?: ProtocolV2InteractionDescriptor;
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
-
type InteractionDevice = Pick<Device, 'isProtocolV2' | 'toMessageObject'
|
|
32
|
-
Partial<
|
|
33
|
-
Pick<
|
|
34
|
-
Device,
|
|
35
|
-
| 'createProtocolV2UiPhaseMetadata'
|
|
36
|
-
| 'finishProtocolV2UiInteraction'
|
|
37
|
-
| 'hasOpenProtocolV2UiInteraction'
|
|
38
|
-
>
|
|
39
|
-
>;
|
|
31
|
+
type InteractionDevice = Pick<Device, 'isProtocolV2' | 'toMessageObject'>;
|
|
40
32
|
type PostMessage = (message: CoreMessage) => void;
|
|
41
33
|
|
|
42
34
|
export const isProtocolV2UiEnabled = (method: { protocolV2UiMode?: 'auto' | 'none' }) =>
|
|
@@ -164,17 +156,12 @@ export class ProtocolV2UiInteractionCoordinator {
|
|
|
164
156
|
this.methodInteraction = interaction;
|
|
165
157
|
if (!interaction) return;
|
|
166
158
|
const { request, ...metadata } = interaction;
|
|
167
|
-
const interactionMeta = this.device.createProtocolV2UiPhaseMetadata?.(
|
|
168
|
-
request === 'pin' ? 'pin' : 'button',
|
|
169
|
-
'start'
|
|
170
|
-
);
|
|
171
159
|
|
|
172
160
|
this.emit(
|
|
173
161
|
request === 'pin' ? UI_REQUEST.REQUEST_PIN : UI_REQUEST.REQUEST_BUTTON,
|
|
174
162
|
{
|
|
175
163
|
device: this.device.toMessageObject() as KnownDevice,
|
|
176
164
|
...metadata,
|
|
177
|
-
...(interactionMeta ? { interaction: interactionMeta } : {}),
|
|
178
165
|
},
|
|
179
166
|
`method:${request}:${interaction.reason}:${interaction.page ?? ''}:${
|
|
180
167
|
interaction.operation ?? ''
|
|
@@ -182,8 +169,7 @@ export class ProtocolV2UiInteractionCoordinator {
|
|
|
182
169
|
);
|
|
183
170
|
}
|
|
184
171
|
|
|
185
|
-
enterUnlockInteraction(method?: string)
|
|
186
|
-
const interaction = this.device.createProtocolV2UiPhaseMetadata?.('pin', 'start');
|
|
172
|
+
enterUnlockInteraction(method?: string) {
|
|
187
173
|
this.emit(
|
|
188
174
|
UI_REQUEST.REQUEST_PIN,
|
|
189
175
|
{
|
|
@@ -192,11 +178,9 @@ export class ProtocolV2UiInteractionCoordinator {
|
|
|
192
178
|
reason: 'device-locked',
|
|
193
179
|
deviceOnly: true,
|
|
194
180
|
method,
|
|
195
|
-
...(interaction ? { interaction } : {}),
|
|
196
181
|
},
|
|
197
182
|
`unlock:${method ?? ''}`
|
|
198
183
|
);
|
|
199
|
-
return interaction;
|
|
200
184
|
}
|
|
201
185
|
|
|
202
186
|
resumeMethodInteraction() {
|
|
@@ -204,19 +188,9 @@ export class ProtocolV2UiInteractionCoordinator {
|
|
|
204
188
|
}
|
|
205
189
|
|
|
206
190
|
close() {
|
|
207
|
-
if (
|
|
208
|
-
!this.device.isProtocolV2() ||
|
|
209
|
-
(!this.opened && !this.device.hasOpenProtocolV2UiInteraction?.()) ||
|
|
210
|
-
this.closed
|
|
211
|
-
)
|
|
212
|
-
return;
|
|
191
|
+
if (!this.device.isProtocolV2() || !this.opened || this.closed) return;
|
|
213
192
|
this.closed = true;
|
|
214
|
-
|
|
215
|
-
this.postMessage(
|
|
216
|
-
interaction
|
|
217
|
-
? createUiMessage(UI_REQUEST.CLOSE_UI_WINDOW, interaction)
|
|
218
|
-
: createUiMessage(UI_REQUEST.CLOSE_UI_WINDOW)
|
|
219
|
-
);
|
|
193
|
+
this.postMessage(createUiMessage(UI_REQUEST.CLOSE_UI_WINDOW));
|
|
220
194
|
}
|
|
221
195
|
|
|
222
196
|
private emit(
|
|
@@ -1 +1,105 @@
|
|
|
1
|
-
export type UnlockPolicy = 'none' | 'unlock-before-run';
|
|
1
|
+
export type UnlockPolicy = 'none' | 'unlock-before-run' | 'retry-on-locked';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Protocol V2 methods that are safe to replay after a locked response.
|
|
5
|
+
*
|
|
6
|
+
* Keep this as an exact allowlist. Name-pattern matching can silently make a new
|
|
7
|
+
* state-changing method replayable when it happens to share a suffix.
|
|
8
|
+
*/
|
|
9
|
+
export const PROTOCOL_V2_RETRY_ON_LOCKED_METHODS = [
|
|
10
|
+
'cipherKeyValue',
|
|
11
|
+
'allNetworkGetAddress',
|
|
12
|
+
'allNetworkGetAddressByLoop',
|
|
13
|
+
'btcGetAddress',
|
|
14
|
+
'btcGetPublicKey',
|
|
15
|
+
'btcSignMessage',
|
|
16
|
+
'btcSignPsbt',
|
|
17
|
+
'btcSignTransaction',
|
|
18
|
+
'btcVerifyMessage',
|
|
19
|
+
'confluxGetAddress',
|
|
20
|
+
'confluxSignMessage',
|
|
21
|
+
'confluxSignTransaction',
|
|
22
|
+
'evmGetAddress',
|
|
23
|
+
'evmGetPublicKey',
|
|
24
|
+
'evmSignMessage',
|
|
25
|
+
'evmSignTransaction',
|
|
26
|
+
'evmSignTypedData',
|
|
27
|
+
'evmVerifyMessage',
|
|
28
|
+
'starcoinGetAddress',
|
|
29
|
+
'starcoinGetPublicKey',
|
|
30
|
+
'starcoinSignMessage',
|
|
31
|
+
'starcoinSignTransaction',
|
|
32
|
+
'starcoinVerifyMessage',
|
|
33
|
+
'nemGetAddress',
|
|
34
|
+
'nemSignTransaction',
|
|
35
|
+
'solGetAddress',
|
|
36
|
+
'solSignTransaction',
|
|
37
|
+
'solSignOffchainMessage',
|
|
38
|
+
'solSignMessage',
|
|
39
|
+
'stellarGetAddress',
|
|
40
|
+
'stellarSignTransaction',
|
|
41
|
+
'tronGetAddress',
|
|
42
|
+
'tronSignMessage',
|
|
43
|
+
'tronSignTransaction',
|
|
44
|
+
'nearGetAddress',
|
|
45
|
+
'nearSignTransaction',
|
|
46
|
+
'aptosGetAddress',
|
|
47
|
+
'aptosGetPublicKey',
|
|
48
|
+
'aptosSignTransaction',
|
|
49
|
+
'aptosSignMessage',
|
|
50
|
+
'aptosSignInMessage',
|
|
51
|
+
'algoGetAddress',
|
|
52
|
+
'algoSignTransaction',
|
|
53
|
+
'cosmosGetAddress',
|
|
54
|
+
'cosmosGetPublicKey',
|
|
55
|
+
'cosmosSignTransaction',
|
|
56
|
+
'xrpGetAddress',
|
|
57
|
+
'xrpSignTransaction',
|
|
58
|
+
'suiGetAddress',
|
|
59
|
+
'suiGetPublicKey',
|
|
60
|
+
'suiSignMessage',
|
|
61
|
+
'suiSignTransaction',
|
|
62
|
+
'cardanoGetAddress',
|
|
63
|
+
'cardanoGetPublicKey',
|
|
64
|
+
'cardanoSignTransaction',
|
|
65
|
+
'cardanoSignMessage',
|
|
66
|
+
'filecoinGetAddress',
|
|
67
|
+
'filecoinSignTransaction',
|
|
68
|
+
'polkadotGetAddress',
|
|
69
|
+
'polkadotSignTransaction',
|
|
70
|
+
'kaspaGetAddress',
|
|
71
|
+
'kaspaSignTransaction',
|
|
72
|
+
'nexaGetAddress',
|
|
73
|
+
'nexaSignTransaction',
|
|
74
|
+
'nostrGetPublicKey',
|
|
75
|
+
'nostrSignEvent',
|
|
76
|
+
'nostrEncryptMessage',
|
|
77
|
+
'nostrDecryptMessage',
|
|
78
|
+
'nostrSignSchnorr',
|
|
79
|
+
'lnurlAuth',
|
|
80
|
+
'nervosGetAddress',
|
|
81
|
+
'nervosSignTransaction',
|
|
82
|
+
'dnxGetAddress',
|
|
83
|
+
'dnxSignTransaction',
|
|
84
|
+
'tonGetAddress',
|
|
85
|
+
'tonSignMessage',
|
|
86
|
+
'tonSignProof',
|
|
87
|
+
'tonSignData',
|
|
88
|
+
'scdoGetAddress',
|
|
89
|
+
'scdoSignTransaction',
|
|
90
|
+
'scdoSignMessage',
|
|
91
|
+
'alephiumGetAddress',
|
|
92
|
+
'alephiumSignTransaction',
|
|
93
|
+
'alephiumSignMessage',
|
|
94
|
+
'benfenGetAddress',
|
|
95
|
+
'benfenGetPublicKey',
|
|
96
|
+
'benfenSignMessage',
|
|
97
|
+
'benfenSignTransaction',
|
|
98
|
+
'neoGetAddress',
|
|
99
|
+
'neoSignTransaction',
|
|
100
|
+
] as const;
|
|
101
|
+
|
|
102
|
+
const retryOnLockedMethods = new Set<string>(PROTOCOL_V2_RETRY_ON_LOCKED_METHODS);
|
|
103
|
+
|
|
104
|
+
export const getProtocolV2UnlockPolicy = (methodName: string): UnlockPolicy =>
|
|
105
|
+
retryOnLockedMethods.has(methodName) ? 'retry-on-locked' : 'none';
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { LoggerNames, getLogger } from '../../utils';
|
|
2
|
+
import { isDeviceLockedError } from './lockedError';
|
|
3
|
+
import { isProtocolV2UiEnabled, resolveProtocolV2UiInteraction } from './uiInteraction';
|
|
4
|
+
import { refreshProtocolV2DeviceStatus, restoreProtocolV2WalletSession } from './walletSession';
|
|
5
|
+
|
|
6
|
+
import type { BaseMethod } from '../../api/BaseMethod';
|
|
7
|
+
import type { Device } from '../../device/Device';
|
|
8
|
+
import type { ProtocolV2UiInteractionCoordinator } from './uiInteraction';
|
|
9
|
+
|
|
10
|
+
const Log = getLogger(LoggerNames.Core);
|
|
11
|
+
|
|
12
|
+
type RunnableMethod = Pick<
|
|
13
|
+
BaseMethod,
|
|
14
|
+
| 'run'
|
|
15
|
+
| 'unlockPolicy'
|
|
16
|
+
| 'protocolV2UiInteraction'
|
|
17
|
+
| 'protocolV2UiMode'
|
|
18
|
+
| 'params'
|
|
19
|
+
| 'payload'
|
|
20
|
+
| 'useDevicePassphraseState'
|
|
21
|
+
> & { name?: string };
|
|
22
|
+
type UiInteractionCoordinator = Pick<
|
|
23
|
+
ProtocolV2UiInteractionCoordinator,
|
|
24
|
+
'enterMethodInteraction' | 'enterUnlockInteraction' | 'resumeMethodInteraction'
|
|
25
|
+
>;
|
|
26
|
+
|
|
27
|
+
const restoreExpectedWalletSessionAfterUnlock = async (method: RunnableMethod, device: Device) => {
|
|
28
|
+
const expectedPassphraseState = method.payload?.useEmptyPassphrase
|
|
29
|
+
? undefined
|
|
30
|
+
: method.payload?.passphraseState ?? device.passphraseState;
|
|
31
|
+
if (
|
|
32
|
+
!method.useDevicePassphraseState ||
|
|
33
|
+
typeof expectedPassphraseState !== 'string' ||
|
|
34
|
+
expectedPassphraseState.length === 0
|
|
35
|
+
) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
await restoreProtocolV2WalletSession(device, expectedPassphraseState);
|
|
40
|
+
Log.debug('Protocol V2 wallet session restored after unlock', { method: method.name });
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export async function runMethodWithUnlockRetry(
|
|
44
|
+
method: RunnableMethod,
|
|
45
|
+
device: Device,
|
|
46
|
+
uiCoordinator?: UiInteractionCoordinator
|
|
47
|
+
) {
|
|
48
|
+
const shouldEmitUi = isProtocolV2UiEnabled(method);
|
|
49
|
+
const isProtocolV2 = device.isProtocolV2();
|
|
50
|
+
const requiresFreshStatus =
|
|
51
|
+
isProtocolV2 &&
|
|
52
|
+
method.unlockPolicy === 'unlock-before-run' &&
|
|
53
|
+
!device.isBootloader?.() &&
|
|
54
|
+
!device.isRomloader?.();
|
|
55
|
+
|
|
56
|
+
if (requiresFreshStatus) {
|
|
57
|
+
await refreshProtocolV2DeviceStatus(device);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const shouldUnlockBeforeRun =
|
|
61
|
+
isProtocolV2 &&
|
|
62
|
+
method.unlockPolicy !== 'none' &&
|
|
63
|
+
!device.isBootloader?.() &&
|
|
64
|
+
!device.isRomloader?.() &&
|
|
65
|
+
device.features?.unlocked === false;
|
|
66
|
+
|
|
67
|
+
if (shouldUnlockBeforeRun) {
|
|
68
|
+
if (shouldEmitUi) {
|
|
69
|
+
uiCoordinator?.enterUnlockInteraction(method.name);
|
|
70
|
+
}
|
|
71
|
+
await device.unlockDevice();
|
|
72
|
+
Log.debug('Protocol V2 pre-unlock completed', { method: method.name });
|
|
73
|
+
await restoreExpectedWalletSessionAfterUnlock(method, device);
|
|
74
|
+
if (shouldEmitUi) {
|
|
75
|
+
uiCoordinator?.enterMethodInteraction(resolveProtocolV2UiInteraction(method));
|
|
76
|
+
}
|
|
77
|
+
return method.run();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (shouldEmitUi) {
|
|
81
|
+
uiCoordinator?.enterMethodInteraction(resolveProtocolV2UiInteraction(method));
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
return await method.run();
|
|
85
|
+
} catch (error) {
|
|
86
|
+
if (!isProtocolV2 || method.unlockPolicy !== 'retry-on-locked' || !isDeviceLockedError(error)) {
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
Log.debug('Protocol V2 unlock retry triggered', { method: method.name });
|
|
91
|
+
if (shouldEmitUi) {
|
|
92
|
+
uiCoordinator?.enterUnlockInteraction(method.name);
|
|
93
|
+
}
|
|
94
|
+
await device.unlockDevice();
|
|
95
|
+
Log.debug('Protocol V2 unlock completed', { method: method.name });
|
|
96
|
+
await restoreExpectedWalletSessionAfterUnlock(method, device);
|
|
97
|
+
if (shouldEmitUi) {
|
|
98
|
+
uiCoordinator?.resumeMethodInteraction();
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
const response = await method.run();
|
|
102
|
+
Log.debug('Protocol V2 method retry completed', { method: method.name, success: true });
|
|
103
|
+
return response;
|
|
104
|
+
} catch (retryError) {
|
|
105
|
+
Log.debug('Protocol V2 method retry completed', { method: method.name, success: false });
|
|
106
|
+
throw retryError;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -38,26 +38,10 @@ export async function refreshProtocolV2DeviceStatus(device: Device) {
|
|
|
38
38
|
return device.updateProtocolV2Status(status);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
export async function ensureProtocolV2WalletSessionUnlocked(device: Device) {
|
|
42
|
-
if (!device.isProtocolV2() || device.isBootloader?.() || device.isRomloader?.()) {
|
|
43
|
-
return false;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
await refreshProtocolV2DeviceStatus(device);
|
|
47
|
-
if (device.state?.status.unlocked !== false) {
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
await device.unlockDevice(DeviceSessionPinType.Main, {
|
|
52
|
-
source: 'unlock-coordinator',
|
|
53
|
-
reason: 'device-locked',
|
|
54
|
-
deviceOnly: true,
|
|
55
|
-
});
|
|
56
|
-
return true;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
41
|
const negotiateEventlessWalletSession = async (device: Device) => {
|
|
60
|
-
await device.
|
|
42
|
+
await device.commands.typedCall('ProtocolInfoRequest', 'ProtocolInfo', {
|
|
43
|
+
eventless_wallet_session: true,
|
|
44
|
+
});
|
|
61
45
|
};
|
|
62
46
|
|
|
63
47
|
const getDeviceSession = async (device: Device, request: DeviceSessionGet) =>
|
|
@@ -75,13 +59,11 @@ const selectDeviceSession = async (device: Device, expectedPassphraseState?: str
|
|
|
75
59
|
reason: expectedPassphraseState ? ('session-recovery' as const) : ('open-wallet' as const),
|
|
76
60
|
...(expectedPassphraseState ? { expectedPassphraseState } : {}),
|
|
77
61
|
};
|
|
78
|
-
const passphraseInteraction = device.createProtocolV2UiPhaseMetadata?.('passphrase', 'start');
|
|
79
62
|
const response = await device.commands.promptPassphrase(
|
|
80
63
|
{
|
|
81
64
|
existsAttachPinUser,
|
|
82
65
|
deviceOnly: false,
|
|
83
66
|
...metadata,
|
|
84
|
-
...(passphraseInteraction ? { interaction: passphraseInteraction } : {}),
|
|
85
67
|
},
|
|
86
68
|
{ cancelDeviceOnReject: false }
|
|
87
69
|
);
|
|
@@ -120,15 +102,8 @@ const selectDeviceSession = async (device: Device, expectedPassphraseState?: str
|
|
|
120
102
|
'Attach PIN wallet selection is unavailable on this device.'
|
|
121
103
|
);
|
|
122
104
|
}
|
|
123
|
-
|
|
124
|
-
device.
|
|
125
|
-
...metadata,
|
|
126
|
-
...(attachPinInteraction ? { interaction: attachPinInteraction } : {}),
|
|
127
|
-
});
|
|
128
|
-
await device.unlockDevice(DeviceSessionPinType.AttachToPin, {
|
|
129
|
-
emitUiEvent: false,
|
|
130
|
-
interaction: attachPinInteraction,
|
|
131
|
-
});
|
|
105
|
+
device.emit(DEVICE.ATTACH_PIN_ON_DEVICE, device, metadata);
|
|
106
|
+
await device.unlockDevice(DeviceSessionPinType.AttachToPin);
|
|
132
107
|
return getDeviceSession(device, {});
|
|
133
108
|
}
|
|
134
109
|
|
|
@@ -140,10 +115,7 @@ const selectDeviceSession = async (device: Device, expectedPassphraseState?: str
|
|
|
140
115
|
return getDeviceSession(device, {});
|
|
141
116
|
}
|
|
142
117
|
|
|
143
|
-
device.emit(DEVICE.PASSPHRASE_ON_DEVICE, device,
|
|
144
|
-
...metadata,
|
|
145
|
-
...(passphraseInteraction ? { interaction: passphraseInteraction } : {}),
|
|
146
|
-
});
|
|
118
|
+
device.emit(DEVICE.PASSPHRASE_ON_DEVICE, device, metadata);
|
|
147
119
|
await askDevicePassphrase(device, { on_device: true });
|
|
148
120
|
return getDeviceSession(device, {});
|
|
149
121
|
};
|
|
@@ -156,9 +128,7 @@ export async function getProtocolV2WalletSession(
|
|
|
156
128
|
initSession?: boolean;
|
|
157
129
|
expectedPassphraseState?: string;
|
|
158
130
|
onlyMainPin?: boolean;
|
|
159
|
-
selectMainWalletBeforeRestore?: boolean;
|
|
160
131
|
resumeOnly?: boolean;
|
|
161
|
-
deriveCardano?: boolean;
|
|
162
132
|
}
|
|
163
133
|
) {
|
|
164
134
|
const forceWalletSelection =
|
|
@@ -191,48 +161,13 @@ export async function getProtocolV2WalletSession(
|
|
|
191
161
|
: undefined;
|
|
192
162
|
let response;
|
|
193
163
|
let resumed = false;
|
|
194
|
-
let mainWalletSelected = false;
|
|
195
|
-
|
|
196
|
-
const clearCurrentWalletSession = () => {
|
|
197
|
-
if (options?.onlyMainPin) {
|
|
198
|
-
device.clearStandardInternalState?.();
|
|
199
|
-
} else {
|
|
200
|
-
device.clearInternalState();
|
|
201
|
-
}
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
const rejectMismatchedAttachPinWallet = async () => {
|
|
205
|
-
const features = await refreshProtocolV2DeviceStatus(device);
|
|
206
|
-
if (features.unlockedAttachPin !== true) {
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
try {
|
|
211
|
-
await device.lockDevice();
|
|
212
|
-
} catch {
|
|
213
|
-
// Reject the mismatched Attach PIN wallet even when older firmware cannot lock.
|
|
214
|
-
}
|
|
215
|
-
clearCurrentWalletSession();
|
|
216
|
-
throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckUnlockTypeError);
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
const selectMainWallet = async (force = false) => {
|
|
220
|
-
if (force || !mainWalletSelected) {
|
|
221
|
-
await device.unlockDevice(DeviceSessionPinType.Main, {
|
|
222
|
-
source: 'wallet-session-coordinator',
|
|
223
|
-
reason: expectedPassphraseState ? 'session-recovery' : 'open-wallet',
|
|
224
|
-
deviceOnly: true,
|
|
225
|
-
});
|
|
226
|
-
mainWalletSelected = true;
|
|
227
|
-
}
|
|
228
|
-
};
|
|
229
164
|
|
|
230
165
|
if (options?.onlyMainPin) {
|
|
231
166
|
expectedPassphraseState = cachedStandardSession?.passphraseState;
|
|
232
167
|
if (cachedStandardSession) {
|
|
233
168
|
try {
|
|
234
|
-
if (
|
|
235
|
-
await
|
|
169
|
+
if (device.features?.unlockedAttachPin === true) {
|
|
170
|
+
await device.unlockDevice(DeviceSessionPinType.Main);
|
|
236
171
|
}
|
|
237
172
|
response = await getDeviceSession(device, {
|
|
238
173
|
session_id: cachedStandardSession.sessionId,
|
|
@@ -248,14 +183,12 @@ export async function getProtocolV2WalletSession(
|
|
|
248
183
|
}
|
|
249
184
|
|
|
250
185
|
if (!response) {
|
|
251
|
-
await
|
|
186
|
+
await device.unlockDevice(DeviceSessionPinType.Main);
|
|
252
187
|
response = await getDeviceSession(device, {});
|
|
253
188
|
}
|
|
254
189
|
} else if (cachedSessionId && expectedPassphraseState) {
|
|
255
190
|
try {
|
|
256
|
-
response = await getDeviceSession(device, {
|
|
257
|
-
session_id: cachedSessionId,
|
|
258
|
-
});
|
|
191
|
+
response = await getDeviceSession(device, { session_id: cachedSessionId });
|
|
259
192
|
resumed = true;
|
|
260
193
|
} catch (error) {
|
|
261
194
|
device.clearInternalState();
|
|
@@ -264,14 +197,6 @@ export async function getProtocolV2WalletSession(
|
|
|
264
197
|
}
|
|
265
198
|
resumed = false;
|
|
266
199
|
}
|
|
267
|
-
} else if (expectedPassphraseState) {
|
|
268
|
-
try {
|
|
269
|
-
response = await getDeviceSession(device, {});
|
|
270
|
-
} catch (error) {
|
|
271
|
-
if (options?.resumeOnly || !isWalletSessionInvalidError(error)) {
|
|
272
|
-
throw error;
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
200
|
}
|
|
276
201
|
|
|
277
202
|
if (!response) {
|
|
@@ -295,14 +220,13 @@ export async function getProtocolV2WalletSession(
|
|
|
295
220
|
}
|
|
296
221
|
if (expectedPassphraseState && expectedPassphraseState !== message.btc_test_address) {
|
|
297
222
|
resumed = false;
|
|
298
|
-
await rejectMismatchedAttachPinWallet();
|
|
299
223
|
if (options?.resumeOnly) {
|
|
300
224
|
device.clearInternalState();
|
|
301
225
|
throw ERRORS.TypedError(HardwareErrorCode.WalletSessionInvalid);
|
|
302
226
|
}
|
|
303
227
|
if (options?.onlyMainPin) {
|
|
304
228
|
device.clearStandardInternalState?.();
|
|
305
|
-
await
|
|
229
|
+
await device.unlockDevice(DeviceSessionPinType.Main);
|
|
306
230
|
response = await getDeviceSession(device, {});
|
|
307
231
|
} else {
|
|
308
232
|
device.clearInternalState();
|
|
@@ -320,8 +244,11 @@ export async function getProtocolV2WalletSession(
|
|
|
320
244
|
throw error;
|
|
321
245
|
}
|
|
322
246
|
if (expectedPassphraseState !== message.btc_test_address) {
|
|
323
|
-
|
|
324
|
-
|
|
247
|
+
if (options?.onlyMainPin) {
|
|
248
|
+
device.clearStandardInternalState?.();
|
|
249
|
+
} else {
|
|
250
|
+
device.clearInternalState();
|
|
251
|
+
}
|
|
325
252
|
throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckPassphraseStateError);
|
|
326
253
|
}
|
|
327
254
|
}
|
|
@@ -342,19 +269,17 @@ export async function getProtocolV2WalletSession(
|
|
|
342
269
|
return {
|
|
343
270
|
passphraseState: message.btc_test_address,
|
|
344
271
|
newSession: message.session_id,
|
|
345
|
-
unlockedAttachPin:
|
|
272
|
+
unlockedAttachPin: device.features?.unlockedAttachPin ?? undefined,
|
|
346
273
|
resumed,
|
|
347
274
|
};
|
|
348
275
|
}
|
|
349
276
|
|
|
350
277
|
export async function restoreProtocolV2WalletSession(
|
|
351
278
|
device: Device,
|
|
352
|
-
expectedPassphraseState: string
|
|
353
|
-
deriveCardano?: boolean
|
|
279
|
+
expectedPassphraseState: string
|
|
354
280
|
) {
|
|
355
281
|
return getProtocolV2WalletSession(device, {
|
|
356
282
|
expectedPassphraseState,
|
|
357
283
|
resumeOnly: true,
|
|
358
|
-
deriveCardano,
|
|
359
284
|
});
|
|
360
285
|
}
|
package/src/topLevelInject.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import EventEmitter from 'events';
|
|
2
2
|
|
|
3
3
|
import { createCoreApi } from './inject';
|
|
4
|
+
import { unregisterFirmwareUpdateHostBinding } from './api/firmware/FirmwareHostBinding';
|
|
4
5
|
|
|
5
6
|
import type { ConnectSettings } from './types/settings';
|
|
6
7
|
import type { CoreApi } from './types/api';
|
|
@@ -46,7 +47,10 @@ export const topLevelInject = () => {
|
|
|
46
47
|
lowLevelApi?.removeAllListeners(type);
|
|
47
48
|
},
|
|
48
49
|
|
|
49
|
-
dispose: () =>
|
|
50
|
+
dispose: async () => {
|
|
51
|
+
unregisterFirmwareUpdateHostBinding();
|
|
52
|
+
await lowLevelApi?.dispose();
|
|
53
|
+
},
|
|
50
54
|
|
|
51
55
|
uiResponse: response => lowLevelApi?.uiResponse(response),
|
|
52
56
|
|
|
@@ -12,6 +12,7 @@ import type {
|
|
|
12
12
|
IProtocolV2FirmwareComponentTarget,
|
|
13
13
|
} from '../settings';
|
|
14
14
|
import type { FirmwareUpdateV4Target } from './firmwareUpdate';
|
|
15
|
+
import type { FirmwareUpdatePlan, FirmwareUpdatePlanForceTarget } from './firmwareUpdatePlan';
|
|
15
16
|
|
|
16
17
|
export type FirmwareRelease = {
|
|
17
18
|
shouldUpdate?: boolean;
|
|
@@ -63,11 +64,14 @@ export type AllFirmwareRelease = {
|
|
|
63
64
|
components?: ProtocolV2FirmwareComponentRelease[];
|
|
64
65
|
targetsToUpdate?: FirmwareUpdateV4Target[];
|
|
65
66
|
release?: IFirmwareReleaseInfo;
|
|
67
|
+
firmwareUpdatePlan?: FirmwareUpdatePlan;
|
|
66
68
|
};
|
|
67
69
|
|
|
68
70
|
export type CheckAllFirmwareReleaseParams = {
|
|
69
71
|
checkBridgeRelease?: boolean;
|
|
70
72
|
firmwareType?: EFirmwareType;
|
|
73
|
+
platform?: 'native' | 'desktop' | 'ext' | 'web' | 'web-embed';
|
|
74
|
+
forceUpdateTargets?: FirmwareUpdatePlanForceTarget[];
|
|
71
75
|
};
|
|
72
76
|
|
|
73
77
|
export declare function checkAllFirmwareRelease(
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import type { Success } from '@onekeyfe/hd-transport';
|
|
2
2
|
import type { EFirmwareType } from '@onekeyfe/hd-shared';
|
|
3
|
+
import type { FirmwareArtifactReader, FirmwareArtifactReference } from './firmwareUpdate';
|
|
4
|
+
import type { FirmwareUpdatePreparedPlan } from './firmwareUpdatePreparedPlan';
|
|
3
5
|
import type { Response } from '../params';
|
|
4
6
|
|
|
5
7
|
export type DeviceUpdateBootloaderParams = {
|
|
8
|
+
preparedPlan?: FirmwareUpdatePreparedPlan;
|
|
9
|
+
hostBindingGeneration?: number;
|
|
6
10
|
binary?: ArrayBuffer;
|
|
11
|
+
artifact?: FirmwareArtifactReference;
|
|
12
|
+
artifactReader?: FirmwareArtifactReader;
|
|
7
13
|
firmwareType?: EFirmwareType;
|
|
8
14
|
};
|
|
9
15
|
|
package/src/types/api/export.ts
CHANGED
|
@@ -25,12 +25,30 @@ export type {
|
|
|
25
25
|
DeviceUploadResourceResponse,
|
|
26
26
|
} from './deviceUploadResource';
|
|
27
27
|
export type {
|
|
28
|
+
FirmwareArtifactReader,
|
|
29
|
+
FirmwareArtifactReference,
|
|
30
|
+
FirmwareUpdateHostBinding,
|
|
31
|
+
FirmwareUpdateArtifactParams,
|
|
28
32
|
FirmwareUpdateParams,
|
|
29
33
|
FirmwareUpdateBinaryParams,
|
|
30
34
|
FirmwareUpdateV3Params,
|
|
31
35
|
FirmwareUpdateV4Params,
|
|
32
36
|
FirmwareUpdateV4Target,
|
|
33
37
|
} from './firmwareUpdate';
|
|
38
|
+
export type {
|
|
39
|
+
FirmwareUpdatePlan,
|
|
40
|
+
FirmwareUpdatePlanArtifact,
|
|
41
|
+
FirmwareUpdatePlanArtifactRole,
|
|
42
|
+
FirmwareUpdatePlanForceTarget,
|
|
43
|
+
FirmwareUpdatePlanTarget,
|
|
44
|
+
} from './firmwareUpdatePlan';
|
|
45
|
+
export type {
|
|
46
|
+
FirmwareUpdatePreparedArtifact,
|
|
47
|
+
FirmwareUpdatePreparedArtifactInput,
|
|
48
|
+
FirmwareUpdatePreparedEntry,
|
|
49
|
+
FirmwareUpdatePreparedPlan,
|
|
50
|
+
} from './firmwareUpdatePreparedPlan';
|
|
51
|
+
export type { FirmwareUpdateCapabilities } from './firmwareUpdateCapabilities';
|
|
34
52
|
export type { AllFirmwareRelease } from './checkAllFirmwareRelease';
|
|
35
53
|
export type {
|
|
36
54
|
ProtocolV2FirmwareComponentRelease,
|