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

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 (50) hide show
  1. package/__tests__/bridgeBinaryPayload.test.ts +173 -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__/get-device-state.test.ts +102 -13
  5. package/__tests__/protocol-v2-legacy-recovery.test.ts +29 -0
  6. package/__tests__/protocol-v2.test.ts +234 -1
  7. package/__tests__/refresh-device-state.test.ts +4 -1
  8. package/__tests__/search-devices.test.ts +2 -0
  9. package/__tests__/ton-sign-message.test.ts +84 -0
  10. package/dist/api/FirmwareUpdateV4.d.ts +3 -0
  11. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  12. package/dist/api/GetDeviceState.d.ts.map +1 -1
  13. package/dist/api/SearchDevices.d.ts.map +1 -1
  14. package/dist/api/firmware/protocolV2Release.d.ts.map +1 -1
  15. package/dist/api/ton/TonSignMessage.d.ts.map +1 -1
  16. package/dist/api/utils.d.ts.map +1 -1
  17. package/dist/core/index.d.ts.map +1 -1
  18. package/dist/core/protocolV2LegacyRecovery.d.ts +5 -0
  19. package/dist/core/protocolV2LegacyRecovery.d.ts.map +1 -0
  20. package/dist/device/Device.d.ts +9 -2
  21. package/dist/device/Device.d.ts.map +1 -1
  22. package/dist/device/DevicePool.d.ts +1 -1
  23. package/dist/device/DevicePool.d.ts.map +1 -1
  24. package/dist/index.d.ts +12 -2
  25. package/dist/index.js +243 -60
  26. package/dist/protocols/protocol-v2/features.d.ts +8 -0
  27. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  28. package/dist/protocols/protocol-v2/index.d.ts +2 -2
  29. package/dist/protocols/protocol-v2/index.d.ts.map +1 -1
  30. package/dist/topLevelInject.d.ts.map +1 -1
  31. package/dist/types/api/getDeviceState.d.ts +1 -0
  32. package/dist/types/api/getDeviceState.d.ts.map +1 -1
  33. package/dist/utils/bridgeBinaryPayload.d.ts +3 -0
  34. package/dist/utils/bridgeBinaryPayload.d.ts.map +1 -0
  35. package/package.json +4 -4
  36. package/src/api/FirmwareUpdateV4.ts +70 -23
  37. package/src/api/GetDeviceState.ts +1 -0
  38. package/src/api/SearchDevices.ts +2 -0
  39. package/src/api/firmware/protocolV2Release.ts +1 -0
  40. package/src/api/ton/TonSignMessage.ts +5 -3
  41. package/src/api/utils.ts +5 -2
  42. package/src/core/index.ts +4 -0
  43. package/src/core/protocolV2LegacyRecovery.ts +12 -0
  44. package/src/device/Device.ts +78 -20
  45. package/src/device/DevicePool.ts +17 -5
  46. package/src/protocols/protocol-v2/features.ts +10 -0
  47. package/src/protocols/protocol-v2/index.ts +2 -0
  48. package/src/topLevelInject.ts +4 -2
  49. package/src/types/api/getDeviceState.ts +2 -0
  50. package/src/utils/bridgeBinaryPayload.ts +137 -0
@@ -0,0 +1,137 @@
1
+ import { Buffer } from 'buffer';
2
+ import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
3
+
4
+ // Top-level and low-level SDK instances can be separated by JSON-only hosts,
5
+ // including browser extension background/offscreen message bridges.
6
+ const BRIDGE_BINARY_PAYLOAD_MARKER = '__onekey_hd_bridge_binary_payload__';
7
+
8
+ type BridgeBinaryPayload = {
9
+ [BRIDGE_BINARY_PAYLOAD_MARKER]: 1;
10
+ data: string;
11
+ type: 'array-buffer' | 'uint8-array';
12
+ };
13
+
14
+ const BASE64_PATTERN = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
15
+
16
+ const invalidBinaryPayload = (message: string) =>
17
+ ERRORS.TypedError(HardwareErrorCode.CallMethodInvalidParameter, message);
18
+
19
+ function isPlainObject(value: unknown): value is Record<string, unknown> {
20
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
21
+ const prototype = Object.getPrototypeOf(value);
22
+ return prototype === Object.prototype || prototype === null;
23
+ }
24
+
25
+ function isArrayBufferValue(value: unknown): value is ArrayBuffer {
26
+ return Boolean(
27
+ typeof ArrayBuffer !== 'undefined' &&
28
+ (value instanceof ArrayBuffer ||
29
+ Object.prototype.toString.call(value) === '[object ArrayBuffer]')
30
+ );
31
+ }
32
+
33
+ function isBlobValue(value: unknown): value is Blob {
34
+ return Boolean(
35
+ typeof Blob !== 'undefined' &&
36
+ (value instanceof Blob || Object.prototype.toString.call(value) === '[object Blob]') &&
37
+ typeof (value as Blob).arrayBuffer === 'function'
38
+ );
39
+ }
40
+
41
+ function readBinaryPayload(value: unknown): BridgeBinaryPayload | undefined {
42
+ if (!isPlainObject(value) || !(BRIDGE_BINARY_PAYLOAD_MARKER in value)) return undefined;
43
+ const payload = value as Partial<BridgeBinaryPayload>;
44
+ if (
45
+ payload[BRIDGE_BINARY_PAYLOAD_MARKER] !== 1 ||
46
+ (payload.type !== 'array-buffer' && payload.type !== 'uint8-array') ||
47
+ typeof payload.data !== 'string'
48
+ ) {
49
+ throw invalidBinaryPayload('Invalid bridge binary payload');
50
+ }
51
+ return payload as BridgeBinaryPayload;
52
+ }
53
+
54
+ function bytesToPayload(bytes: Uint8Array, type: BridgeBinaryPayload['type']): BridgeBinaryPayload {
55
+ return {
56
+ [BRIDGE_BINARY_PAYLOAD_MARKER]: 1,
57
+ data: Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString('base64'),
58
+ type,
59
+ };
60
+ }
61
+
62
+ function payloadToBytes(payload: BridgeBinaryPayload): Uint8Array {
63
+ if (payload.data.length % 4 !== 0 || !BASE64_PATTERN.test(payload.data)) {
64
+ throw invalidBinaryPayload('Invalid bridge binary payload data');
65
+ }
66
+ const decoded = Buffer.from(payload.data, 'base64');
67
+ if (decoded.toString('base64') !== payload.data) {
68
+ throw invalidBinaryPayload('Invalid bridge binary payload data');
69
+ }
70
+ return Uint8Array.from(decoded);
71
+ }
72
+
73
+ async function encodeValue(value: unknown, seen: WeakSet<object>): Promise<unknown> {
74
+ if (isArrayBufferValue(value)) {
75
+ return bytesToPayload(new Uint8Array(value), 'array-buffer');
76
+ }
77
+ if (typeof ArrayBuffer !== 'undefined' && ArrayBuffer.isView(value)) {
78
+ return bytesToPayload(
79
+ new Uint8Array(value.buffer, value.byteOffset, value.byteLength),
80
+ 'uint8-array'
81
+ );
82
+ }
83
+ if (isBlobValue(value)) {
84
+ return bytesToPayload(new Uint8Array(await value.arrayBuffer()), 'uint8-array');
85
+ }
86
+
87
+ const encodedPayload = readBinaryPayload(value);
88
+ if (encodedPayload) return encodedPayload;
89
+ if (Array.isArray(value)) {
90
+ if (seen.has(value)) throw invalidBinaryPayload('Circular bridge payload');
91
+ seen.add(value);
92
+ try {
93
+ const encoded: unknown[] = [];
94
+ for (const item of value) {
95
+ encoded.push(await encodeValue(item, seen));
96
+ }
97
+ return encoded.some((item, index) => item !== value[index]) ? encoded : value;
98
+ } finally {
99
+ seen.delete(value);
100
+ }
101
+ }
102
+ if (!isPlainObject(value)) return value;
103
+ if (seen.has(value)) throw invalidBinaryPayload('Circular bridge payload');
104
+ seen.add(value);
105
+ try {
106
+ const entries: [string, unknown][] = [];
107
+ for (const [key, item] of Object.entries(value)) {
108
+ entries.push([key, await encodeValue(item, seen)]);
109
+ }
110
+ return entries.some(([key, item]) => item !== value[key]) ? Object.fromEntries(entries) : value;
111
+ } finally {
112
+ seen.delete(value);
113
+ }
114
+ }
115
+
116
+ function decodeValue(value: unknown): unknown {
117
+ const payload = readBinaryPayload(value);
118
+ if (payload) {
119
+ const bytes = payloadToBytes(payload);
120
+ return payload.type === 'array-buffer' ? bytes.buffer : bytes;
121
+ }
122
+ if (Array.isArray(value)) {
123
+ const decoded = value.map(decodeValue);
124
+ return decoded.some((item, index) => item !== value[index]) ? decoded : value;
125
+ }
126
+ if (!isPlainObject(value)) return value;
127
+ const entries = Object.entries(value).map(([key, item]) => [key, decodeValue(item)] as const);
128
+ return entries.some(([key, item]) => item !== value[key]) ? Object.fromEntries(entries) : value;
129
+ }
130
+
131
+ export async function encodeBridgeBinaryPayload(value: unknown): Promise<unknown> {
132
+ return encodeValue(value, new WeakSet());
133
+ }
134
+
135
+ export function decodeBridgeBinaryPayload(value: unknown): unknown {
136
+ return decodeValue(value);
137
+ }