@onekeyfe/hd-core 1.2.0-alpha.54 → 1.2.0-alpha.56
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 +231 -0
- package/__tests__/DeviceCommands.test.ts +45 -0
- package/__tests__/DeviceEventRegistration.test.ts +6 -0
- package/__tests__/check-all-firmware-release-protocol-v2.test.ts +198 -3
- package/__tests__/connectSettings.test.ts +5 -47
- package/__tests__/device-lifecycle-events.test.ts +105 -3
- package/__tests__/device-state-contract.test.ts +1 -0
- package/__tests__/device-state-mapper.test.ts +1 -1
- package/__tests__/deviceSettings.test.ts +1 -1
- package/__tests__/deviceUploadNft.test.ts +293 -0
- package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +31 -59
- package/__tests__/get-device-state.test.ts +132 -12
- package/__tests__/homescreen.test.ts +41 -1
- package/__tests__/kaspaSignTransaction.test.ts +3 -26
- package/__tests__/logBlockEvent.test.ts +1 -1
- package/__tests__/method-protocol-support.test.ts +19 -0
- package/__tests__/open-wallet-session.test.ts +568 -37
- package/__tests__/pro2Nft.test.ts +108 -0
- package/__tests__/protocol-binding.test.ts +89 -0
- package/__tests__/protocol-v2-resources.test.ts +286 -0
- package/__tests__/protocol-v2-ui-lifecycle.test.ts +91 -0
- package/__tests__/protocol-v2-unlock-policy.test.ts +201 -35
- package/__tests__/protocol-v2.test.ts +1353 -1011
- package/__tests__/protocolV2FileWrite.test.ts +39 -0
- package/__tests__/protocolV2UiInteraction.test.ts +63 -0
- package/__tests__/public-pro2-api-boundary.test.ts +1 -0
- package/__tests__/search-devices.test.ts +12 -3
- package/__tests__/uiProgressThrottle.test.ts +74 -0
- package/__tests__/uiPromiseRegistry.test.ts +86 -0
- package/dist/api/BaseMethod.d.ts +3 -1
- package/dist/api/BaseMethod.d.ts.map +1 -1
- package/dist/api/CheckAllFirmwareRelease.d.ts +2 -1
- package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
- package/dist/api/DetectDeviceConnectProtocol.d.ts +7 -0
- package/dist/api/DetectDeviceConnectProtocol.d.ts.map +1 -0
- package/dist/api/FirmwareUpdate.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV2.d.ts +0 -11
- package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV3.d.ts +3 -7
- package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +11 -25
- 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/SearchDevices.d.ts.map +1 -1
- package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
- package/dist/api/device/DeviceUnlock.d.ts +2 -2
- package/dist/api/device/DeviceUnlock.d.ts.map +1 -1
- package/dist/api/device/DeviceUpdateBootloader.d.ts +1 -5
- package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +0 -9
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
- package/dist/api/firmware/getBinary.d.ts +0 -7
- package/dist/api/firmware/getBinary.d.ts.map +1 -1
- package/dist/api/firmware/updateBootloader.d.ts +0 -2
- package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
- package/dist/api/firmware/uploadFirmware.d.ts +1 -9
- package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
- package/dist/api/helpers/protocolV2FileWrite.d.ts +2 -0
- package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
- package/dist/api/index.d.ts +2 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/kaspa/KaspaSignTransaction.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts +31 -0
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -0
- package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -1
- package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
- package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
- package/dist/core/deviceEventRegistration.d.ts +2 -0
- package/dist/core/deviceEventRegistration.d.ts.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/uiPromiseRegistry.d.ts +4 -0
- package/dist/core/uiPromiseRegistry.d.ts.map +1 -0
- package/dist/data-manager/DataManager.d.ts +4 -2
- 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 +29 -6
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts +4 -4
- package/dist/device/DeviceCommands.d.ts.map +1 -1
- package/dist/device/DevicePool.d.ts.map +1 -1
- package/dist/events/device.d.ts +4 -0
- package/dist/events/device.d.ts.map +1 -1
- package/dist/events/logBlockEvent.d.ts.map +1 -1
- package/dist/events/ui-promise.d.ts +4 -2
- package/dist/events/ui-promise.d.ts.map +1 -1
- package/dist/events/ui-request.d.ts +31 -2
- package/dist/events/ui-request.d.ts.map +1 -1
- package/dist/events/ui-response.d.ts +10 -2
- package/dist/events/ui-response.d.ts.map +1 -1
- package/dist/index.d.ts +214 -231
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2634 -3530
- package/dist/inject.d.ts +6 -1
- package/dist/inject.d.ts.map +1 -1
- package/dist/lowLevelInject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/features.d.ts +0 -4
- package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/firmware.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/resources.d.ts +30 -0
- package/dist/protocols/protocol-v2/resources.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/uiInteraction.d.ts +7 -4
- package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockPolicy.d.ts +1 -3
- package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +22 -0
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/walletSession.d.ts +6 -1
- 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 +2 -4
- package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/detectDeviceConnectProtocol.d.ts +4 -0
- package/dist/types/api/detectDeviceConnectProtocol.d.ts.map +1 -0
- package/dist/types/api/deviceUnlock.d.ts +5 -1
- package/dist/types/api/deviceUnlock.d.ts.map +1 -1
- package/dist/types/api/deviceUpdateBootloader.d.ts +0 -6
- package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
- package/dist/types/api/export.d.ts +2 -4
- package/dist/types/api/export.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdate.d.ts +2 -70
- package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
- package/dist/types/api/index.d.ts +7 -10
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/protocolV2.d.ts +3 -0
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/device.d.ts.map +1 -1
- package/dist/types/params.d.ts +1 -0
- package/dist/types/params.d.ts.map +1 -1
- package/dist/types/settings.d.ts +22 -13
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesCompat.d.ts +0 -1
- package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesUtils.d.ts +4 -0
- package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
- package/dist/utils/homescreen.d.ts +4 -0
- 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/pro2Nft.d.ts +31 -0
- package/dist/utils/pro2Nft.d.ts.map +1 -0
- package/dist/utils/pro2Wallpaper.d.ts +10 -0
- package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
- package/dist/utils/uiProgressThrottle.d.ts +3 -0
- package/dist/utils/uiProgressThrottle.d.ts.map +1 -0
- package/package.json +4 -4
- package/src/api/BaseMethod.ts +8 -10
- package/src/api/CheckAllFirmwareRelease.ts +54 -57
- package/src/api/DetectDeviceConnectProtocol.ts +18 -0
- package/src/api/FirmwareUpdate.ts +7 -15
- package/src/api/FirmwareUpdateV2.ts +126 -316
- package/src/api/FirmwareUpdateV3.ts +63 -265
- package/src/api/FirmwareUpdateV4.ts +584 -975
- package/src/api/GetPassphraseState.ts +7 -1
- package/src/api/OpenWalletSession.ts +70 -17
- package/src/api/SearchDevices.ts +3 -1
- package/src/api/allnetwork/AllNetworkGetAddress.ts +21 -21
- package/src/api/allnetwork/AllNetworkGetAddressBase.ts +34 -11
- package/src/api/device/DeviceUnlock.ts +8 -3
- package/src/api/device/DeviceUpdateBootloader.ts +6 -122
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +16 -83
- package/src/api/firmware/updateBootloader.ts +4 -19
- package/src/api/firmware/uploadFirmware.ts +39 -144
- package/src/api/helpers/protocolV2FileWrite.ts +27 -7
- package/src/api/index.ts +2 -0
- package/src/api/kaspa/KaspaSignTransaction.ts +1 -12
- package/src/api/protocol-v2/DeviceUploadNft.ts +189 -0
- package/src/api/protocol-v2/ProtocolInfoRequest.ts +3 -1
- package/src/api/protocol-v2/helpers.ts +1 -0
- package/src/core/deviceEventRegistration.ts +4 -0
- package/src/core/index.ts +167 -83
- package/src/core/uiPromiseRegistry.ts +41 -0
- package/src/data/messages/messages-protocol-v2.json +25 -0
- package/src/data-manager/DataManager.ts +71 -39
- package/src/data-manager/connectSettings.ts +0 -11
- package/src/device/Device.ts +259 -43
- package/src/device/DeviceCommands.ts +7 -1
- package/src/device/DevicePool.ts +7 -2
- package/src/events/device.ts +4 -0
- package/src/events/logBlockEvent.ts +1 -0
- package/src/events/ui-promise.ts +4 -2
- package/src/events/ui-request.ts +36 -2
- package/src/events/ui-response.ts +12 -2
- package/src/index.ts +0 -5
- package/src/inject.ts +60 -24
- package/src/lowLevelInject.ts +7 -8
- package/src/protocols/protocol-v2/features.ts +10 -7
- package/src/protocols/protocol-v2/firmware.ts +2 -0
- package/src/protocols/protocol-v2/resources.ts +359 -0
- package/src/protocols/protocol-v2/uiInteraction.ts +46 -6
- package/src/protocols/protocol-v2/unlockPolicy.ts +1 -105
- package/src/protocols/protocol-v2/unlockPolicyRunner.ts +118 -0
- package/src/protocols/protocol-v2/walletSession.ts +214 -36
- package/src/topLevelInject.ts +7 -8
- package/src/types/api/checkAllFirmwareRelease.ts +2 -4
- package/src/types/api/detectDeviceConnectProtocol.ts +6 -0
- package/src/types/api/deviceUnlock.ts +12 -1
- package/src/types/api/deviceUpdateBootloader.ts +0 -6
- package/src/types/api/export.ts +1 -18
- package/src/types/api/firmwareUpdate.ts +3 -76
- package/src/types/api/index.ts +13 -14
- package/src/types/api/protocolV2.ts +13 -0
- package/src/types/device.ts +3 -0
- package/src/types/params.ts +7 -1
- package/src/types/settings.ts +42 -13
- package/src/utils/deviceFeaturesCompat.ts +0 -6
- package/src/utils/deviceFeaturesUtils.ts +8 -0
- package/src/utils/homescreen.ts +32 -6
- package/src/utils/index.ts +6 -1
- package/src/utils/pro2Nft.ts +142 -0
- package/src/utils/pro2Wallpaper.ts +35 -8
- package/src/utils/uiProgressThrottle.ts +63 -0
- package/__tests__/device-initialize-timeout.test.ts +0 -56
- package/__tests__/firmware-update/check-all-firmware-release.test.ts +0 -175
- package/__tests__/firmware-update/firmware-artifact-source.test.ts +0 -119
- package/__tests__/firmware-update/firmware-host-binding.test.ts +0 -70
- package/__tests__/firmware-update/firmware-preparation-error.test.ts +0 -27
- package/__tests__/firmware-update/firmware-update-bootloader-poll.test.ts +0 -200
- package/__tests__/firmware-update/firmware-update-capabilities.test.ts +0 -13
- package/__tests__/firmware-update/firmware-update-plan-bootloader-identity.test.ts +0 -294
- package/__tests__/firmware-update/firmware-update-plan.test.ts +0 -593
- package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +0 -213
- package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +0 -58
- package/__tests__/firmware-update/firmware-upload-source.test.ts +0 -70
- package/dist/api/firmware/FirmwareArtifactSource.d.ts +0 -25
- package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +0 -1
- package/dist/api/firmware/FirmwareHostBinding.d.ts +0 -6
- package/dist/api/firmware/FirmwareHostBinding.d.ts.map +0 -1
- package/dist/api/firmware/FirmwarePreparationError.d.ts +0 -3
- package/dist/api/firmware/FirmwarePreparationError.d.ts.map +0 -1
- package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +0 -3
- package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +0 -1
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts +0 -25
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +0 -1
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +0 -32
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +0 -1
- package/dist/api/firmware/progressThrottle.d.ts +0 -3
- package/dist/api/firmware/progressThrottle.d.ts.map +0 -1
- package/dist/protocols/protocol-v2/lockedError.d.ts +0 -2
- package/dist/protocols/protocol-v2/lockedError.d.ts.map +0 -1
- package/dist/protocols/protocol-v2/unlockRetry.d.ts +0 -10
- package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +0 -1
- package/dist/types/api/firmwareUpdateCapabilities.d.ts +0 -9
- package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +0 -1
- package/dist/types/api/firmwareUpdatePlan.d.ts +0 -28
- package/dist/types/api/firmwareUpdatePlan.d.ts.map +0 -1
- package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +0 -42
- package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +0 -1
- package/src/api/firmware/FirmwareArtifactSource.ts +0 -278
- package/src/api/firmware/FirmwareHostBinding.ts +0 -100
- package/src/api/firmware/FirmwarePreparationError.ts +0 -12
- package/src/api/firmware/FirmwareUpdateCapabilities.ts +0 -9
- package/src/api/firmware/FirmwareUpdatePlan.ts +0 -772
- package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +0 -415
- package/src/api/firmware/progressThrottle.ts +0 -44
- package/src/protocols/protocol-v2/lockedError.ts +0 -10
- package/src/protocols/protocol-v2/unlockRetry.ts +0 -109
- package/src/types/api/firmwareUpdateCapabilities.ts +0 -9
- package/src/types/api/firmwareUpdatePlan.ts +0 -38
- package/src/types/api/firmwareUpdatePreparedPlan.ts +0 -53
package/src/types/api/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
deviceGetOnboardingStatus,
|
|
3
3
|
deviceReboot,
|
|
4
|
+
deviceUploadNft,
|
|
4
5
|
deviceUploadWallpaper,
|
|
5
6
|
testProtocolV2Ping,
|
|
6
7
|
uploadPortfolio,
|
|
@@ -18,6 +19,7 @@ import type { checkBootloaderRelease } from './checkBootloaderRelease';
|
|
|
18
19
|
import type { checkAllFirmwareRelease } from './checkAllFirmwareRelease';
|
|
19
20
|
import type { checkFirmwareTypeAvailable } from './checkFirmwareTypeAvailable';
|
|
20
21
|
import type { searchDevices } from './searchDevices';
|
|
22
|
+
import type { detectDeviceConnectProtocol } from './detectDeviceConnectProtocol';
|
|
21
23
|
import type { getFeatures } from './getFeatures';
|
|
22
24
|
import type { getDeviceState } from './getDeviceState';
|
|
23
25
|
import type { getOnekeyFeatures } from './getOnekeyFeatures';
|
|
@@ -30,15 +32,7 @@ import type {
|
|
|
30
32
|
firmwareUpdateV2,
|
|
31
33
|
firmwareUpdateV3,
|
|
32
34
|
firmwareUpdateV4,
|
|
33
|
-
getFirmwareUpdateHostBindingGeneration,
|
|
34
|
-
registerFirmwareUpdateHostBinding,
|
|
35
|
-
unregisterFirmwareUpdateHostBinding,
|
|
36
35
|
} from './firmwareUpdate';
|
|
37
|
-
import type { getFirmwareUpdateCapabilities } from './firmwareUpdateCapabilities';
|
|
38
|
-
import type {
|
|
39
|
-
prepareFirmwareUpdatePlan,
|
|
40
|
-
validateFirmwareUpdatePreparedPlan,
|
|
41
|
-
} from './firmwareUpdatePreparedPlan';
|
|
42
36
|
import type { promptWebDeviceAccess } from './promptWebDeviceAccess';
|
|
43
37
|
import type { deviceReset } from './deviceReset';
|
|
44
38
|
import type { deviceRecovery } from './deviceRecovery';
|
|
@@ -152,6 +146,7 @@ import type { benfenSignMessage } from './benfenSignMessage';
|
|
|
152
146
|
import type { neoGetAddress } from './neoGetAddress';
|
|
153
147
|
import type { neoSignTransaction } from './neoSignTransaction';
|
|
154
148
|
import type { ConnectSettings } from '../settings';
|
|
149
|
+
import type { HardwareConnectProtocol } from '@onekeyfe/hd-shared';
|
|
155
150
|
|
|
156
151
|
export * from './export';
|
|
157
152
|
export type { DeviceStateScope, GetDeviceStateParams } from './getDeviceState';
|
|
@@ -176,6 +171,14 @@ export type CoreApi = {
|
|
|
176
171
|
removeAllListeners: typeof removeAllListeners;
|
|
177
172
|
dispose: () => void | Promise<void>;
|
|
178
173
|
call: (params: any) => Promise<any>;
|
|
174
|
+
/**
|
|
175
|
+
* Bind a protocol that has already been verified for one transport endpoint.
|
|
176
|
+
* Every later SDK call for the same connectId uses it as a strict expectation.
|
|
177
|
+
*/
|
|
178
|
+
setDeviceConnectProtocol: (
|
|
179
|
+
connectId: string,
|
|
180
|
+
connectProtocol: HardwareConnectProtocol | undefined
|
|
181
|
+
) => void;
|
|
179
182
|
uiResponse: typeof uiResponse;
|
|
180
183
|
cancel: (connectId?: string) => void;
|
|
181
184
|
updateSettings: typeof updateSettings;
|
|
@@ -203,6 +206,7 @@ export type CoreApi = {
|
|
|
203
206
|
* Device function
|
|
204
207
|
*/
|
|
205
208
|
searchDevices: typeof searchDevices;
|
|
209
|
+
detectDeviceConnectProtocol: typeof detectDeviceConnectProtocol;
|
|
206
210
|
promptWebDeviceAccess: typeof promptWebDeviceAccess;
|
|
207
211
|
getFeatures: typeof getFeatures;
|
|
208
212
|
getDeviceState: typeof getDeviceState;
|
|
@@ -235,12 +239,6 @@ export type CoreApi = {
|
|
|
235
239
|
firmwareUpdateV2: typeof firmwareUpdateV2;
|
|
236
240
|
firmwareUpdateV3: typeof firmwareUpdateV3;
|
|
237
241
|
firmwareUpdateV4: typeof firmwareUpdateV4;
|
|
238
|
-
registerFirmwareUpdateHostBinding: typeof registerFirmwareUpdateHostBinding;
|
|
239
|
-
unregisterFirmwareUpdateHostBinding: typeof unregisterFirmwareUpdateHostBinding;
|
|
240
|
-
getFirmwareUpdateHostBindingGeneration: typeof getFirmwareUpdateHostBindingGeneration;
|
|
241
|
-
getFirmwareUpdateCapabilities: typeof getFirmwareUpdateCapabilities;
|
|
242
|
-
prepareFirmwareUpdatePlan: typeof prepareFirmwareUpdatePlan;
|
|
243
|
-
validateFirmwareUpdatePreparedPlan: typeof validateFirmwareUpdatePreparedPlan;
|
|
244
242
|
cipherKeyValue: typeof cipherKeyValue;
|
|
245
243
|
|
|
246
244
|
/**
|
|
@@ -248,6 +246,7 @@ export type CoreApi = {
|
|
|
248
246
|
*/
|
|
249
247
|
deviceReboot: typeof deviceReboot;
|
|
250
248
|
deviceGetOnboardingStatus: typeof deviceGetOnboardingStatus;
|
|
249
|
+
deviceUploadNft: typeof deviceUploadNft;
|
|
251
250
|
deviceUploadWallpaper: typeof deviceUploadWallpaper;
|
|
252
251
|
uploadPortfolio: typeof uploadPortfolio;
|
|
253
252
|
|
|
@@ -5,6 +5,10 @@ import type {
|
|
|
5
5
|
DeviceUploadWallpaperParams,
|
|
6
6
|
DeviceUploadWallpaperResponse,
|
|
7
7
|
} from '../../api/protocol-v2/DeviceUploadWallpaper';
|
|
8
|
+
import type {
|
|
9
|
+
DeviceUploadNftParams,
|
|
10
|
+
DeviceUploadNftResponse,
|
|
11
|
+
} from '../../api/protocol-v2/DeviceUploadNft';
|
|
8
12
|
|
|
9
13
|
// Re-export implementation parameter types as the single source of truth.
|
|
10
14
|
export type { DeviceRebootParams, RebootTypeInput } from '../../api/protocol-v2/helpers';
|
|
@@ -12,6 +16,10 @@ export type {
|
|
|
12
16
|
DeviceUploadWallpaperParams,
|
|
13
17
|
DeviceUploadWallpaperResponse,
|
|
14
18
|
} from '../../api/protocol-v2/DeviceUploadWallpaper';
|
|
19
|
+
export type {
|
|
20
|
+
DeviceUploadNftParams,
|
|
21
|
+
DeviceUploadNftResponse,
|
|
22
|
+
} from '../../api/protocol-v2/DeviceUploadNft';
|
|
15
23
|
|
|
16
24
|
// ── Shared response shapes (Protocol V2 file system) ────────────────────
|
|
17
25
|
|
|
@@ -52,6 +60,11 @@ export declare function deviceUploadWallpaper(
|
|
|
52
60
|
params: CommonParams & DeviceUploadWallpaperParams
|
|
53
61
|
): Response<DeviceUploadWallpaperResponse>;
|
|
54
62
|
|
|
63
|
+
export declare function deviceUploadNft(
|
|
64
|
+
connectId: string,
|
|
65
|
+
params: CommonParams & DeviceUploadNftParams
|
|
66
|
+
): Response<DeviceUploadNftResponse>;
|
|
67
|
+
|
|
55
68
|
export declare function uploadPortfolio(
|
|
56
69
|
connectId: string,
|
|
57
70
|
params: {
|
package/src/types/device.ts
CHANGED
|
@@ -210,7 +210,9 @@ export type DeviceStateStatus = {
|
|
|
210
210
|
recoveryMode: boolean | null;
|
|
211
211
|
passphraseProtection: boolean | null;
|
|
212
212
|
pinProtection: boolean | null;
|
|
213
|
+
/** `attach_to_pin_enabled`:是否至少存在一个 Attach PIN 绑定。 */
|
|
213
214
|
attachToPinEnabled: boolean | null;
|
|
215
|
+
/** `unlocked_by_attach_to_pin`:本次解锁是否由 Attach PIN 完成。 */
|
|
214
216
|
unlockedAttachPin: boolean | null;
|
|
215
217
|
};
|
|
216
218
|
|
|
@@ -321,6 +323,7 @@ export type NormalizedFeatures = {
|
|
|
321
323
|
sdProtection: boolean | null;
|
|
322
324
|
wipeCodeProtection: boolean | null;
|
|
323
325
|
passphraseAlwaysOnDevice: boolean | null;
|
|
326
|
+
/** `attach_to_pin_enabled`:是否至少存在一个 Attach PIN 绑定。 */
|
|
324
327
|
attachToPinEnabled?: boolean | null;
|
|
325
328
|
safetyChecks: Enum_SafetyCheckLevel | null;
|
|
326
329
|
autoLockDelayMs: number | null;
|
package/src/types/params.ts
CHANGED
|
@@ -61,9 +61,15 @@ export interface CommonParams {
|
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
63
|
* Strictly expected transport protocol. The SDK actively verifies this value and
|
|
64
|
-
* rejects a mismatch.
|
|
64
|
+
* rejects a mismatch. After a successful probe, the cached protocol is also strict.
|
|
65
65
|
*/
|
|
66
66
|
connectProtocol?: HardwareConnectProtocol;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Ignore a previously bound protocol for this call and actively detect the
|
|
70
|
+
* protocol again. Intended for the first verified connection or explicit recovery.
|
|
71
|
+
*/
|
|
72
|
+
forceProtocolDetection?: boolean;
|
|
67
73
|
}
|
|
68
74
|
|
|
69
75
|
export type Params<T> = CommonParams & T & { bundle?: undefined };
|
package/src/types/settings.ts
CHANGED
|
@@ -31,8 +31,6 @@ export type ConnectSettings = {
|
|
|
31
31
|
timestamp: number;
|
|
32
32
|
isFrame?: boolean;
|
|
33
33
|
preRelease?: boolean;
|
|
34
|
-
firmwareManifestMode?: 'sdk-managed' | 'external-only';
|
|
35
|
-
preloadedConfig?: RemoteConfigResponse;
|
|
36
34
|
fetchConfig?: boolean;
|
|
37
35
|
extension?: string;
|
|
38
36
|
configFetcher?: (url: string) => Promise<RemoteConfigResponse | null>;
|
|
@@ -60,18 +58,55 @@ export type IProtocolV2FirmwareComponent = {
|
|
|
60
58
|
fingerprint?: string;
|
|
61
59
|
/** OKPP payload hash, used to detect same-version package changes. */
|
|
62
60
|
payloadHash?: string;
|
|
63
|
-
expectedSize?: number;
|
|
64
61
|
version?: IVersionArray;
|
|
65
62
|
};
|
|
66
63
|
|
|
64
|
+
export type IProtocolV2ResourceType =
|
|
65
|
+
| 'images'
|
|
66
|
+
| 'animation'
|
|
67
|
+
| 'wallpaper'
|
|
68
|
+
| 'translations'
|
|
69
|
+
| 'roobert'
|
|
70
|
+
| 'noto';
|
|
71
|
+
|
|
72
|
+
/** Pro2 RES package descriptor. Hashes identify content without a human-managed version. */
|
|
73
|
+
export type IProtocolV2Resource = {
|
|
74
|
+
type: IProtocolV2ResourceType;
|
|
75
|
+
url: string;
|
|
76
|
+
/** Complete okpkg file size in bytes. */
|
|
77
|
+
size: number;
|
|
78
|
+
/** SHA-256 of the complete okpkg file. */
|
|
79
|
+
fileHash: string;
|
|
80
|
+
/** SHA3-512 header_hash from the signed okpkg header. */
|
|
81
|
+
headerHash: string;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/** Optional Pro2 startup-resource CRATE installed by the bootloader updater. */
|
|
85
|
+
export type IProtocolV2BootResources = {
|
|
86
|
+
required: false;
|
|
87
|
+
target: 'CRATE';
|
|
88
|
+
url: string;
|
|
89
|
+
/** Complete CRATE file size in bytes. */
|
|
90
|
+
size: number;
|
|
91
|
+
/** SHA-256 of the complete CRATE file. */
|
|
92
|
+
fileHash: string;
|
|
93
|
+
/** SHA3-512 payload_hash from the signed CRATE header. */
|
|
94
|
+
payloadHash: string;
|
|
95
|
+
/** SHA3-512 header_hash from the signed CRATE header. */
|
|
96
|
+
headerHash: string;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export type IProtocolV2Resources = {
|
|
100
|
+
stable: IProtocolV2Resource[];
|
|
101
|
+
boot?: IProtocolV2BootResources;
|
|
102
|
+
};
|
|
103
|
+
|
|
67
104
|
/** Pro2 RESC bundle okpkg descriptor for incremental FileWrite synchronization. */
|
|
68
105
|
export type IProtocolV2ResourceBundle = {
|
|
69
106
|
/** Bundle name, such as images, animation, translations, or fonts_roobert. */
|
|
70
107
|
name: string;
|
|
71
108
|
/** Download URL. */
|
|
72
109
|
url: string;
|
|
73
|
-
fingerprint?: string;
|
|
74
|
-
expectedSize?: number;
|
|
75
110
|
/** Device target path, such as vol0:/bundles/images/images.okpkg. */
|
|
76
111
|
devicePath: string;
|
|
77
112
|
/** okpkg payload_version used to skip matching content after FileRead. */
|
|
@@ -93,16 +128,10 @@ export type IFirmwareReleaseInfo = {
|
|
|
93
128
|
firmwareType?: EFirmwareType;
|
|
94
129
|
/** Firmware UI resource */
|
|
95
130
|
resource?: string;
|
|
96
|
-
resourceFingerprint?: string;
|
|
97
|
-
resourceExpectedSize?: number;
|
|
98
131
|
/** Firmware full UI resource */
|
|
99
132
|
fullResource?: string;
|
|
100
|
-
fullResourceFingerprint?: string;
|
|
101
|
-
fullResourceExpectedSize?: number;
|
|
102
133
|
fullResourceRange?: string[];
|
|
103
134
|
bootloaderResource?: string;
|
|
104
|
-
bootloaderFingerprint?: string;
|
|
105
|
-
bootloaderExpectedSize?: number;
|
|
106
135
|
bootloaderVersion?: IVersionArray;
|
|
107
136
|
displayBootloaderVersion?: IVersionArray;
|
|
108
137
|
bootloaderRelatedFirmwareVersion?: IVersionArray;
|
|
@@ -115,7 +144,6 @@ export type IFirmwareReleaseInfo = {
|
|
|
115
144
|
[k in ILocale]: string;
|
|
116
145
|
};
|
|
117
146
|
fingerprint: string;
|
|
118
|
-
expectedSize?: number;
|
|
119
147
|
version: IVersionArray;
|
|
120
148
|
changelog: {
|
|
121
149
|
[k in ILocale]: string;
|
|
@@ -131,7 +159,6 @@ export type IBLEFirmwareReleaseInfo = {
|
|
|
131
159
|
webUpdate: string;
|
|
132
160
|
fingerprint: string;
|
|
133
161
|
fingerprintWeb: string;
|
|
134
|
-
expectedSize?: number;
|
|
135
162
|
version: IVersionArray;
|
|
136
163
|
changelog: {
|
|
137
164
|
[k in ILocale]: string;
|
|
@@ -149,6 +176,8 @@ export type DeviceTypeMap = {
|
|
|
149
176
|
'firmware-v8'?: IFirmwareReleaseInfo[];
|
|
150
177
|
'firmware-btc-v8'?: IFirmwareReleaseInfo[];
|
|
151
178
|
ble: IBLEFirmwareReleaseInfo[];
|
|
179
|
+
/** Independent Pro2 resource release configuration. */
|
|
180
|
+
resources?: IProtocolV2Resources;
|
|
152
181
|
};
|
|
153
182
|
};
|
|
154
183
|
|
|
@@ -37,12 +37,6 @@ export const resolveDeviceSerialNo = (features?: DeviceFeaturesInput): string =>
|
|
|
37
37
|
);
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
-
export const resolveDeviceBootloaderMode = (features?: DeviceFeaturesInput): boolean => {
|
|
41
|
-
if (!features) return false;
|
|
42
|
-
const compatible = asCompatibleFeatures(features);
|
|
43
|
-
return (compatible.bootloaderMode ?? compatible.bootloader_mode) === true;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
40
|
export const resolveDeviceType = (features?: DeviceFeaturesInput): IDeviceType => {
|
|
47
41
|
if (!features || typeof features !== 'object') {
|
|
48
42
|
return EDeviceType.Unknown;
|
|
@@ -106,6 +106,8 @@ export const getPassphraseStateWithRefreshDeviceInfo = async (
|
|
|
106
106
|
expectPassphraseState?: string;
|
|
107
107
|
onlyMainPin?: boolean;
|
|
108
108
|
initSession?: boolean;
|
|
109
|
+
deriveCardano?: boolean;
|
|
110
|
+
rejectAttachPinForMainWallet?: boolean;
|
|
109
111
|
}
|
|
110
112
|
) => {
|
|
111
113
|
if (device.isProtocolV2()) {
|
|
@@ -121,6 +123,8 @@ export const getPassphraseStateWithRefreshDeviceInfo = async (
|
|
|
121
123
|
initSession: options?.initSession,
|
|
122
124
|
expectedPassphraseState: options?.expectPassphraseState,
|
|
123
125
|
onlyMainPin: options?.onlyMainPin,
|
|
126
|
+
deriveCardano: options?.deriveCardano,
|
|
127
|
+
rejectAttachPinForMainWallet: options?.rejectAttachPinForMainWallet,
|
|
124
128
|
});
|
|
125
129
|
}
|
|
126
130
|
|
|
@@ -185,6 +189,8 @@ export const getPassphraseState = async (
|
|
|
185
189
|
expectPassphraseState?: string;
|
|
186
190
|
onlyMainPin?: boolean;
|
|
187
191
|
initSession?: boolean;
|
|
192
|
+
deriveCardano?: boolean;
|
|
193
|
+
rejectAttachPinForMainWallet?: boolean;
|
|
188
194
|
}
|
|
189
195
|
): Promise<{
|
|
190
196
|
passphraseState: string | undefined;
|
|
@@ -205,6 +211,8 @@ export const getPassphraseState = async (
|
|
|
205
211
|
initSession: options?.initSession,
|
|
206
212
|
expectedPassphraseState: options?.expectPassphraseState,
|
|
207
213
|
onlyMainPin: options?.onlyMainPin,
|
|
214
|
+
deriveCardano: options?.deriveCardano,
|
|
215
|
+
rejectAttachPinForMainWallet: options?.rejectAttachPinForMainWallet,
|
|
208
216
|
});
|
|
209
217
|
}
|
|
210
218
|
|
package/src/utils/homescreen.ts
CHANGED
|
@@ -4,6 +4,12 @@ import { EDeviceType } from '@onekeyfe/hd-shared';
|
|
|
4
4
|
import { getDeviceType } from './deviceInfoUtils';
|
|
5
5
|
import { getDeviceFirmwareVersion } from './deviceVersionUtils';
|
|
6
6
|
import { PRO2_WALLPAPER_HEIGHT, PRO2_WALLPAPER_WIDTH } from './pro2Wallpaper';
|
|
7
|
+
import {
|
|
8
|
+
PRO2_NFT_IMAGE_HEIGHT,
|
|
9
|
+
PRO2_NFT_IMAGE_WIDTH,
|
|
10
|
+
PRO2_NFT_THUMBNAIL_HEIGHT,
|
|
11
|
+
PRO2_NFT_THUMBNAIL_WIDTH,
|
|
12
|
+
} from './pro2Nft';
|
|
7
13
|
|
|
8
14
|
import type { Features, IDeviceType } from '../types';
|
|
9
15
|
|
|
@@ -302,6 +308,31 @@ type SizeConfig = {
|
|
|
302
308
|
radius?: number;
|
|
303
309
|
};
|
|
304
310
|
|
|
311
|
+
export const getNftSize = ({
|
|
312
|
+
deviceType,
|
|
313
|
+
thumbnail,
|
|
314
|
+
}: {
|
|
315
|
+
deviceType: IDeviceType;
|
|
316
|
+
thumbnail?: boolean;
|
|
317
|
+
}): SizeConfig | undefined => {
|
|
318
|
+
const sizes: Partial<Record<IDeviceType, { full: SizeConfig; thumbnail: SizeConfig }>> = {
|
|
319
|
+
touch: {
|
|
320
|
+
full: { width: 480, height: 800 },
|
|
321
|
+
thumbnail: { width: 238, height: 238 },
|
|
322
|
+
},
|
|
323
|
+
pro: {
|
|
324
|
+
full: { width: 480, height: 800 },
|
|
325
|
+
thumbnail: { width: 226, height: 226, radius: 40 },
|
|
326
|
+
},
|
|
327
|
+
pro2: {
|
|
328
|
+
full: { width: PRO2_NFT_IMAGE_WIDTH, height: PRO2_NFT_IMAGE_HEIGHT },
|
|
329
|
+
thumbnail: { width: PRO2_NFT_THUMBNAIL_WIDTH, height: PRO2_NFT_THUMBNAIL_HEIGHT },
|
|
330
|
+
},
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
return sizes[deviceType]?.[thumbnail ? 'thumbnail' : 'full'];
|
|
334
|
+
};
|
|
335
|
+
|
|
305
336
|
export const getHomeScreenSize = ({
|
|
306
337
|
deviceType,
|
|
307
338
|
homeScreenType,
|
|
@@ -312,12 +343,7 @@ export const getHomeScreenSize = ({
|
|
|
312
343
|
thumbnail?: boolean;
|
|
313
344
|
}) => {
|
|
314
345
|
if (deviceType === EDeviceType.Pro2) {
|
|
315
|
-
return thumbnail
|
|
316
|
-
? undefined
|
|
317
|
-
: {
|
|
318
|
-
width: PRO2_WALLPAPER_WIDTH,
|
|
319
|
-
height: PRO2_WALLPAPER_HEIGHT,
|
|
320
|
-
};
|
|
346
|
+
return thumbnail ? undefined : { width: PRO2_WALLPAPER_WIDTH, height: PRO2_WALLPAPER_HEIGHT };
|
|
321
347
|
}
|
|
322
348
|
|
|
323
349
|
const sizes: Partial<
|
package/src/utils/index.ts
CHANGED
|
@@ -54,7 +54,12 @@ export { getHDPath, getScriptType, getOutputScriptType } from '../api/helpers/pa
|
|
|
54
54
|
|
|
55
55
|
export const isBleConnect = (env: string) => env === 'react-native' || env === 'lowlevel';
|
|
56
56
|
|
|
57
|
-
export {
|
|
57
|
+
export {
|
|
58
|
+
getHomeScreenHex,
|
|
59
|
+
getHomeScreenDefaultList,
|
|
60
|
+
getHomeScreenSize,
|
|
61
|
+
getNftSize,
|
|
62
|
+
} from './homescreen';
|
|
58
63
|
export { encodePro2Wallpaper, PRO2_WALLPAPER_HEIGHT, PRO2_WALLPAPER_WIDTH } from './pro2Wallpaper';
|
|
59
64
|
export type { Pro2WallpaperColorFormat } from './pro2Wallpaper';
|
|
60
65
|
|
|
@@ -0,0 +1,142 @@
|
|
|
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 = 2048;
|
|
13
|
+
export const PRO2_NFT_DEFAULT_PACE_MS = 0;
|
|
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
|
+
export const PRO2_NFT_MAX_ITEMS = 10;
|
|
18
|
+
|
|
19
|
+
export type Pro2NftImage = {
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
rgba: Uint8Array | ArrayBuffer;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type Pro2NftBundle = {
|
|
26
|
+
basename: string;
|
|
27
|
+
image: Uint8Array;
|
|
28
|
+
thumbnail: Uint8Array;
|
|
29
|
+
metadata: Uint8Array;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const PRO2_NFT_BASENAME_PATTERN = /^nft-[0-9a-f]{8}-[1-9][0-9]*$/;
|
|
33
|
+
|
|
34
|
+
type Pro2NftFileType = 'image' | 'thumbnail' | 'metadata';
|
|
35
|
+
|
|
36
|
+
function parsePro2NftFile(listedPath: string):
|
|
37
|
+
| {
|
|
38
|
+
basename: string;
|
|
39
|
+
fileType: Pro2NftFileType;
|
|
40
|
+
}
|
|
41
|
+
| undefined {
|
|
42
|
+
const filename = listedPath.trim().split('/').at(-1);
|
|
43
|
+
if (!filename) return undefined;
|
|
44
|
+
|
|
45
|
+
let basename: string | undefined;
|
|
46
|
+
let fileType: Pro2NftFileType | undefined;
|
|
47
|
+
if (filename.endsWith('_m.bin')) {
|
|
48
|
+
basename = filename.slice(0, -'_m.bin'.length);
|
|
49
|
+
fileType = 'thumbnail';
|
|
50
|
+
} else if (filename.endsWith('.json')) {
|
|
51
|
+
basename = filename.slice(0, -'.json'.length);
|
|
52
|
+
fileType = 'metadata';
|
|
53
|
+
} else if (filename.endsWith('.bin')) {
|
|
54
|
+
basename = filename.slice(0, -'.bin'.length);
|
|
55
|
+
fileType = 'image';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return basename && fileType && PRO2_NFT_BASENAME_PATTERN.test(basename)
|
|
59
|
+
? { basename, fileType }
|
|
60
|
+
: undefined;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function getCompletePro2NftBasenames(childFiles?: string): Set<string> {
|
|
64
|
+
const filesByBasename = new Map<string, Set<Pro2NftFileType>>();
|
|
65
|
+
|
|
66
|
+
for (const listedPath of childFiles?.split('\n') ?? []) {
|
|
67
|
+
const file = parsePro2NftFile(listedPath);
|
|
68
|
+
if (file) {
|
|
69
|
+
const fileTypes = filesByBasename.get(file.basename) ?? new Set<Pro2NftFileType>();
|
|
70
|
+
fileTypes.add(file.fileType);
|
|
71
|
+
filesByBasename.set(file.basename, fileTypes);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return new Set(
|
|
76
|
+
[...filesByBasename.entries()]
|
|
77
|
+
.filter(([, fileTypes]) => fileTypes.size === 3)
|
|
78
|
+
.map(([basename]) => basename)
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function utf8Length(value: string): number {
|
|
83
|
+
return new TextEncoder().encode(value).byteLength;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function assertImage(
|
|
87
|
+
name: string,
|
|
88
|
+
image: Pro2NftImage,
|
|
89
|
+
expectedWidth: number,
|
|
90
|
+
expectedHeight: number
|
|
91
|
+
) {
|
|
92
|
+
if (image.width !== expectedWidth || image.height !== expectedHeight) {
|
|
93
|
+
throw invalidParameter(
|
|
94
|
+
`Pro2 NFT ${name} dimensions must be ${expectedWidth}x${expectedHeight}.`
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
if (!(image.rgba instanceof ArrayBuffer) && !ArrayBuffer.isView(image.rgba)) {
|
|
98
|
+
throw invalidParameter(`Parameter [${name}.rgba] must be an ArrayBuffer or Uint8Array.`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function buildPro2NftBundle(options: {
|
|
103
|
+
image: Pro2NftImage;
|
|
104
|
+
thumbnail: Pro2NftImage;
|
|
105
|
+
title: string;
|
|
106
|
+
subtitle: string;
|
|
107
|
+
timestampMs: number;
|
|
108
|
+
}): Pro2NftBundle {
|
|
109
|
+
const { image, thumbnail, title, subtitle, timestampMs } = options;
|
|
110
|
+
assertImage('image', image, PRO2_NFT_IMAGE_WIDTH, PRO2_NFT_IMAGE_HEIGHT);
|
|
111
|
+
assertImage('thumbnail', thumbnail, PRO2_NFT_THUMBNAIL_WIDTH, PRO2_NFT_THUMBNAIL_HEIGHT);
|
|
112
|
+
const titleLength = typeof title === 'string' ? utf8Length(title) : 0;
|
|
113
|
+
const subtitleLength =
|
|
114
|
+
typeof subtitle === 'string' ? utf8Length(subtitle) : Number.POSITIVE_INFINITY;
|
|
115
|
+
if (titleLength < 1 || titleLength > 63) {
|
|
116
|
+
throw invalidParameter('Pro2 NFT title must contain 1 to 63 UTF-8 bytes.');
|
|
117
|
+
}
|
|
118
|
+
if (subtitleLength > 95) {
|
|
119
|
+
throw invalidParameter('Pro2 NFT subtitle must contain at most 95 UTF-8 bytes.');
|
|
120
|
+
}
|
|
121
|
+
if (!Number.isSafeInteger(timestampMs) || timestampMs <= 0) {
|
|
122
|
+
throw invalidParameter('Parameter [timestampMs] must be a positive safe integer.');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const encodedImage = encodePro2Image({ ...image, alphaMode: 'black-background' }).data;
|
|
126
|
+
const encodedThumbnail = encodePro2Image({
|
|
127
|
+
...thumbnail,
|
|
128
|
+
alphaMode: 'black-background',
|
|
129
|
+
}).data;
|
|
130
|
+
const metadata = new TextEncoder().encode(JSON.stringify({ title, subtitle }));
|
|
131
|
+
if (metadata.byteLength === 0 || metadata.byteLength > 512) {
|
|
132
|
+
throw invalidParameter('Pro2 NFT metadata must contain 1 to 512 UTF-8 bytes.');
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const hash8 = bytesToHex(blake2s(encodedImage)).slice(0, 8);
|
|
136
|
+
return {
|
|
137
|
+
basename: `nft-${hash8}-${timestampMs}`,
|
|
138
|
+
image: encodedImage,
|
|
139
|
+
thumbnail: encodedThumbnail,
|
|
140
|
+
metadata,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
@@ -8,6 +8,8 @@ export const PRO2_WALLPAPER_HEIGHT = 1024;
|
|
|
8
8
|
|
|
9
9
|
export type Pro2WallpaperColorFormat = 'RGB565' | 'RGB565A8';
|
|
10
10
|
|
|
11
|
+
export type Pro2ImageAlphaMode = 'preserve' | 'black-background';
|
|
12
|
+
|
|
11
13
|
const COLOR_FORMAT_RGB565 = 0x12;
|
|
12
14
|
const COLOR_FORMAT_RGB565A8 = 0x14;
|
|
13
15
|
|
|
@@ -36,10 +38,11 @@ function align(value: number, boundary: number): number {
|
|
|
36
38
|
return Math.ceil(value / boundary) * boundary;
|
|
37
39
|
}
|
|
38
40
|
|
|
39
|
-
export function
|
|
41
|
+
export function encodePro2Image(options: {
|
|
40
42
|
width: number;
|
|
41
43
|
height: number;
|
|
42
44
|
rgba: Uint8Array | ArrayBuffer;
|
|
45
|
+
alphaMode?: Pro2ImageAlphaMode;
|
|
43
46
|
}): { data: Uint8Array; colorFormat: Pro2WallpaperColorFormat } {
|
|
44
47
|
const { width, height } = options;
|
|
45
48
|
if (!Number.isInteger(width) || width <= 0 || width > 0xffff) {
|
|
@@ -57,11 +60,14 @@ export function encodePro2Wallpaper(options: {
|
|
|
57
60
|
);
|
|
58
61
|
}
|
|
59
62
|
|
|
63
|
+
const alphaMode = options.alphaMode ?? 'preserve';
|
|
60
64
|
let hasTransparency = false;
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
if (alphaMode === 'preserve') {
|
|
66
|
+
for (let index = 3; index < rgba.length; index += 4) {
|
|
67
|
+
if (rgba[index] !== 0xff) {
|
|
68
|
+
hasTransparency = true;
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
65
71
|
}
|
|
66
72
|
}
|
|
67
73
|
|
|
@@ -85,9 +91,22 @@ export function encodePro2Wallpaper(options: {
|
|
|
85
91
|
for (let x = 0; x < width; x += 1) {
|
|
86
92
|
const sourceOffset = (y * width + x) * 4;
|
|
87
93
|
const thresholdIndex = ((y & 7) << 3) + (x & 7);
|
|
88
|
-
const
|
|
89
|
-
const
|
|
90
|
-
|
|
94
|
+
const alpha = rgba[sourceOffset + 3];
|
|
95
|
+
const redChannel =
|
|
96
|
+
alphaMode === 'black-background'
|
|
97
|
+
? Math.round((rgba[sourceOffset] * alpha) / 0xff)
|
|
98
|
+
: rgba[sourceOffset];
|
|
99
|
+
const greenChannel =
|
|
100
|
+
alphaMode === 'black-background'
|
|
101
|
+
? Math.round((rgba[sourceOffset + 1] * alpha) / 0xff)
|
|
102
|
+
: rgba[sourceOffset + 1];
|
|
103
|
+
const blueChannel =
|
|
104
|
+
alphaMode === 'black-background'
|
|
105
|
+
? Math.round((rgba[sourceOffset + 2] * alpha) / 0xff)
|
|
106
|
+
: rgba[sourceOffset + 2];
|
|
107
|
+
const red = Math.min(redChannel + RED_THRESHOLD[thresholdIndex], 0xff) & 0xf8;
|
|
108
|
+
const green = Math.min(greenChannel + GREEN_THRESHOLD[thresholdIndex], 0xff) & 0xfc;
|
|
109
|
+
const blue = Math.min(blueChannel + BLUE_THRESHOLD[thresholdIndex], 0xff) & 0xf8;
|
|
91
110
|
const rgb565 = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
|
|
92
111
|
const rgbOffset = 12 + y * stride + x * 2;
|
|
93
112
|
data[rgbOffset] = rgb565 & 0xff;
|
|
@@ -101,3 +120,11 @@ export function encodePro2Wallpaper(options: {
|
|
|
101
120
|
|
|
102
121
|
return { data, colorFormat };
|
|
103
122
|
}
|
|
123
|
+
|
|
124
|
+
export function encodePro2Wallpaper(options: {
|
|
125
|
+
width: number;
|
|
126
|
+
height: number;
|
|
127
|
+
rgba: Uint8Array | ArrayBuffer;
|
|
128
|
+
}): { data: Uint8Array; colorFormat: Pro2WallpaperColorFormat } {
|
|
129
|
+
return encodePro2Image(options);
|
|
130
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
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
|
+
};
|