@onekeyfe/hd-core 1.2.0-alpha.101 → 1.2.0-alpha.103

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 (63) hide show
  1. package/__tests__/base64Data.test.ts +70 -0
  2. package/__tests__/check-all-firmware-release-protocol-v2.test.ts +2 -0
  3. package/__tests__/device-pool-state.test.ts +29 -0
  4. package/__tests__/deviceUploadNft.test.ts +33 -4
  5. package/__tests__/get-device-state.test.ts +102 -13
  6. package/__tests__/protocol-v2-legacy-recovery.test.ts +29 -0
  7. package/__tests__/protocol-v2.test.ts +309 -17
  8. package/__tests__/refresh-device-state.test.ts +4 -1
  9. package/__tests__/resourceBase64Boundary.test.ts +48 -0
  10. package/__tests__/search-devices.test.ts +2 -0
  11. package/__tests__/ton-sign-message.test.ts +84 -0
  12. package/dist/api/FirmwareUpdateV4.d.ts +3 -0
  13. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  14. package/dist/api/GetDeviceState.d.ts.map +1 -1
  15. package/dist/api/SearchDevices.d.ts.map +1 -1
  16. package/dist/api/UploadPortfolio.d.ts +1 -1
  17. package/dist/api/UploadPortfolio.d.ts.map +1 -1
  18. package/dist/api/firmware/protocolV2Release.d.ts.map +1 -1
  19. package/dist/api/helpers/base64Data.d.ts +16 -0
  20. package/dist/api/helpers/base64Data.d.ts.map +1 -0
  21. package/dist/api/protocol-v2/DeviceUploadNft.d.ts +2 -3
  22. package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -1
  23. package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts +2 -3
  24. package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -1
  25. package/dist/api/ton/TonSignMessage.d.ts.map +1 -1
  26. package/dist/core/index.d.ts.map +1 -1
  27. package/dist/core/protocolV2LegacyRecovery.d.ts +5 -0
  28. package/dist/core/protocolV2LegacyRecovery.d.ts.map +1 -0
  29. package/dist/device/Device.d.ts +9 -2
  30. package/dist/device/Device.d.ts.map +1 -1
  31. package/dist/device/DevicePool.d.ts +1 -1
  32. package/dist/device/DevicePool.d.ts.map +1 -1
  33. package/dist/index.d.ts +16 -14
  34. package/dist/index.js +266 -86
  35. package/dist/protocols/protocol-v2/features.d.ts +8 -0
  36. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  37. package/dist/protocols/protocol-v2/index.d.ts +2 -2
  38. package/dist/protocols/protocol-v2/index.d.ts.map +1 -1
  39. package/dist/types/api/getDeviceState.d.ts +1 -0
  40. package/dist/types/api/getDeviceState.d.ts.map +1 -1
  41. package/dist/types/api/protocolV2.d.ts +1 -1
  42. package/dist/types/api/protocolV2.d.ts.map +1 -1
  43. package/dist/utils/pro2Nft.d.ts +7 -0
  44. package/dist/utils/pro2Nft.d.ts.map +1 -1
  45. package/package.json +6 -4
  46. package/src/api/FirmwareUpdateV4.ts +70 -23
  47. package/src/api/GetDeviceState.ts +1 -0
  48. package/src/api/SearchDevices.ts +2 -0
  49. package/src/api/UploadPortfolio.ts +9 -2
  50. package/src/api/firmware/protocolV2Release.ts +1 -0
  51. package/src/api/helpers/base64Data.ts +85 -0
  52. package/src/api/protocol-v2/DeviceUploadNft.ts +56 -8
  53. package/src/api/protocol-v2/DeviceUploadWallpaper.ts +37 -18
  54. package/src/api/ton/TonSignMessage.ts +5 -3
  55. package/src/core/index.ts +4 -0
  56. package/src/core/protocolV2LegacyRecovery.ts +12 -0
  57. package/src/device/Device.ts +78 -20
  58. package/src/device/DevicePool.ts +17 -5
  59. package/src/protocols/protocol-v2/features.ts +10 -0
  60. package/src/protocols/protocol-v2/index.ts +2 -0
  61. package/src/types/api/getDeviceState.ts +2 -0
  62. package/src/types/api/protocolV2.ts +1 -1
  63. package/src/utils/pro2Nft.ts +31 -8
@@ -7,6 +7,14 @@ export type ProtocolV2SeStateLabel = 'BOOT' | 'APP_FACTORY' | 'APP';
7
7
  export declare const getProtocolV2SeState: (se?: DeviceSEInfo) => ProtocolV2SeStateLabel | null;
8
8
  export declare const getProtocolV2SeType: (se?: DeviceSEInfo) => string | null;
9
9
  export type ProtocolV2RuntimeMode = 'normal' | 'bootloader' | 'romloader';
10
+ export type ProtocolV2ProtocolInfo = ProtocolInfo & {
11
+ protobuf_definition?: string | null;
12
+ };
13
+ export declare const isLegacyProtocolV2ProtocolInfo: (protocolInfo: ProtocolInfo) => protocolInfo is ProtocolInfo & {
14
+ protobuf_definition?: string | null | undefined;
15
+ } & {
16
+ protobuf_definition: string | null;
17
+ };
10
18
  export type ProtocolV2BuildFingerprint = {
11
19
  binary: 'application' | 'bootloader' | 'romloader';
12
20
  version: string;
@@ -1 +1 @@
1
- {"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../../../src/protocols/protocol-v2/features.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,oBAAoB,EACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAGlE,YAAY,EAAE,oBAAoB,EAAE,CAAC;AACrC,YAAY,EAAE,uBAAuB,IAAI,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AACrG,YAAY,EAAE,YAAY,IAAI,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/E,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,aAAa,GAAG,KAAK,CAAC;AAoBpE,eAAO,MAAM,oBAAoB,QAAS,YAAY,KAAG,sBAAsB,GAAG,IAYjF,CAAC;AAKF,eAAO,MAAM,mBAAmB,QAAS,YAAY,KAAG,MAAM,GAAG,IACrB,CAAC;AAE7C,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,YAAY,GAAG,WAAW,CAAC;AAM1E,MAAM,MAAM,0BAA0B,GAAG;IACvC,MAAM,EAAE,aAAa,GAAG,YAAY,GAAG,WAAW,CAAC;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,GAAG,KAAK,CAAC;IAC5B,SAAS,EAAE,OAAO,GAAG,SAAS,CAAC;CAChC,CAAC;AAEF,eAAO,MAAM,+BAA+B,qBACxB,MAAM,GAAG,IAAI,GAAG,SAAS,KAC1C,0BAA0B,GAAG,IAc/B,CAAC;AAEF,eAAO,MAAM,wBAAwB,iBACrB,YAAY,KACzB,qBAAqB,GAAG,SAI1B,CAAC;AAGF,eAAO,MAAM,0CAA0C,QAAQ,CAAC;AAEhE,eAAO,MAAM,yBAAyB,iBACtB,YAAY,eACb,MAAM,KAClB,OAAgE,CAAC;AAEpE,eAAO,MAAM,wCAAwC;;;;;;;;;;CAUpD,CAAC;AAMF,eAAO,MAAM,wCAAwC;;;;;;;;;;;;;;CAcpD,CAAC;AAEF,eAAO,MAAM,oCAAoC;;;;;;;;;;;;;;;;CAgBhD,CAAC;AAEF,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;CAAuC,CAAC;AACpF,eAAO,MAAM,kCAAkC,QAAY,CAAC;AAE5D,wBAAsB,6BAA6B,CAAC,EAClD,QAAQ,EACR,SAAS,GACV,EAAE;IACD,QAAQ,EAAE,cAAc,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,YAAY,CAAC,CAaxB;AAED,wBAAsB,2BAA2B,CAAC,EAChD,QAAQ,EACR,SAA8C,EAC9C,OAAkD,GACnD,EAAE;IACD,QAAQ,EAAE,cAAc,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAMhC;AAED,wBAAsB,6BAA6B,CAAC,EAClD,QAAQ,EACR,SAAS,GACV,EAAE;IACD,QAAQ,EAAE,cAAc,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,YAAY,CAAC,CAOxB"}
1
+ {"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../../../src/protocols/protocol-v2/features.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,oBAAoB,EACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAGlE,YAAY,EAAE,oBAAoB,EAAE,CAAC;AACrC,YAAY,EAAE,uBAAuB,IAAI,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AACrG,YAAY,EAAE,YAAY,IAAI,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/E,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,aAAa,GAAG,KAAK,CAAC;AAoBpE,eAAO,MAAM,oBAAoB,QAAS,YAAY,KAAG,sBAAsB,GAAG,IAYjF,CAAC;AAKF,eAAO,MAAM,mBAAmB,QAAS,YAAY,KAAG,MAAM,GAAG,IACrB,CAAC;AAE7C,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,YAAY,GAAG,WAAW,CAAC;AAE1E,MAAM,MAAM,sBAAsB,GAAG,YAAY,GAAG;IAElD,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC,CAAC;AAEF,eAAO,MAAM,8BAA8B,iBAC3B,YAAY;;;yBACuC,MAAM,GAAG,IAAI;CACL,CAAC;AAM5E,MAAM,MAAM,0BAA0B,GAAG;IACvC,MAAM,EAAE,aAAa,GAAG,YAAY,GAAG,WAAW,CAAC;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,GAAG,KAAK,CAAC;IAC5B,SAAS,EAAE,OAAO,GAAG,SAAS,CAAC;CAChC,CAAC;AAEF,eAAO,MAAM,+BAA+B,qBACxB,MAAM,GAAG,IAAI,GAAG,SAAS,KAC1C,0BAA0B,GAAG,IAc/B,CAAC;AAEF,eAAO,MAAM,wBAAwB,iBACrB,YAAY,KACzB,qBAAqB,GAAG,SAI1B,CAAC;AAGF,eAAO,MAAM,0CAA0C,QAAQ,CAAC;AAEhE,eAAO,MAAM,yBAAyB,iBACtB,YAAY,eACb,MAAM,KAClB,OAAgE,CAAC;AAEpE,eAAO,MAAM,wCAAwC;;;;;;;;;;CAUpD,CAAC;AAMF,eAAO,MAAM,wCAAwC;;;;;;;;;;;;;;CAcpD,CAAC;AAEF,eAAO,MAAM,oCAAoC;;;;;;;;;;;;;;;;CAgBhD,CAAC;AAEF,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;CAAuC,CAAC;AACpF,eAAO,MAAM,kCAAkC,QAAY,CAAC;AAE5D,wBAAsB,6BAA6B,CAAC,EAClD,QAAQ,EACR,SAAS,GACV,EAAE;IACD,QAAQ,EAAE,cAAc,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,YAAY,CAAC,CAaxB;AAED,wBAAsB,2BAA2B,CAAC,EAChD,QAAQ,EACR,SAA8C,EAC9C,OAAkD,GACnD,EAAE;IACD,QAAQ,EAAE,cAAc,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAMhC;AAED,wBAAsB,6BAA6B,CAAC,EAClD,QAAQ,EACR,SAAS,GACV,EAAE;IACD,QAAQ,EAAE,cAAc,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,YAAY,CAAC,CAOxB"}
@@ -1,5 +1,5 @@
1
- export { PROTOCOL_V2_DEVICE_INFO_REQUEST, PROTOCOL_V2_DEVICE_INFO_TIMEOUT_MS, PROTOCOL_V2_DEVICE_STATUS_GET_MESSAGE_TYPE, PROTOCOL_V2_FEATURES_DEVICE_INFO_REQUEST, PROTOCOL_V2_VERSIONS_DEVICE_INFO_REQUEST, getProtocolV2RuntimeMode, getProtocolV2SeState, getProtocolV2SeType, parseProtocolV2BuildFingerprint, requestProtocolV2ProtocolInfo, supportsProtocolV2Message, } from './features';
2
- export type { ProtocolV2BuildFingerprint, ProtocolV2DeviceInfo, ProtocolV2FirmwareImageInfo, ProtocolV2SEInfo, ProtocolV2SeStateLabel, ProtocolV2RuntimeMode, } from './features';
1
+ export { PROTOCOL_V2_DEVICE_INFO_REQUEST, PROTOCOL_V2_DEVICE_INFO_TIMEOUT_MS, PROTOCOL_V2_DEVICE_STATUS_GET_MESSAGE_TYPE, PROTOCOL_V2_FEATURES_DEVICE_INFO_REQUEST, PROTOCOL_V2_VERSIONS_DEVICE_INFO_REQUEST, getProtocolV2RuntimeMode, getProtocolV2SeState, getProtocolV2SeType, isLegacyProtocolV2ProtocolInfo, parseProtocolV2BuildFingerprint, requestProtocolV2ProtocolInfo, supportsProtocolV2Message, } from './features';
2
+ export type { ProtocolV2BuildFingerprint, ProtocolV2DeviceInfo, ProtocolV2FirmwareImageInfo, ProtocolV2SEInfo, ProtocolV2SeStateLabel, ProtocolV2RuntimeMode, ProtocolV2ProtocolInfo, } from './features';
3
3
  export * from './firmware';
4
4
  export * from './walletSession';
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/protocols/protocol-v2/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,+BAA+B,EAC/B,kCAAkC,EAClC,0CAA0C,EAC1C,wCAAwC,EACxC,wCAAwC,EACxC,wBAAwB,EACxB,oBAAoB,EACpB,mBAAmB,EACnB,+BAA+B,EAC/B,6BAA6B,EAC7B,yBAAyB,GAC1B,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,0BAA0B,EAC1B,oBAAoB,EACpB,2BAA2B,EAC3B,gBAAgB,EAChB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,YAAY,CAAC;AACpB,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/protocols/protocol-v2/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,+BAA+B,EAC/B,kCAAkC,EAClC,0CAA0C,EAC1C,wCAAwC,EACxC,wCAAwC,EACxC,wBAAwB,EACxB,oBAAoB,EACpB,mBAAmB,EACnB,8BAA8B,EAC9B,+BAA+B,EAC/B,6BAA6B,EAC7B,yBAAyB,GAC1B,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,0BAA0B,EAC1B,oBAAoB,EACpB,2BAA2B,EAC3B,gBAAgB,EAChB,sBAAsB,EACtB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AACpB,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC"}
@@ -7,6 +7,7 @@ export type GetDeviceStateParams = CommonParams & {
7
7
  export type DeviceStateReadOptions = {
8
8
  refreshSections?: DeviceStateSection[];
9
9
  includeRaw?: boolean;
10
+ allowLegacyProtocolV2ProtocolInfo?: boolean;
10
11
  };
11
12
  export declare function getDeviceState(connectId?: string, params?: GetDeviceStateParams): Response<DeviceState>;
12
13
  //# sourceMappingURL=getDeviceState.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"getDeviceState.d.ts","sourceRoot":"","sources":["../../../src/types/api/getDeviceState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAExD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;AAEnE,MAAM,MAAM,oBAAoB,GAAG,YAAY,GAAG;IAChD,KAAK,CAAC,EAAE,gBAAgB,CAAC;CAC1B,CAAC;AAGF,MAAM,MAAM,sBAAsB,GAAG;IACnC,eAAe,CAAC,EAAE,kBAAkB,EAAE,CAAC;IACvC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,cAAc,CACpC,SAAS,CAAC,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,oBAAoB,GAC5B,QAAQ,CAAC,WAAW,CAAC,CAAC"}
1
+ {"version":3,"file":"getDeviceState.d.ts","sourceRoot":"","sources":["../../../src/types/api/getDeviceState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAExD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;AAEnE,MAAM,MAAM,oBAAoB,GAAG,YAAY,GAAG;IAChD,KAAK,CAAC,EAAE,gBAAgB,CAAC;CAC1B,CAAC;AAGF,MAAM,MAAM,sBAAsB,GAAG;IACnC,eAAe,CAAC,EAAE,kBAAkB,EAAE,CAAC;IACvC,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,iCAAiC,CAAC,EAAE,OAAO,CAAC;CAC7C,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,cAAc,CACpC,SAAS,CAAC,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,oBAAoB,GAC5B,QAAQ,CAAC,WAAW,CAAC,CAAC"}
@@ -24,7 +24,7 @@ export declare function deviceGetOnboardingStatus(connectId: string, params?: Co
24
24
  export declare function deviceUploadWallpaper(connectId: string, params: CommonParams & DeviceUploadWallpaperParams): Response<DeviceUploadWallpaperResponse>;
25
25
  export declare function deviceUploadNft(connectId: string, params: CommonParams & DeviceUploadNftParams): Response<DeviceUploadNftResponse>;
26
26
  export declare function uploadPortfolio(connectId: string, params: {
27
- packageBytes: ArrayBuffer | Uint8Array | Blob;
27
+ packageBase64: string;
28
28
  timeoutMs?: number | string;
29
29
  }): Response<FileInfo & {
30
30
  portfolioUpdated: true;
@@ -1 +1 @@
1
- {"version":3,"file":"protocolV2.d.ts","sourceRoot":"","sources":["../../../src/types/api/protocolV2.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACxE,OAAO,KAAK,EACV,2BAA2B,EAC3B,6BAA6B,EAC9B,MAAM,6CAA6C,CAAC;AACrD,OAAO,KAAK,EACV,qBAAqB,EACrB,uBAAuB,EACxB,MAAM,uCAAuC,CAAC;AAG/C,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACzF,YAAY,EACV,2BAA2B,EAC3B,6BAA6B,GAC9B,MAAM,6CAA6C,CAAC;AACrD,YAAY,EACV,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,uCAAuC,CAAC;AAI/C,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAIF,MAAM,MAAM,wBAAwB,GAAG,YAAY,GAAG;IAEpD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,kBAAkB,CACxC,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,wBAAwB,GAChC,QAAQ,CAAC,OAAO,CAAC,CAAC;AAErB,MAAM,CAAC,OAAO,UAAU,YAAY,CAClC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,YAAY,GAAG,kBAAkB,GACxC,QAAQ,CAAC,OAAO,CAAC,CAAC;AAErB,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAC/C,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,YAAY,GACpB,QAAQ,CAAC,gBAAgB,CAAC,CAAC;AAE9B,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAC3C,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,YAAY,GAAG,2BAA2B,GACjD,QAAQ,CAAC,6BAA6B,CAAC,CAAC;AAE3C,MAAM,CAAC,OAAO,UAAU,eAAe,CACrC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,YAAY,GAAG,qBAAqB,GAC3C,QAAQ,CAAC,uBAAuB,CAAC,CAAC;AAErC,MAAM,CAAC,OAAO,UAAU,eAAe,CACrC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;IACN,YAAY,EAAE,WAAW,GAAG,UAAU,GAAG,IAAI,CAAC;IAC9C,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC7B,GACA,QAAQ,CAAC,QAAQ,GAAG;IAAE,gBAAgB,EAAE,IAAI,CAAA;CAAE,CAAC,CAAC"}
1
+ {"version":3,"file":"protocolV2.d.ts","sourceRoot":"","sources":["../../../src/types/api/protocolV2.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACxE,OAAO,KAAK,EACV,2BAA2B,EAC3B,6BAA6B,EAC9B,MAAM,6CAA6C,CAAC;AACrD,OAAO,KAAK,EACV,qBAAqB,EACrB,uBAAuB,EACxB,MAAM,uCAAuC,CAAC;AAG/C,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACzF,YAAY,EACV,2BAA2B,EAC3B,6BAA6B,GAC9B,MAAM,6CAA6C,CAAC;AACrD,YAAY,EACV,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,uCAAuC,CAAC;AAI/C,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAIF,MAAM,MAAM,wBAAwB,GAAG,YAAY,GAAG;IAEpD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,kBAAkB,CACxC,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,wBAAwB,GAChC,QAAQ,CAAC,OAAO,CAAC,CAAC;AAErB,MAAM,CAAC,OAAO,UAAU,YAAY,CAClC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,YAAY,GAAG,kBAAkB,GACxC,QAAQ,CAAC,OAAO,CAAC,CAAC;AAErB,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAC/C,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,YAAY,GACpB,QAAQ,CAAC,gBAAgB,CAAC,CAAC;AAE9B,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAC3C,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,YAAY,GAAG,2BAA2B,GACjD,QAAQ,CAAC,6BAA6B,CAAC,CAAC;AAE3C,MAAM,CAAC,OAAO,UAAU,eAAe,CACrC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,YAAY,GAAG,qBAAqB,GAC3C,QAAQ,CAAC,uBAAuB,CAAC,CAAC;AAErC,MAAM,CAAC,OAAO,UAAU,eAAe,CACrC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;IACN,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC7B,GACA,QAAQ,CAAC,QAAQ,GAAG;IAAE,gBAAgB,EAAE,IAAI,CAAA;CAAE,CAAC,CAAC"}
@@ -28,4 +28,11 @@ export declare function buildPro2NftBundle(options: {
28
28
  subtitle: string;
29
29
  timestampMs: number;
30
30
  }): Pro2NftBundle;
31
+ export declare function buildPro2NftBundleFromEncodedImages(options: {
32
+ image: Uint8Array;
33
+ thumbnail: Uint8Array;
34
+ title: string;
35
+ subtitle: string;
36
+ timestampMs: number;
37
+ }): Pro2NftBundle;
31
38
  //# sourceMappingURL=pro2Nft.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pro2Nft.d.ts","sourceRoot":"","sources":["../../src/utils/pro2Nft.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,oBAAoB,MAAM,CAAC;AACxC,eAAO,MAAM,qBAAqB,MAAM,CAAC;AACzC,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAC5C,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C,eAAO,MAAM,kBAAkB,cAAc,CAAC;AAC9C,eAAO,MAAM,2BAA2B,OAAO,CAAC;AAChD,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAC1C,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAClD,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAC5C,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,UAAU,GAAG,WAAW,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,UAAU,CAAC;IACtB,QAAQ,EAAE,UAAU,CAAC;CACtB,CAAC;AAiCF,wBAAgB,2BAA2B,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAiB5E;AAsBD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC1C,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,YAAY,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,aAAa,CAkChB"}
1
+ {"version":3,"file":"pro2Nft.d.ts","sourceRoot":"","sources":["../../src/utils/pro2Nft.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,oBAAoB,MAAM,CAAC;AACxC,eAAO,MAAM,qBAAqB,MAAM,CAAC;AACzC,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAC5C,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C,eAAO,MAAM,kBAAkB,cAAc,CAAC;AAC9C,eAAO,MAAM,2BAA2B,OAAO,CAAC;AAChD,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAC1C,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAClD,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAC5C,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,UAAU,GAAG,WAAW,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,UAAU,CAAC;IACtB,QAAQ,EAAE,UAAU,CAAC;CACtB,CAAC;AAiCF,wBAAgB,2BAA2B,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAiB5E;AAsBD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC1C,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,YAAY,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,aAAa,CAgBhB;AAED,wBAAgB,mCAAmC,CAAC,OAAO,EAAE;IAC3D,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,UAAU,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,aAAa,CAiChB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-core",
3
- "version": "1.2.0-alpha.101",
3
+ "version": "1.2.0-alpha.103",
4
4
  "description": "Core processes and APIs for communicating with OneKey hardware devices.",
5
5
  "author": "OneKey",
6
6
  "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
@@ -25,11 +25,13 @@
25
25
  "url": "https://github.com/OneKeyHQ/hardware-js-sdk/issues"
26
26
  },
27
27
  "dependencies": {
28
- "@onekeyfe/hd-shared": "1.2.0-alpha.101",
29
- "@onekeyfe/hd-transport": "1.2.0-alpha.101",
28
+ "@onekeyfe/hd-shared": "1.2.0-alpha.103",
29
+ "@onekeyfe/hd-transport": "1.2.0-alpha.103",
30
30
  "axios": "1.15.2",
31
31
  "bignumber.js": "^9.0.2",
32
+ "buffer": "^6.0.3",
32
33
  "bytebuffer": "^5.0.1",
34
+ "jpeg-js": "^0.4.4",
33
35
  "jszip": "^3.10.1",
34
36
  "parse-uri": "^1.0.7",
35
37
  "semver": "^7.3.7"
@@ -44,5 +46,5 @@
44
46
  "@types/w3c-web-usb": "^1.0.10",
45
47
  "@types/web-bluetooth": "^0.0.21"
46
48
  },
47
- "gitHead": "f24ac3a93c71dc3814e62c5e6bcf6a4c757e0d44"
49
+ "gitHead": "ba7c3866269200b25a514202b8286d0c9e9105d3"
48
50
  }
@@ -28,6 +28,7 @@ import { DevicePool } from '../device/DevicePool';
28
28
  import {
29
29
  PROTOCOL_V2_VERSIONS_DEVICE_INFO_REQUEST,
30
30
  ProtocolV2FirmwareTargetType,
31
+ isLegacyProtocolV2ProtocolInfo,
31
32
  } from '../protocols/protocol-v2';
32
33
  import { requestProtocolV2DeviceInfo } from '../protocols/protocol-v2/features';
33
34
  import {
@@ -393,6 +394,13 @@ const isProtocolV2FirmwareStatusEndpointUnavailable = (error: unknown) => {
393
394
  );
394
395
  };
395
396
 
397
+ const isProtocolV2FirmwareUpdateEndpointUnavailable = (error: unknown) => {
398
+ const message = getProtocolV2UnknownErrorText(error).toLowerCase();
399
+ return (
400
+ message.includes('handler not registered') || message.includes('message handler not found')
401
+ );
402
+ };
403
+
396
404
  const isProtocolV2TerminalInstallStatusError = (error: unknown) =>
397
405
  error instanceof HardwareError &&
398
406
  (error.errorCode === HardwareErrorCode.FirmwareError ||
@@ -587,6 +595,8 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
587
595
 
588
596
  private protocolV2ExecutionInLoader = false;
589
597
 
598
+ private protocolV2LegacyDirectUpdate = false;
599
+
590
600
  private protocolV2BootResourceStagingSafe = false;
591
601
 
592
602
  private protocolV2CompletedTargetVersions = new Map<number, number>();
@@ -2067,21 +2077,12 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
2067
2077
  return this.device.features?.mode === 'romloader';
2068
2078
  }
2069
2079
 
2070
- async enterProtocolV2BootloaderMode() {
2071
- // romloader is the first update environment and forwards targets to bootloader.
2072
- // It rejects DeviceRebootType.Bootloader, so reuse the current connection.
2073
- if (this.isProtocolV2RomloaderMode()) {
2074
- Log.debug('Protocol V2 device is in romloader mode; start firmware update directly');
2075
- this.protocolV2ExecutionInLoader = true;
2076
- return false;
2077
- }
2078
- if (this.isProtocolV2BootloaderMode()) {
2079
- Log.debug('Protocol V2 device is already in bootloader mode, skip reboot');
2080
- this.protocolV2ExecutionInLoader = true;
2081
- this.postTipMessage(FirmwareUpdateTipMessage.GoToBootloaderSuccess);
2082
- return false;
2083
- }
2080
+ private isLegacyProtocolV2Runtime() {
2081
+ const protocolInfo = this.device.state?.raw?.protocolV2ProtocolInfo;
2082
+ return protocolInfo ? isLegacyProtocolV2ProtocolInfo(protocolInfo) : false;
2083
+ }
2084
2084
 
2085
+ private async rebootProtocolV2ToBootloader() {
2085
2086
  try {
2086
2087
  this.postTipMessage(FirmwareUpdateTipMessage.AutoRebootToBootloader);
2087
2088
  await this.protocolV2Reboot(DeviceRebootType.Bootloader);
@@ -2099,6 +2100,27 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
2099
2100
  }
2100
2101
  }
2101
2102
 
2103
+ async enterProtocolV2BootloaderMode() {
2104
+ this.protocolV2LegacyDirectUpdate = false;
2105
+ // romloader is the first update environment and forwards targets to bootloader.
2106
+ // It rejects DeviceRebootType.Bootloader, so reuse the current connection.
2107
+ if (this.isProtocolV2RomloaderMode()) {
2108
+ Log.debug('Protocol V2 device is in romloader mode; start firmware update directly');
2109
+ this.protocolV2LegacyDirectUpdate = this.isLegacyProtocolV2Runtime();
2110
+ this.protocolV2ExecutionInLoader = true;
2111
+ return false;
2112
+ }
2113
+ if (this.isProtocolV2BootloaderMode()) {
2114
+ Log.debug('Protocol V2 device is already in bootloader mode, skip reboot');
2115
+ this.protocolV2LegacyDirectUpdate = this.isLegacyProtocolV2Runtime();
2116
+ this.protocolV2ExecutionInLoader = true;
2117
+ this.postTipMessage(FirmwareUpdateTipMessage.GoToBootloaderSuccess);
2118
+ return false;
2119
+ }
2120
+
2121
+ return this.rebootProtocolV2ToBootloader();
2122
+ }
2123
+
2102
2124
  private async waitForProtocolV2BootloaderMode(
2103
2125
  timeout = PROTOCOL_V2_BOOTLOADER_RECONNECT_TIMEOUT,
2104
2126
  retryInterval = 1000
@@ -2120,7 +2142,8 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
2120
2142
  this.assertProtocolV2DeviceInfoIdentity(deviceInfo);
2121
2143
  const features = await this.device.probeProtocolV2RuntimeState(
2122
2144
  deviceInfo,
2123
- PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT
2145
+ PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT,
2146
+ { allowLegacyProtocolV2ProtocolInfo: true }
2124
2147
  );
2125
2148
  if (features?.mode === 'bootloader') {
2126
2149
  return features;
@@ -2809,7 +2832,8 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
2809
2832
  private async probeProtocolV2NormalMode(deviceInfo: ProtocolV2DeviceInfo) {
2810
2833
  const features = await this.device.probeProtocolV2RuntimeState(
2811
2834
  deviceInfo,
2812
- PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT
2835
+ PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT,
2836
+ { allowLegacyProtocolV2ProtocolInfo: true }
2813
2837
  );
2814
2838
  return features.mode === 'normal' && !features.bootloaderMode;
2815
2839
  }
@@ -2871,7 +2895,8 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
2871
2895
  this.assertProtocolV2DeviceInfoIdentity(deviceInfo);
2872
2896
  const features = await this.device.probeProtocolV2RuntimeState(
2873
2897
  deviceInfo,
2874
- PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT
2898
+ PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT,
2899
+ { allowLegacyProtocolV2ProtocolInfo: true }
2875
2900
  );
2876
2901
  if (features.mode === 'normal' && !features.bootloaderMode) {
2877
2902
  return features;
@@ -3044,12 +3069,34 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
3044
3069
  targets: Array<{ target_id: number; path: string }>;
3045
3070
  }) {
3046
3071
  const commands = this.device.getCommands();
3047
- const response: ProtocolV2FirmwareUpdateStartResponse = await commands.typedCall(
3048
- 'DeviceFirmwareUpdateRequest',
3049
- 'Success',
3050
- { targets },
3051
- { timeoutMs: PROTOCOL_V2_START_UPDATE_TIMEOUT }
3052
- );
3072
+ const startUpdate = () =>
3073
+ commands.typedCall(
3074
+ 'DeviceFirmwareUpdateRequest',
3075
+ 'Success',
3076
+ { targets },
3077
+ { timeoutMs: PROTOCOL_V2_START_UPDATE_TIMEOUT }
3078
+ );
3079
+ let response: ProtocolV2FirmwareUpdateStartResponse;
3080
+ try {
3081
+ response = await startUpdate();
3082
+ } catch (error) {
3083
+ if (
3084
+ !this.protocolV2LegacyDirectUpdate ||
3085
+ !isProtocolV2FirmwareUpdateEndpointUnavailable(error)
3086
+ ) {
3087
+ throw error;
3088
+ }
3089
+
3090
+ // Both legacy loaders register this request. A missing handler therefore identifies
3091
+ // a legacy App before dispatch, so it is safe to reboot and retry the unhandled request.
3092
+ this.protocolV2LegacyDirectUpdate = false;
3093
+ Log.debug(
3094
+ '[FirmwareUpdateV4] legacy App does not expose DeviceFirmwareUpdateRequest; rebooting to bootloader'
3095
+ );
3096
+ await this.rebootProtocolV2ToBootloader();
3097
+ response = await startUpdate();
3098
+ }
3099
+ this.protocolV2LegacyDirectUpdate = false;
3053
3100
  // Success acknowledges that the device accepted installation. End confirmation
3054
3101
  // and begin status polling only after receiving this ACK.
3055
3102
  this.postTipMessage(FirmwareUpdateTipMessage.FirmwareUpdating);
@@ -43,6 +43,7 @@ export default class GetDeviceState extends BaseMethod<
43
43
  async run() {
44
44
  const state = await this.device.getDeviceState({
45
45
  refreshSections: SCOPE_SECTIONS[this.params.scope],
46
+ ...(this.params.scope === 'firmware' ? { allowLegacyProtocolV2ProtocolInfo: true } : {}),
46
47
  });
47
48
  if (
48
49
  this.params.scope === 'settings' &&
@@ -63,6 +63,8 @@ export default class SearchDevices extends BaseMethod {
63
63
  connectProtocol: undefined,
64
64
  forceProtocolDetection: true,
65
65
  refreshRuntimeState: true,
66
+ // Old loader firmware predates build_fingerprint. Keep this recovery-only.
67
+ allowLegacyProtocolV2ProtocolInfo: true,
66
68
  });
67
69
  deviceList.push(...result.deviceList);
68
70
  } catch (error) {
@@ -1,21 +1,28 @@
1
1
  import { createDeviceNotSupportMethodError } from '@onekeyfe/hd-shared';
2
2
 
3
3
  import { supportsProtocolV2Message } from '../protocols/protocol-v2/features';
4
+ import { decodeCanonicalBase64 } from './helpers/base64Data';
4
5
  import FileWrite from './FileWrite';
5
6
 
6
7
  export type UploadPortfolioParams = {
7
- packageBytes: ArrayBuffer | Uint8Array | Blob;
8
+ packageBase64: string;
8
9
  timeoutMs?: number | string;
9
10
  };
10
11
 
11
12
  const PORTFOLIO_PENDING_PATH = 'vol1:/portfolio/portfolio.okpkg.pending';
12
13
  const PORTFOLIO_CHUNK_SIZE = 2048;
14
+ const PORTFOLIO_PACKAGE_MAX_BYTES = 128 * 1024;
13
15
  const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE = 60805;
14
16
  const PORTFOLIO_UPDATE_MESSAGE_TYPE = 61400;
15
17
 
16
18
  export default class UploadPortfolio extends FileWrite {
17
19
  init() {
18
- const { packageBytes, timeoutMs } = this.payload as UploadPortfolioParams;
20
+ const { packageBase64, timeoutMs } = this.payload as UploadPortfolioParams;
21
+ const packageBytes = decodeCanonicalBase64({
22
+ value: packageBase64,
23
+ parameterName: 'packageBase64',
24
+ maxBytes: PORTFOLIO_PACKAGE_MAX_BYTES,
25
+ });
19
26
  this.payload = {
20
27
  ...this.payload,
21
28
  path: PORTFOLIO_PENDING_PATH,
@@ -60,6 +60,7 @@ export async function loadProtocolV2FirmwareReleaseContext({
60
60
  refreshSections: checkFirmwareHash
61
61
  ? ['identity', 'versions', 'verification']
62
62
  : ['identity', 'versions'],
63
+ allowLegacyProtocolV2ProtocolInfo: true,
63
64
  });
64
65
  if (state.identity.deviceType !== 'pro2' && state.identity.deviceType !== 'neo') {
65
66
  throw ERRORS.TypedError(
@@ -0,0 +1,85 @@
1
+ import { Buffer } from 'buffer';
2
+ import { decode as decodeJpeg } from 'jpeg-js';
3
+
4
+ import { invalidParameter } from './filesystemValidation';
5
+
6
+ const BASE64_PATTERN = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
7
+ const JPEG_CONTAINER_OVERHEAD_BYTES = 64 * 1024;
8
+ const JPEG_MAX_MEMORY_USAGE_IN_MB = 32;
9
+ const JPEG_MAX_RESOLUTION_IN_MP = 1;
10
+
11
+ export function decodeCanonicalBase64({
12
+ value,
13
+ parameterName,
14
+ maxBytes,
15
+ }: {
16
+ value: unknown;
17
+ parameterName: string;
18
+ maxBytes: number;
19
+ }): Uint8Array {
20
+ if (typeof value !== 'string' || value.length === 0) {
21
+ throw invalidParameter(`Parameter [${parameterName}] must be a non-empty Base64 string.`);
22
+ }
23
+ if (value.length > Math.ceil(maxBytes / 3) * 4) {
24
+ throw invalidParameter(`Parameter [${parameterName}] exceeds the maximum supported size.`);
25
+ }
26
+ if (value.length % 4 !== 0 || !BASE64_PATTERN.test(value)) {
27
+ throw invalidParameter(`Parameter [${parameterName}] must use canonical Base64 encoding.`);
28
+ }
29
+
30
+ const decoded = Buffer.from(value, 'base64');
31
+ if (decoded.byteLength === 0 || decoded.byteLength > maxBytes) {
32
+ throw invalidParameter(`Parameter [${parameterName}] exceeds the maximum supported size.`);
33
+ }
34
+ if (decoded.toString('base64') !== value) {
35
+ throw invalidParameter(`Parameter [${parameterName}] must use canonical Base64 encoding.`);
36
+ }
37
+ return Uint8Array.from(decoded);
38
+ }
39
+
40
+ export function decodeJpegBase64ToRgba({
41
+ jpegBase64,
42
+ parameterName,
43
+ expectedWidth,
44
+ expectedHeight,
45
+ }: {
46
+ jpegBase64: unknown;
47
+ parameterName: string;
48
+ expectedWidth: number;
49
+ expectedHeight: number;
50
+ }): { width: number; height: number; data: Uint8Array } {
51
+ const jpegBytes = decodeCanonicalBase64({
52
+ value: jpegBase64,
53
+ parameterName,
54
+ maxBytes: expectedWidth * expectedHeight * 8 + JPEG_CONTAINER_OVERHEAD_BYTES,
55
+ });
56
+ if (jpegBytes[0] !== 0xff || jpegBytes[1] !== 0xd8) {
57
+ throw invalidParameter(`Parameter [${parameterName}] must contain a JPEG image.`);
58
+ }
59
+
60
+ let decoded: { width: number; height: number; data: Uint8Array };
61
+ try {
62
+ decoded = decodeJpeg(jpegBytes, {
63
+ useTArray: true,
64
+ formatAsRGBA: true,
65
+ tolerantDecoding: false,
66
+ maxResolutionInMP: JPEG_MAX_RESOLUTION_IN_MP,
67
+ maxMemoryUsageInMB: JPEG_MAX_MEMORY_USAGE_IN_MB,
68
+ });
69
+ } catch {
70
+ throw invalidParameter(`Parameter [${parameterName}] must contain a valid JPEG image.`);
71
+ }
72
+
73
+ if (decoded.width !== expectedWidth || decoded.height !== expectedHeight) {
74
+ throw invalidParameter(
75
+ `Parameter [${parameterName}] must contain a ${expectedWidth}x${expectedHeight} JPEG image.`
76
+ );
77
+ }
78
+ const expectedLength = expectedWidth * expectedHeight * 4;
79
+ if (decoded.data.byteLength !== expectedLength) {
80
+ throw invalidParameter(
81
+ `Decoded parameter [${parameterName}] must contain ${expectedLength} RGBA bytes.`
82
+ );
83
+ }
84
+ return decoded;
85
+ }
@@ -7,21 +7,26 @@ import {
7
7
  PRO2_NFT_DEFAULT_PACE_MS,
8
8
  PRO2_NFT_DEFAULT_TIMEOUT_MS,
9
9
  PRO2_NFT_DIRECTORY,
10
+ PRO2_NFT_IMAGE_HEIGHT,
11
+ PRO2_NFT_IMAGE_WIDTH,
10
12
  PRO2_NFT_MAX_CHUNK_SIZE,
11
13
  PRO2_NFT_MAX_ITEMS,
12
14
  PRO2_NFT_MIN_CHUNK_SIZE,
15
+ PRO2_NFT_THUMBNAIL_HEIGHT,
16
+ PRO2_NFT_THUMBNAIL_WIDTH,
13
17
  type Pro2NftBundle,
14
- type Pro2NftImage,
15
- buildPro2NftBundle,
18
+ buildPro2NftBundleFromEncodedImages,
16
19
  getCompletePro2NftBasenames,
17
20
  } from '../../utils/pro2Nft';
21
+ import { encodePro2Image } from '../../utils/pro2Wallpaper';
18
22
  import { BaseMethod } from '../BaseMethod';
23
+ import { decodeJpegBase64ToRgba } from '../helpers/base64Data';
19
24
  import { invalidParameter } from '../helpers/filesystemValidation';
20
25
  import { writeProtocolV2File } from '../helpers/protocolV2FileWrite';
21
26
 
22
27
  export type DeviceUploadNftParams = {
23
- image: Pro2NftImage;
24
- thumbnail: Pro2NftImage;
28
+ imageJpegBase64: string;
29
+ thumbnailJpegBase64: string;
25
30
  title: string;
26
31
  subtitle: string;
27
32
  timestampMs?: number;
@@ -54,8 +59,8 @@ export default class DeviceUploadNft extends BaseMethod<DeviceUploadNftParams> {
54
59
 
55
60
  init() {
56
61
  const {
57
- image,
58
- thumbnail,
62
+ imageJpegBase64,
63
+ thumbnailJpegBase64,
59
64
  title,
60
65
  subtitle,
61
66
  timestampMs = Date.now(),
@@ -79,8 +84,51 @@ export default class DeviceUploadNft extends BaseMethod<DeviceUploadNftParams> {
79
84
  throw invalidParameter('Parameter [timeoutMs] must be a positive integer.');
80
85
  }
81
86
 
82
- this.bundle = buildPro2NftBundle({ image, thumbnail, title, subtitle, timestampMs });
83
- this.params = { image, thumbnail, title, subtitle, timestampMs, chunkSize, paceMs, timeoutMs };
87
+ const encodedImage = (() => {
88
+ const decoded = decodeJpegBase64ToRgba({
89
+ jpegBase64: imageJpegBase64,
90
+ parameterName: 'imageJpegBase64',
91
+ expectedWidth: PRO2_NFT_IMAGE_WIDTH,
92
+ expectedHeight: PRO2_NFT_IMAGE_HEIGHT,
93
+ });
94
+ return encodePro2Image({
95
+ width: PRO2_NFT_IMAGE_WIDTH,
96
+ height: PRO2_NFT_IMAGE_HEIGHT,
97
+ rgba: decoded.data,
98
+ alphaMode: 'black-background',
99
+ }).data;
100
+ })();
101
+ const encodedThumbnail = (() => {
102
+ const decoded = decodeJpegBase64ToRgba({
103
+ jpegBase64: thumbnailJpegBase64,
104
+ parameterName: 'thumbnailJpegBase64',
105
+ expectedWidth: PRO2_NFT_THUMBNAIL_WIDTH,
106
+ expectedHeight: PRO2_NFT_THUMBNAIL_HEIGHT,
107
+ });
108
+ return encodePro2Image({
109
+ width: PRO2_NFT_THUMBNAIL_WIDTH,
110
+ height: PRO2_NFT_THUMBNAIL_HEIGHT,
111
+ rgba: decoded.data,
112
+ alphaMode: 'black-background',
113
+ }).data;
114
+ })();
115
+ this.bundle = buildPro2NftBundleFromEncodedImages({
116
+ image: encodedImage,
117
+ thumbnail: encodedThumbnail,
118
+ title,
119
+ subtitle,
120
+ timestampMs,
121
+ });
122
+ this.params = {
123
+ imageJpegBase64,
124
+ thumbnailJpegBase64,
125
+ title,
126
+ subtitle,
127
+ timestampMs,
128
+ chunkSize,
129
+ paceMs,
130
+ timeoutMs,
131
+ };
84
132
  this.unlockPolicy = 'none';
85
133
  this.skipForceUpdateCheck = true;
86
134
  this.useDevicePassphraseState = false;
@@ -1,10 +1,13 @@
1
1
  import { blake2s } from '@noble/hashes/blake2s';
2
2
  import { bytesToHex } from '@noble/hashes/utils';
3
+ import { createDeviceNotSupportMethodError } from '@onekeyfe/hd-shared';
3
4
 
4
5
  import { BaseMethod } from '../BaseMethod';
6
+ import { decodeJpegBase64ToRgba } from '../helpers/base64Data';
5
7
  import { invalidParameter } from '../helpers/filesystemValidation';
6
8
  import { writeProtocolV2File } from '../helpers/protocolV2FileWrite';
7
9
  import { UI_REQUEST, createUiMessage } from '../../events/ui-request';
10
+ import { supportsProtocolV2Message } from '../../protocols/protocol-v2/features';
8
11
  import {
9
12
  PRO2_WALLPAPER_HEIGHT,
10
13
  PRO2_WALLPAPER_WIDTH,
@@ -13,9 +16,7 @@ import {
13
16
  } from '../../utils/pro2Wallpaper';
14
17
 
15
18
  export type DeviceUploadWallpaperParams = {
16
- width: number;
17
- height: number;
18
- rgba: Uint8Array | ArrayBuffer;
19
+ jpegBase64: string;
19
20
  fileName?: string;
20
21
  chunkSize?: number;
21
22
  };
@@ -29,6 +30,9 @@ export type DeviceUploadWallpaperResponse = {
29
30
 
30
31
  const WALLPAPER_DIRECTORY = 'vol1:/wallpapers';
31
32
  const SAFE_FILE_NAME = /^[A-Za-z0-9_-]+(?:\.bin)?$/;
33
+ const DEVICE_SETTINGS_SET_MESSAGE_TYPE = 60412;
34
+ const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE = 60805;
35
+ const FILESYSTEM_DIR_MAKE_MESSAGE_TYPE = 60809;
32
36
 
33
37
  function normalizeFileName(fileName: string | undefined, data: Uint8Array): string {
34
38
  if (fileName !== undefined && (!fileName || !SAFE_FILE_NAME.test(fileName))) {
@@ -54,31 +58,45 @@ export default class DeviceUploadWallpaper extends BaseMethod<DeviceUploadWallpa
54
58
  private path = '';
55
59
 
56
60
  init() {
57
- const { width, height, rgba, fileName, chunkSize } = this.payload;
58
- if (width !== PRO2_WALLPAPER_WIDTH || height !== PRO2_WALLPAPER_HEIGHT) {
59
- throw invalidParameter(
60
- `Pro2 wallpaper dimensions must be ${PRO2_WALLPAPER_WIDTH}x${PRO2_WALLPAPER_HEIGHT}.`
61
- );
62
- }
63
- if (!(rgba instanceof ArrayBuffer) && !ArrayBuffer.isView(rgba)) {
64
- throw invalidParameter('Parameter [rgba] must be an ArrayBuffer or Uint8Array.');
65
- }
61
+ const { jpegBase64, fileName, chunkSize } = this.payload;
66
62
  if (chunkSize !== undefined && (!Number.isInteger(chunkSize) || chunkSize <= 0)) {
67
63
  throw invalidParameter('Parameter [chunkSize] must be a positive integer.');
68
64
  }
69
65
 
70
- const rgbaBytes =
71
- rgba instanceof ArrayBuffer
72
- ? rgba
73
- : new Uint8Array(rgba.buffer, rgba.byteOffset, rgba.byteLength);
74
- this.encoded = encodePro2Wallpaper({ width, height, rgba: rgbaBytes });
66
+ const decoded = decodeJpegBase64ToRgba({
67
+ jpegBase64,
68
+ parameterName: 'jpegBase64',
69
+ expectedWidth: PRO2_WALLPAPER_WIDTH,
70
+ expectedHeight: PRO2_WALLPAPER_HEIGHT,
71
+ });
72
+ this.encoded = encodePro2Wallpaper({
73
+ width: PRO2_WALLPAPER_WIDTH,
74
+ height: PRO2_WALLPAPER_HEIGHT,
75
+ rgba: decoded.data,
76
+ });
75
77
  this.path = `${WALLPAPER_DIRECTORY}/${normalizeFileName(fileName, this.encoded.data)}`;
76
- this.params = { width, height, rgba: rgbaBytes, fileName, chunkSize };
78
+ this.params = { jpegBase64, fileName, chunkSize };
77
79
  this.unlockPolicy = 'none';
78
80
  this.skipForceUpdateCheck = true;
79
81
  this.useDevicePassphraseState = false;
80
82
  }
81
83
 
84
+ private async assertCapabilities() {
85
+ const protocolInfo = await this.device.ensureProtocolV2RuntimeContext();
86
+ const requiredMessageTypes = [
87
+ DEVICE_SETTINGS_SET_MESSAGE_TYPE,
88
+ FILESYSTEM_FILE_WRITE_MESSAGE_TYPE,
89
+ FILESYSTEM_DIR_MAKE_MESSAGE_TYPE,
90
+ ];
91
+ if (
92
+ requiredMessageTypes.some(
93
+ messageType => !supportsProtocolV2Message(protocolInfo, messageType)
94
+ )
95
+ ) {
96
+ throw createDeviceNotSupportMethodError(this.name, this.device.getCurrentFirmwareType());
97
+ }
98
+ }
99
+
82
100
  private async ensureDirectory() {
83
101
  if (this.directoryReady) return;
84
102
  try {
@@ -119,6 +137,7 @@ export default class DeviceUploadWallpaper extends BaseMethod<DeviceUploadWallpa
119
137
  async run(): Promise<DeviceUploadWallpaperResponse> {
120
138
  const { encoded } = this;
121
139
  if (!encoded) throw invalidParameter('Wallpaper data has not been initialized.');
140
+ await this.assertCapabilities();
122
141
  await this.ensureDirectory();
123
142
  await this.upload();
124
143
  const response = await this.device.commands.typedCall('DeviceSettingsSet', 'Success', {
@@ -174,12 +174,14 @@ export default class TonSignMessage extends BaseMethod<HardwareTonSignMessage> {
174
174
  if (!request.init_data_length) {
175
175
  const deviceType = this.device.getCurrentDeviceType();
176
176
  const hasClassic = DeviceModelToTypes.model_classic1s.includes(deviceType);
177
- // use signing_message_repr sign, not exists signning_message, skip validate
178
- const hasSigningMessageRepr = request.signning_message == null;
177
+ const signingMessage = request.signing_message ?? request.signning_message;
178
+ // Blind signing omits the signing message in both protocol schemas.
179
+ const shouldSkipValidation = signingMessage == null;
179
180
 
180
181
  return Promise.resolve({
181
182
  ...request,
182
- skip_validate: hasClassic || hasSigningMessageRepr,
183
+ signing_message: signingMessage,
184
+ skip_validate: hasClassic || shouldSkipValidation,
183
185
  });
184
186
  }
185
187