@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.
Files changed (195) hide show
  1. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +0 -78
  2. package/__tests__/DeviceEventRegistration.test.ts +0 -6
  3. package/__tests__/connectSettings.test.ts +47 -5
  4. package/__tests__/firmware-update/check-all-firmware-release.test.ts +175 -0
  5. package/__tests__/firmware-update/firmware-artifact-source.test.ts +119 -0
  6. package/__tests__/firmware-update/firmware-host-binding.test.ts +70 -0
  7. package/__tests__/firmware-update/firmware-preparation-error.test.ts +27 -0
  8. package/__tests__/firmware-update/firmware-update-capabilities.test.ts +13 -0
  9. package/__tests__/firmware-update/firmware-update-plan.test.ts +593 -0
  10. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +213 -0
  11. package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +59 -31
  12. package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +58 -0
  13. package/__tests__/firmware-update/firmware-upload-source.test.ts +70 -0
  14. package/__tests__/get-device-state.test.ts +12 -132
  15. package/__tests__/homescreen.test.ts +1 -41
  16. package/__tests__/logBlockEvent.test.ts +1 -1
  17. package/__tests__/open-wallet-session.test.ts +18 -259
  18. package/__tests__/protocol-v2-unlock-policy.test.ts +35 -86
  19. package/__tests__/protocol-v2.test.ts +632 -333
  20. package/__tests__/public-pro2-api-boundary.test.ts +0 -1
  21. package/dist/api/BaseMethod.d.ts +1 -3
  22. package/dist/api/BaseMethod.d.ts.map +1 -1
  23. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  24. package/dist/api/FirmwareUpdateV2.d.ts +11 -0
  25. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  26. package/dist/api/FirmwareUpdateV3.d.ts +7 -3
  27. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  28. package/dist/api/FirmwareUpdateV4.d.ts +22 -5
  29. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  30. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  31. package/dist/api/OpenWalletSession.d.ts.map +1 -1
  32. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  33. package/dist/api/device/DeviceUpdateBootloader.d.ts +5 -1
  34. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  35. package/dist/api/firmware/FirmwareArtifactSource.d.ts +25 -0
  36. package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +1 -0
  37. package/dist/api/firmware/FirmwareHostBinding.d.ts +6 -0
  38. package/dist/api/firmware/FirmwareHostBinding.d.ts.map +1 -0
  39. package/dist/api/firmware/FirmwarePreparationError.d.ts +3 -0
  40. package/dist/api/firmware/FirmwarePreparationError.d.ts.map +1 -0
  41. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +8 -0
  42. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  43. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +3 -0
  44. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +1 -0
  45. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +25 -0
  46. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -0
  47. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +30 -0
  48. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -0
  49. package/dist/api/firmware/getBinary.d.ts +7 -0
  50. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  51. package/dist/api/firmware/progressThrottle.d.ts +3 -0
  52. package/dist/api/firmware/progressThrottle.d.ts.map +1 -0
  53. package/dist/api/firmware/updateBootloader.d.ts +2 -0
  54. package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
  55. package/dist/api/firmware/uploadFirmware.d.ts +9 -1
  56. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  57. package/dist/api/helpers/protocolV2FileWrite.d.ts +0 -2
  58. package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
  59. package/dist/api/index.d.ts +0 -1
  60. package/dist/api/index.d.ts.map +1 -1
  61. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -1
  62. package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
  63. package/dist/core/deviceEventRegistration.d.ts +0 -2
  64. package/dist/core/deviceEventRegistration.d.ts.map +1 -1
  65. package/dist/core/index.d.ts.map +1 -1
  66. package/dist/data-manager/DataManager.d.ts +1 -0
  67. package/dist/data-manager/DataManager.d.ts.map +1 -1
  68. package/dist/data-manager/connectSettings.d.ts.map +1 -1
  69. package/dist/device/Device.d.ts +4 -22
  70. package/dist/device/Device.d.ts.map +1 -1
  71. package/dist/events/device.d.ts +0 -4
  72. package/dist/events/device.d.ts.map +1 -1
  73. package/dist/events/logBlockEvent.d.ts.map +1 -1
  74. package/dist/events/ui-request.d.ts +2 -27
  75. package/dist/events/ui-request.d.ts.map +1 -1
  76. package/dist/index.d.ts +181 -88
  77. package/dist/index.d.ts.map +1 -1
  78. package/dist/index.js +3162 -1614
  79. package/dist/inject.d.ts.map +1 -1
  80. package/dist/lowLevelInject.d.ts.map +1 -1
  81. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  82. package/dist/protocols/protocol-v2/lockedError.d.ts +2 -0
  83. package/dist/protocols/protocol-v2/lockedError.d.ts.map +1 -0
  84. package/dist/protocols/protocol-v2/uiInteraction.d.ts +3 -3
  85. package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
  86. package/dist/protocols/protocol-v2/unlockPolicy.d.ts +3 -1
  87. package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -1
  88. package/dist/protocols/protocol-v2/unlockRetry.d.ts +10 -0
  89. package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +1 -0
  90. package/dist/protocols/protocol-v2/walletSession.d.ts +1 -4
  91. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  92. package/dist/topLevelInject.d.ts.map +1 -1
  93. package/dist/types/api/checkAllFirmwareRelease.d.ts +4 -0
  94. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  95. package/dist/types/api/deviceUpdateBootloader.d.ts +6 -0
  96. package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
  97. package/dist/types/api/export.d.ts +4 -1
  98. package/dist/types/api/export.d.ts.map +1 -1
  99. package/dist/types/api/firmwareUpdate.d.ts +69 -0
  100. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  101. package/dist/types/api/firmwareUpdateCapabilities.d.ts +9 -0
  102. package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +1 -0
  103. package/dist/types/api/firmwareUpdatePlan.d.ts +28 -0
  104. package/dist/types/api/firmwareUpdatePlan.d.ts.map +1 -0
  105. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +42 -0
  106. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +1 -0
  107. package/dist/types/api/index.d.ts +10 -3
  108. package/dist/types/api/index.d.ts.map +1 -1
  109. package/dist/types/api/protocolV2.d.ts +0 -3
  110. package/dist/types/api/protocolV2.d.ts.map +1 -1
  111. package/dist/types/settings.d.ts +13 -0
  112. package/dist/types/settings.d.ts.map +1 -1
  113. package/dist/utils/deviceFeaturesUtils.d.ts +0 -2
  114. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  115. package/dist/utils/homescreen.d.ts +0 -4
  116. package/dist/utils/homescreen.d.ts.map +1 -1
  117. package/dist/utils/index.d.ts +1 -1
  118. package/dist/utils/index.d.ts.map +1 -1
  119. package/dist/utils/patch.d.ts +1 -1
  120. package/dist/utils/patch.d.ts.map +1 -1
  121. package/dist/utils/pro2Wallpaper.d.ts +0 -10
  122. package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
  123. package/package.json +4 -4
  124. package/src/api/BaseMethod.ts +10 -8
  125. package/src/api/CheckAllFirmwareRelease.ts +51 -6
  126. package/src/api/FirmwareUpdateV2.ts +298 -120
  127. package/src/api/FirmwareUpdateV3.ts +263 -57
  128. package/src/api/FirmwareUpdateV4.ts +748 -281
  129. package/src/api/GetPassphraseState.ts +1 -7
  130. package/src/api/OpenWalletSession.ts +17 -54
  131. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +11 -32
  132. package/src/api/device/DeviceUnlock.ts +1 -1
  133. package/src/api/device/DeviceUpdateBootloader.ts +122 -6
  134. package/src/api/firmware/FirmwareArtifactSource.ts +278 -0
  135. package/src/api/firmware/FirmwareHostBinding.ts +100 -0
  136. package/src/api/firmware/FirmwarePreparationError.ts +12 -0
  137. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +57 -0
  138. package/src/api/firmware/FirmwareUpdateCapabilities.ts +9 -0
  139. package/src/api/firmware/FirmwareUpdatePlan.ts +745 -0
  140. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +392 -0
  141. package/src/api/firmware/progressThrottle.ts +44 -0
  142. package/src/api/firmware/updateBootloader.ts +19 -4
  143. package/src/api/firmware/uploadFirmware.ts +140 -22
  144. package/src/api/helpers/protocolV2FileWrite.ts +4 -11
  145. package/src/api/index.ts +0 -1
  146. package/src/api/protocol-v2/ProtocolInfoRequest.ts +1 -3
  147. package/src/core/deviceEventRegistration.ts +0 -4
  148. package/src/core/index.ts +75 -118
  149. package/src/data/messages/messages-protocol-v2.json +0 -10
  150. package/src/data-manager/DataManager.ts +33 -33
  151. package/src/data-manager/connectSettings.ts +11 -0
  152. package/src/device/Device.ts +21 -193
  153. package/src/events/device.ts +0 -4
  154. package/src/events/logBlockEvent.ts +0 -1
  155. package/src/events/ui-request.ts +2 -32
  156. package/src/index.ts +5 -0
  157. package/src/inject.ts +22 -3
  158. package/src/lowLevelInject.ts +5 -1
  159. package/src/protocols/protocol-v2/features.ts +2 -9
  160. package/src/protocols/protocol-v2/lockedError.ts +10 -0
  161. package/src/protocols/protocol-v2/uiInteraction.ts +5 -31
  162. package/src/protocols/protocol-v2/unlockPolicy.ts +105 -1
  163. package/src/protocols/protocol-v2/unlockRetry.ts +109 -0
  164. package/src/protocols/protocol-v2/walletSession.ts +18 -93
  165. package/src/topLevelInject.ts +5 -1
  166. package/src/types/api/checkAllFirmwareRelease.ts +4 -0
  167. package/src/types/api/deviceUpdateBootloader.ts +6 -0
  168. package/src/types/api/export.ts +18 -0
  169. package/src/types/api/firmwareUpdate.ts +76 -0
  170. package/src/types/api/firmwareUpdateCapabilities.ts +9 -0
  171. package/src/types/api/firmwareUpdatePlan.ts +38 -0
  172. package/src/types/api/firmwareUpdatePreparedPlan.ts +53 -0
  173. package/src/types/api/index.ts +14 -2
  174. package/src/types/api/protocolV2.ts +0 -13
  175. package/src/types/settings.ts +13 -0
  176. package/src/utils/deviceFeaturesUtils.ts +0 -4
  177. package/src/utils/homescreen.ts +6 -32
  178. package/src/utils/index.ts +1 -6
  179. package/src/utils/pro2Wallpaper.ts +8 -35
  180. package/__tests__/deviceUploadNft.test.ts +0 -187
  181. package/__tests__/pro2Nft.test.ts +0 -108
  182. package/__tests__/protocol-v2-ui-lifecycle.test.ts +0 -56
  183. package/__tests__/uiProgressThrottle.test.ts +0 -74
  184. package/dist/api/protocol-v2/DeviceUploadNft.d.ts +0 -30
  185. package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +0 -1
  186. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +0 -22
  187. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +0 -1
  188. package/dist/utils/pro2Nft.d.ts +0 -29
  189. package/dist/utils/pro2Nft.d.ts.map +0 -1
  190. package/dist/utils/uiProgressThrottle.d.ts +0 -3
  191. package/dist/utils/uiProgressThrottle.d.ts.map +0 -1
  192. package/src/api/protocol-v2/DeviceUploadNft.ts +0 -166
  193. package/src/protocols/protocol-v2/unlockPolicyRunner.ts +0 -117
  194. package/src/utils/pro2Nft.ts +0 -91
  195. package/src/utils/uiProgressThrottle.ts +0 -63
@@ -1,166 +0,0 @@
1
- import { createDeviceNotSupportMethodError } from '@onekeyfe/hd-shared';
2
-
3
- import { UI_REQUEST, createUiMessage } from '../../events/ui-request';
4
- import { supportsProtocolV2Message } from '../../protocols/protocol-v2/features';
5
- import {
6
- PRO2_NFT_DEFAULT_CHUNK_SIZE,
7
- PRO2_NFT_DEFAULT_PACE_MS,
8
- PRO2_NFT_DEFAULT_TIMEOUT_MS,
9
- PRO2_NFT_DIRECTORY,
10
- PRO2_NFT_MAX_CHUNK_SIZE,
11
- PRO2_NFT_MIN_CHUNK_SIZE,
12
- type Pro2NftBundle,
13
- type Pro2NftImage,
14
- buildPro2NftBundle,
15
- } from '../../utils/pro2Nft';
16
- import { BaseMethod } from '../BaseMethod';
17
- import { invalidParameter } from '../helpers/filesystemValidation';
18
- import { isProtocolV2ResponseTimeout, writeProtocolV2File } from '../helpers/protocolV2FileWrite';
19
-
20
- export type DeviceUploadNftParams = {
21
- image: Pro2NftImage;
22
- thumbnail: Pro2NftImage;
23
- title: string;
24
- subtitle: string;
25
- timestampMs?: number;
26
- chunkSize?: number;
27
- paceMs?: number;
28
- timeoutMs?: number;
29
- };
30
-
31
- export type DeviceUploadNftResponse = {
32
- basename: string;
33
- imagePath: string;
34
- thumbnailPath: string;
35
- metadataPath: string;
36
- totalSize: number;
37
- nftUpdated: true;
38
- message?: string;
39
- };
40
-
41
- const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE = 60805;
42
- const NFT_UPDATE_MESSAGE_TYPE = 61500;
43
-
44
- export default class DeviceUploadNft extends BaseMethod<DeviceUploadNftParams> {
45
- private bundle?: Pro2NftBundle;
46
-
47
- getSupportedProtocols() {
48
- return ['V2'] as const;
49
- }
50
-
51
- init() {
52
- const {
53
- image,
54
- thumbnail,
55
- title,
56
- subtitle,
57
- timestampMs = Date.now(),
58
- chunkSize = PRO2_NFT_DEFAULT_CHUNK_SIZE,
59
- paceMs = PRO2_NFT_DEFAULT_PACE_MS,
60
- timeoutMs = PRO2_NFT_DEFAULT_TIMEOUT_MS,
61
- } = this.payload;
62
- if (
63
- !Number.isInteger(chunkSize) ||
64
- chunkSize < PRO2_NFT_MIN_CHUNK_SIZE ||
65
- chunkSize > PRO2_NFT_MAX_CHUNK_SIZE
66
- ) {
67
- throw invalidParameter(
68
- `Parameter [chunkSize] must be an integer between ${PRO2_NFT_MIN_CHUNK_SIZE} and ${PRO2_NFT_MAX_CHUNK_SIZE}.`
69
- );
70
- }
71
- if (!Number.isInteger(paceMs) || paceMs < 0) {
72
- throw invalidParameter('Parameter [paceMs] must be a non-negative integer.');
73
- }
74
- if (!Number.isInteger(timeoutMs) || timeoutMs <= 0) {
75
- throw invalidParameter('Parameter [timeoutMs] must be a positive integer.');
76
- }
77
-
78
- this.bundle = buildPro2NftBundle({ image, thumbnail, title, subtitle, timestampMs });
79
- this.params = { image, thumbnail, title, subtitle, timestampMs, chunkSize, paceMs, timeoutMs };
80
- this.unlockPolicy = 'none';
81
- this.skipForceUpdateCheck = true;
82
- this.useDevicePassphraseState = false;
83
- }
84
-
85
- private async assertCapabilities() {
86
- const protocolInfo = await this.device.ensureProtocolV2RuntimeContext();
87
- const hasFileWrite = supportsProtocolV2Message(
88
- protocolInfo,
89
- FILESYSTEM_FILE_WRITE_MESSAGE_TYPE
90
- );
91
- const hasNftUpdate = supportsProtocolV2Message(protocolInfo, NFT_UPDATE_MESSAGE_TYPE);
92
- if (!hasFileWrite || !hasNftUpdate) {
93
- throw createDeviceNotSupportMethodError(this.name, this.device.getCurrentFirmwareType());
94
- }
95
- }
96
-
97
- private async updateNft(basename: string) {
98
- const params = { file_name_no_ext: basename };
99
- const options = { timeoutMs: this.params.timeoutMs };
100
- try {
101
- return await this.device.commands.typedCall('NftUpdate', 'Success', params, options);
102
- } catch (error) {
103
- if (!isProtocolV2ResponseTimeout(error)) {
104
- throw error;
105
- }
106
- this.throwIfAborted();
107
- return this.device.commands.typedCall('NftUpdate', 'Success', params, options);
108
- }
109
- }
110
-
111
- async run(): Promise<DeviceUploadNftResponse> {
112
- const { bundle } = this;
113
- if (!bundle) throw invalidParameter('NFT data has not been initialized.');
114
-
115
- await this.assertCapabilities();
116
-
117
- const files = [
118
- { path: `${PRO2_NFT_DIRECTORY}/${bundle.basename}.bin`, data: bundle.image },
119
- { path: `${PRO2_NFT_DIRECTORY}/${bundle.basename}_m.bin`, data: bundle.thumbnail },
120
- { path: `${PRO2_NFT_DIRECTORY}/${bundle.basename}.json`, data: bundle.metadata },
121
- ];
122
- const totalSize = files.reduce((sum, file) => sum + file.data.byteLength, 0);
123
- let transferredBeforeFile = 0;
124
-
125
- for (const file of files) {
126
- const transferredAtFileStart = transferredBeforeFile;
127
- await writeProtocolV2File({
128
- commands: this.device.commands,
129
- path: file.path,
130
- data: file.data,
131
- totalSize: file.data.byteLength,
132
- chunkSize: this.params.chunkSize,
133
- timeoutMs: this.params.timeoutMs,
134
- paceMs: this.params.paceMs,
135
- overwrite: true,
136
- append: false,
137
- throwIfAborted: () => this.throwIfAborted(),
138
- onProgress: progress => {
139
- if (typeof this.postMessage !== 'function') return;
140
- const transferredBytes = transferredAtFileStart + progress.transferredBytes;
141
- this.postMessage(
142
- createUiMessage(UI_REQUEST.DEVICE_PROGRESS, {
143
- ...progress,
144
- progress: Math.floor((transferredBytes / totalSize) * 100),
145
- transferredBytes,
146
- totalBytes: totalSize,
147
- })
148
- );
149
- },
150
- });
151
- transferredBeforeFile += file.data.byteLength;
152
- }
153
-
154
- this.throwIfAborted();
155
- const response = await this.updateNft(bundle.basename);
156
- return {
157
- basename: bundle.basename,
158
- imagePath: files[0].path,
159
- thumbnailPath: files[1].path,
160
- metadataPath: files[2].path,
161
- totalSize,
162
- nftUpdated: true,
163
- message: response.message?.message,
164
- };
165
- }
166
- }
@@ -1,117 +0,0 @@
1
- import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
2
-
3
- import { LoggerNames, getLogger } from '../../utils';
4
- import { isProtocolV2UiEnabled, resolveProtocolV2UiInteraction } from './uiInteraction';
5
- import { refreshProtocolV2DeviceStatus } from './walletSession';
6
-
7
- import type { BaseMethod } from '../../api/BaseMethod';
8
- import type { Device } from '../../device/Device';
9
- import type { HardwareUiInteractionMeta } from '../../events';
10
- import type { ProtocolV2UiInteractionCoordinator } from './uiInteraction';
11
-
12
- const Log = getLogger(LoggerNames.Core);
13
-
14
- export type ProtocolV2UnlockContext = {
15
- preflightCompleted: boolean;
16
- };
17
-
18
- export const createProtocolV2UnlockContext = (): ProtocolV2UnlockContext => ({
19
- preflightCompleted: false,
20
- });
21
-
22
- type RunnableMethod = Pick<
23
- BaseMethod,
24
- | 'run'
25
- | 'unlockPolicy'
26
- | 'useDevicePassphraseState'
27
- | 'protocolV2UiInteraction'
28
- | 'protocolV2UiMode'
29
- | 'params'
30
- | 'payload'
31
- > & {
32
- name?: string;
33
- protocolV2UnlockContext?: ProtocolV2UnlockContext;
34
- };
35
-
36
- type UiInteractionCoordinator = Pick<
37
- ProtocolV2UiInteractionCoordinator,
38
- 'enterMethodInteraction' | 'enterUnlockInteraction'
39
- >;
40
-
41
- type RunMethodWithUnlockPolicyOptions<T> = {
42
- context?: ProtocolV2UnlockContext;
43
- uiCoordinator?: UiInteractionCoordinator;
44
- afterStatusBeforeUnlock?: () => void | Promise<void>;
45
- prepare?: () => Promise<void>;
46
- run?: () => Promise<T>;
47
- };
48
-
49
- export async function runMethodWithUnlockPolicy<T = unknown>(
50
- method: RunnableMethod,
51
- device: Device,
52
- options: RunMethodWithUnlockPolicyOptions<T> = {}
53
- ): Promise<T> {
54
- const {
55
- context = createProtocolV2UnlockContext(),
56
- uiCoordinator,
57
- afterStatusBeforeUnlock,
58
- prepare,
59
- run: configuredRun,
60
- } = options;
61
- const run = configuredRun ?? (() => method.run() as Promise<T>);
62
- method.protocolV2UnlockContext = context;
63
-
64
- const shouldEmitUi = isProtocolV2UiEnabled(method);
65
- const shouldCoordinateUi = shouldEmitUi && uiCoordinator !== undefined;
66
- const requiresPreUnlock =
67
- device.isProtocolV2() &&
68
- (method.useDevicePassphraseState || method.unlockPolicy === 'unlock-before-run') &&
69
- !device.isBootloader?.() &&
70
- !device.isRomloader?.();
71
-
72
- if (requiresPreUnlock && !context.preflightCompleted) {
73
- const status = await refreshProtocolV2DeviceStatus(device);
74
- if (typeof status?.unlocked !== 'boolean') {
75
- throw ERRORS.TypedError(
76
- HardwareErrorCode.RuntimeError,
77
- 'Protocol V2 DeviceStatus did not report an explicit unlock state.'
78
- );
79
- }
80
-
81
- await afterStatusBeforeUnlock?.();
82
-
83
- if (!status.unlocked) {
84
- const unlockInteraction: HardwareUiInteractionMeta | undefined = shouldCoordinateUi
85
- ? uiCoordinator.enterUnlockInteraction(method.name)
86
- : undefined;
87
- const unlockedStatus = await device.unlockDevice(
88
- undefined,
89
- shouldCoordinateUi
90
- ? { emitUiEvent: false, interaction: unlockInteraction }
91
- : {
92
- source: 'unlock-coordinator',
93
- reason: 'device-locked',
94
- deviceOnly: true,
95
- method: method.name,
96
- }
97
- );
98
- if (unlockedStatus?.unlocked !== true) {
99
- throw ERRORS.TypedError(
100
- HardwareErrorCode.RuntimeError,
101
- 'Protocol V2 device remained locked after the unlock flow.'
102
- );
103
- }
104
- Log.debug('Protocol V2 pre-unlock completed', { method: method.name });
105
- }
106
-
107
- context.preflightCompleted = true;
108
- }
109
-
110
- await prepare?.();
111
-
112
- if (shouldCoordinateUi) {
113
- uiCoordinator.enterMethodInteraction(resolveProtocolV2UiInteraction(method));
114
- }
115
-
116
- return run();
117
- }
@@ -1,91 +0,0 @@
1
- import { blake2s } from '@noble/hashes/blake2s';
2
- import { bytesToHex } from '@noble/hashes/utils';
3
-
4
- import { invalidParameter } from '../api/helpers/filesystemValidation';
5
- import { encodePro2Image } from './pro2Wallpaper';
6
-
7
- export const PRO2_NFT_IMAGE_WIDTH = 540;
8
- export const PRO2_NFT_IMAGE_HEIGHT = 540;
9
- export const PRO2_NFT_THUMBNAIL_WIDTH = 263;
10
- export const PRO2_NFT_THUMBNAIL_HEIGHT = 263;
11
- export const PRO2_NFT_DIRECTORY = 'vol1:/nft';
12
- export const PRO2_NFT_DEFAULT_CHUNK_SIZE = 512;
13
- export const PRO2_NFT_DEFAULT_PACE_MS = 20;
14
- export const PRO2_NFT_DEFAULT_TIMEOUT_MS = 15_000;
15
- export const PRO2_NFT_MIN_CHUNK_SIZE = 64;
16
- export const PRO2_NFT_MAX_CHUNK_SIZE = 2048;
17
-
18
- export type Pro2NftImage = {
19
- width: number;
20
- height: number;
21
- rgba: Uint8Array | ArrayBuffer;
22
- };
23
-
24
- export type Pro2NftBundle = {
25
- basename: string;
26
- image: Uint8Array;
27
- thumbnail: Uint8Array;
28
- metadata: Uint8Array;
29
- };
30
-
31
- function utf8Length(value: string): number {
32
- return new TextEncoder().encode(value).byteLength;
33
- }
34
-
35
- function assertImage(
36
- name: string,
37
- image: Pro2NftImage,
38
- expectedWidth: number,
39
- expectedHeight: number
40
- ) {
41
- if (image.width !== expectedWidth || image.height !== expectedHeight) {
42
- throw invalidParameter(
43
- `Pro2 NFT ${name} dimensions must be ${expectedWidth}x${expectedHeight}.`
44
- );
45
- }
46
- if (!(image.rgba instanceof ArrayBuffer) && !ArrayBuffer.isView(image.rgba)) {
47
- throw invalidParameter(`Parameter [${name}.rgba] must be an ArrayBuffer or Uint8Array.`);
48
- }
49
- }
50
-
51
- export function buildPro2NftBundle(options: {
52
- image: Pro2NftImage;
53
- thumbnail: Pro2NftImage;
54
- title: string;
55
- subtitle: string;
56
- timestampMs: number;
57
- }): Pro2NftBundle {
58
- const { image, thumbnail, title, subtitle, timestampMs } = options;
59
- assertImage('image', image, PRO2_NFT_IMAGE_WIDTH, PRO2_NFT_IMAGE_HEIGHT);
60
- assertImage('thumbnail', thumbnail, PRO2_NFT_THUMBNAIL_WIDTH, PRO2_NFT_THUMBNAIL_HEIGHT);
61
- const titleLength = typeof title === 'string' ? utf8Length(title) : 0;
62
- const subtitleLength =
63
- typeof subtitle === 'string' ? utf8Length(subtitle) : Number.POSITIVE_INFINITY;
64
- if (titleLength < 1 || titleLength > 63) {
65
- throw invalidParameter('Pro2 NFT title must contain 1 to 63 UTF-8 bytes.');
66
- }
67
- if (subtitleLength > 95) {
68
- throw invalidParameter('Pro2 NFT subtitle must contain at most 95 UTF-8 bytes.');
69
- }
70
- if (!Number.isSafeInteger(timestampMs) || timestampMs <= 0) {
71
- throw invalidParameter('Parameter [timestampMs] must be a positive safe integer.');
72
- }
73
-
74
- const encodedImage = encodePro2Image({ ...image, alphaMode: 'black-background' }).data;
75
- const encodedThumbnail = encodePro2Image({
76
- ...thumbnail,
77
- alphaMode: 'black-background',
78
- }).data;
79
- const metadata = new TextEncoder().encode(JSON.stringify({ title, subtitle }));
80
- if (metadata.byteLength === 0 || metadata.byteLength > 512) {
81
- throw invalidParameter('Pro2 NFT metadata must contain 1 to 512 UTF-8 bytes.');
82
- }
83
-
84
- const hash8 = bytesToHex(blake2s(encodedImage)).slice(0, 8);
85
- return {
86
- basename: `nft-${hash8}-${timestampMs}`,
87
- image: encodedImage,
88
- thumbnail: encodedThumbnail,
89
- metadata,
90
- };
91
- }
@@ -1,63 +0,0 @@
1
- import { UI_EVENT, UI_REQUEST } from '../events/ui-request';
2
-
3
- import type { CoreMessage } from '../events';
4
-
5
- const DEFAULT_UI_PROGRESS_INTERVAL_MS = 250;
6
-
7
- type UiProgressThrottleState = {
8
- lastEmittedAt: number;
9
- lastProgress?: number;
10
- };
11
-
12
- const normalizeProgress = (progress: unknown) => {
13
- if (typeof progress !== 'number' || !Number.isFinite(progress)) {
14
- return undefined;
15
- }
16
-
17
- return Math.max(0, Math.min(100, Math.floor(progress)));
18
- };
19
-
20
- export const createUiProgressMessageFilter = (
21
- intervalMs = DEFAULT_UI_PROGRESS_INTERVAL_MS,
22
- now = Date.now
23
- ) => {
24
- const stateByType = new Map<string, UiProgressThrottleState>();
25
-
26
- return (message: CoreMessage) => {
27
- if (
28
- !('event' in message) ||
29
- message.event !== UI_EVENT ||
30
- (message.type !== UI_REQUEST.DEVICE_PROGRESS && message.type !== UI_REQUEST.FIRMWARE_PROGRESS)
31
- ) {
32
- return true;
33
- }
34
-
35
- const key =
36
- message.type === UI_REQUEST.FIRMWARE_PROGRESS
37
- ? `${message.type}:${message.payload.progressType}`
38
- : message.type;
39
- const progress = normalizeProgress(message.payload.progress);
40
- const currentTime = now();
41
- const state = stateByType.get(key);
42
-
43
- if (!state) {
44
- stateByType.set(key, { lastEmittedAt: currentTime, lastProgress: progress });
45
- return true;
46
- }
47
-
48
- const isBoundary = progress === 0 || progress === 100;
49
- if (isBoundary && progress === state.lastProgress) {
50
- return false;
51
- }
52
-
53
- const startsNewPhase =
54
- progress !== undefined && state.lastProgress !== undefined && progress < state.lastProgress;
55
-
56
- if (!isBoundary && !startsNewPhase && currentTime - state.lastEmittedAt < intervalMs) {
57
- return false;
58
- }
59
-
60
- stateByType.set(key, { lastEmittedAt: currentTime, lastProgress: progress });
61
- return true;
62
- };
63
- };