@onekeyfe/hd-core 1.2.8-alpha.100 → 1.2.8-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 (53) hide show
  1. package/__tests__/core-dispose.test.ts +114 -1
  2. package/__tests__/core-error-output.test.ts +21 -0
  3. package/__tests__/device-connector-protocol.test.ts +5 -2
  4. package/__tests__/device-lifecycle-events.test.ts +22 -3
  5. package/__tests__/logBlockEvent.test.ts +0 -43
  6. package/__tests__/usb-identity-probe.test.ts +358 -0
  7. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  8. package/dist/api/SearchDevices.d.ts +21 -1
  9. package/dist/api/SearchDevices.d.ts.map +1 -1
  10. package/dist/api/index.d.ts +0 -2
  11. package/dist/api/index.d.ts.map +1 -1
  12. package/dist/core/index.d.ts +3 -1
  13. package/dist/core/index.d.ts.map +1 -1
  14. package/dist/device/DeviceCommands.d.ts +4 -4
  15. package/dist/events/logBlockEvent.d.ts.map +1 -1
  16. package/dist/index.d.ts +37 -39
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +3060 -3229
  19. package/dist/inject.d.ts.map +1 -1
  20. package/dist/types/api/export.d.ts +0 -2
  21. package/dist/types/api/export.d.ts.map +1 -1
  22. package/dist/types/api/index.d.ts +0 -4
  23. package/dist/types/api/index.d.ts.map +1 -1
  24. package/dist/types/device.d.ts +9 -0
  25. package/dist/types/device.d.ts.map +1 -1
  26. package/dist/utils/patch.d.ts +1 -1
  27. package/dist/utils/patch.d.ts.map +1 -1
  28. package/package.json +4 -4
  29. package/src/api/FirmwareUpdateV4.ts +4 -7
  30. package/src/api/SearchDevices.ts +172 -7
  31. package/src/api/index.ts +0 -2
  32. package/src/core/index.ts +45 -14
  33. package/src/data/messages/messages-protocol-v2.json +1 -138
  34. package/src/device/DeviceConnector.ts +4 -4
  35. package/src/events/logBlockEvent.ts +2 -5
  36. package/src/index.ts +1 -0
  37. package/src/inject.ts +0 -4
  38. package/src/types/api/export.ts +0 -2
  39. package/src/types/api/index.ts +0 -8
  40. package/src/types/device.ts +12 -0
  41. package/__tests__/zcash-sign-pczt.test.ts +0 -212
  42. package/dist/api/zcash/ZcashGetAddress.d.ts +0 -12
  43. package/dist/api/zcash/ZcashGetAddress.d.ts.map +0 -1
  44. package/dist/api/zcash/ZcashSignPczt.d.ts +0 -17
  45. package/dist/api/zcash/ZcashSignPczt.d.ts.map +0 -1
  46. package/dist/types/api/zcashGetAddress.d.ts +0 -22
  47. package/dist/types/api/zcashGetAddress.d.ts.map +0 -1
  48. package/dist/types/api/zcashSignPczt.d.ts +0 -9
  49. package/dist/types/api/zcashSignPczt.d.ts.map +0 -1
  50. package/src/api/zcash/ZcashGetAddress.ts +0 -121
  51. package/src/api/zcash/ZcashSignPczt.ts +0 -153
  52. package/src/types/api/zcashGetAddress.ts +0 -36
  53. package/src/types/api/zcashSignPczt.ts +0 -18
@@ -1,212 +0,0 @@
1
- import ZcashSignPczt, { ZCASH_PCZT_MAX_BYTES } from '../src/api/zcash/ZcashSignPczt';
2
- import ZcashGetAddress from '../src/api/zcash/ZcashGetAddress';
3
-
4
- import type { Device } from '../src/device/Device';
5
-
6
- jest.mock('../src/data/config', () => ({
7
- getSDKVersion: jest.fn(() => '1.0.0'),
8
- DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0/',
9
- }));
10
-
11
- const hex = (byte: number, length: number) => byte.toString(16).padStart(2, '0').repeat(length);
12
-
13
- const createSignMethod = (pczt: string) =>
14
- new ZcashSignPczt({ id: 1, payload: { method: 'zcashSignPczt', pczt } });
15
-
16
- const attachDevice = (method: ZcashSignPczt | ZcashGetAddress, typedCall: jest.Mock) => {
17
- const commands = { typedCall };
18
- method.device = {
19
- commands,
20
- getCommands: () => commands,
21
- toMessageObject: () => ({}),
22
- } as unknown as Device;
23
- method.postMessage = jest.fn();
24
- };
25
-
26
- describe('ZcashSignPczt', () => {
27
- test('uploads device-sized chunks and downloads host-sized chunks', async () => {
28
- // 2500 bytes: initial 1024, then device asks 1000 + 476.
29
- const pczt = hex(0xab, 2500);
30
- const signed = Buffer.alloc(1500, 0xcd);
31
- const method = createSignMethod(pczt);
32
- method.init();
33
-
34
- const typedCall = jest
35
- .fn()
36
- .mockResolvedValueOnce({ type: 'ZcashPcztChunkRequest', message: { chunk_length: 1000 } })
37
- .mockResolvedValueOnce({ type: 'ZcashPcztChunkRequest', message: { chunk_length: 476 } })
38
- .mockResolvedValueOnce({
39
- type: 'ZcashSignedPczt',
40
- message: {
41
- pczt_length: signed.length,
42
- pczt_initial_chunk: signed.subarray(0, 1024).toString('hex'),
43
- },
44
- })
45
- .mockResolvedValueOnce({
46
- type: 'ZcashPcztChunkAck',
47
- message: { data_chunk: signed.subarray(1024).toString('hex') },
48
- });
49
- attachDevice(method, typedCall);
50
-
51
- await expect(method.run()).resolves.toEqual({ pczt: signed.toString('hex') });
52
-
53
- expect(typedCall.mock.calls[0]).toEqual([
54
- 'ZcashSignPczt',
55
- ['ZcashSignedPczt', 'ZcashPcztChunkRequest'],
56
- { pczt_length: 2500, pczt_initial_chunk: hex(0xab, 1024) },
57
- ]);
58
- expect(typedCall.mock.calls[1]).toEqual([
59
- 'ZcashPcztChunkAck',
60
- ['ZcashSignedPczt', 'ZcashPcztChunkRequest'],
61
- { data_chunk: hex(0xab, 1000) },
62
- ]);
63
- expect(typedCall.mock.calls[2][2]).toEqual({ data_chunk: hex(0xab, 476) });
64
- expect(typedCall.mock.calls[3]).toEqual([
65
- 'ZcashSignedPcztChunkRequest',
66
- 'ZcashPcztChunkAck',
67
- { chunk_length: 476 },
68
- ]);
69
- expect(typedCall).toHaveBeenCalledTimes(4);
70
- });
71
-
72
- test('single-message round trip when both sides fit in the initial chunk', async () => {
73
- const method = createSignMethod(hex(0x01, 100));
74
- method.init();
75
- const typedCall = jest.fn().mockResolvedValueOnce({
76
- type: 'ZcashSignedPczt',
77
- message: { pczt_length: 80, pczt_initial_chunk: hex(0x02, 80) },
78
- });
79
- attachDevice(method, typedCall);
80
-
81
- await expect(method.run()).resolves.toEqual({ pczt: hex(0x02, 80) });
82
- expect(typedCall).toHaveBeenCalledTimes(1);
83
- });
84
-
85
- test('rejects a device chunk request past the end of the pczt', async () => {
86
- const method = createSignMethod(hex(0x01, 1100));
87
- method.init();
88
- const typedCall = jest
89
- .fn()
90
- .mockResolvedValueOnce({ type: 'ZcashPcztChunkRequest', message: { chunk_length: 200 } });
91
- attachDevice(method, typedCall);
92
-
93
- await expect(method.run()).rejects.toThrow('device requested 200 bytes at offset 1024');
94
- });
95
-
96
- test('rejects completion before the entire input has been uploaded', async () => {
97
- const method = createSignMethod(hex(0x01, 1100));
98
- method.init();
99
- const typedCall = jest.fn().mockResolvedValueOnce({
100
- type: 'ZcashSignedPczt',
101
- message: { pczt_length: 80, pczt_initial_chunk: hex(0x02, 80) },
102
- });
103
- attachDevice(method, typedCall);
104
- await expect(method.run()).rejects.toThrow('before receiving the whole pczt');
105
- expect(typedCall).toHaveBeenCalledTimes(1);
106
- });
107
-
108
- test('rejects an initial signed chunk larger than its announced total', async () => {
109
- const method = createSignMethod(hex(0x01, 100));
110
- method.init();
111
- const typedCall = jest.fn().mockResolvedValueOnce({
112
- type: 'ZcashSignedPczt',
113
- message: { pczt_length: 80, pczt_initial_chunk: hex(0x02, 81) },
114
- });
115
- attachDevice(method, typedCall);
116
- await expect(method.run()).rejects.toThrow('more initial pczt bytes than announced');
117
- expect(typedCall).toHaveBeenCalledTimes(1);
118
- });
119
-
120
- test('rejects oversized and empty input', () => {
121
- expect(() => createSignMethod('').init()).toThrow();
122
- expect(() => createSignMethod(hex(0x00, ZCASH_PCZT_MAX_BYTES + 1)).init()).toThrow('exceeds');
123
- expect(() => createSignMethod(hex(0x00, ZCASH_PCZT_MAX_BYTES)).init()).not.toThrow();
124
- });
125
- });
126
-
127
- describe('ZcashGetAddress', () => {
128
- test('maps params and response', async () => {
129
- const method = new ZcashGetAddress({
130
- id: 1,
131
- payload: {
132
- method: 'zcashGetAddress',
133
- path: "m/32'/133'/0'",
134
- showOnOneKey: false,
135
- includeUfvk: true,
136
- includeSeedFingerprint: true,
137
- },
138
- });
139
- method.init();
140
- const typedCall = jest.fn().mockResolvedValue({
141
- message: { address: 'u1abc', ufvk: 'uview1abc', seed_fingerprint: hex(0x0f, 32) },
142
- });
143
- attachDevice(method, typedCall);
144
-
145
- await expect(method.run()).resolves.toEqual({
146
- path: "m/32'/133'/0'",
147
- address: 'u1abc',
148
- ufvk: 'uview1abc',
149
- seedFingerprint: hex(0x0f, 32),
150
- });
151
- expect(typedCall).toHaveBeenCalledWith('ZcashGetAddress', 'ZcashAddress', {
152
- address_n: [2147483680, 2147483781, 2147483648],
153
- address_type: 0,
154
- scope: 0,
155
- diversifier_index: 0,
156
- show_display: false,
157
- include_ufvk: true,
158
- include_seed_fingerprint: true,
159
- });
160
- });
161
- });
162
-
163
- describe('Zcash address protocol selection', () => {
164
- const createAddress = (params: Record<string, unknown> = {}) =>
165
- new ZcashGetAddress({
166
- id: 1,
167
- payload: { method: 'zcashGetAddress', path: "m/32'/133'/0'", ...params },
168
- });
169
- test('supports only Pro2 and protocol V2', () => {
170
- for (const method of [createAddress(), createSignMethod(hex(1, 1))]) {
171
- method.init();
172
- expect(method.supportsProtocol('V1')).toBe(false);
173
- expect(method.supportsProtocol('V2')).toBe(true);
174
- expect(method.strictCheckDeviceSupport).toBe(true);
175
- expect(Object.keys(method.getVersionRange())).toEqual(['model_pro2']);
176
- }
177
- });
178
- test.each([0, 1, 2])('maps address type %s with internal scope and index', async addressType => {
179
- const method = createAddress({ addressType, scope: 1, diversifierIndex: 37 });
180
- method.init();
181
- const typedCall = jest.fn().mockResolvedValue({ message: { address: 'device-address' } });
182
- attachDevice(method, typedCall);
183
- await method.run();
184
- expect(typedCall).toHaveBeenCalledWith(
185
- 'ZcashGetAddress',
186
- 'ZcashAddress',
187
- expect.objectContaining({
188
- address_type: addressType,
189
- scope: 1,
190
- diversifier_index: 37,
191
- show_display: true,
192
- })
193
- );
194
- });
195
- test.each([
196
- { addressType: 3 },
197
- { scope: 2 },
198
- { diversifierIndex: -1 },
199
- { diversifierIndex: 1.5 },
200
- { diversifierIndex: 0x80000000 },
201
- { addressType: 2, diversifierIndex: 0x100000000 },
202
- { path: "m/44'/133'/0'" },
203
- { path: "m/32'/133'/0'/0/0" },
204
- ])('rejects invalid address requests %j', params => {
205
- expect(() => createAddress(params).init()).toThrow();
206
- });
207
- test('accepts the uint32 limit only for an Orchard-only address', () => {
208
- expect(() =>
209
- createAddress({ addressType: 2, diversifierIndex: 0xffffffff }).init()
210
- ).not.toThrow();
211
- });
212
- });
@@ -1,12 +0,0 @@
1
- import { BaseMethod } from '../BaseMethod';
2
- import type { ZcashGetAddress as HardwareZcashGetAddress } from '@onekeyfe/hd-transport';
3
- import type { ZcashAddress } from '../../types/api/zcashGetAddress';
4
- import type { DeviceFirmwareRange } from '../../types';
5
- export default class ZcashGetAddress extends BaseMethod<HardwareZcashGetAddress[]> {
6
- hasBundle: boolean;
7
- getSupportedProtocols(): readonly ["V2"];
8
- init(): void;
9
- getVersionRange(): DeviceFirmwareRange;
10
- run(): Promise<ZcashAddress | ZcashAddress[]>;
11
- }
12
- //# sourceMappingURL=ZcashGetAddress.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ZcashGetAddress.d.ts","sourceRoot":"","sources":["../../../src/api/zcash/ZcashGetAddress.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAK3C,OAAO,KAAK,EAAE,eAAe,IAAI,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACzF,OAAO,KAAK,EAAyB,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC3F,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,UAAU,CAAC,uBAAuB,EAAE,CAAC;IAChF,SAAS,UAAS;IAElB,qBAAqB;IAIrB,IAAI;IAgEJ,eAAe,IAAI,mBAAmB;IAQhC,GAAG;CA8BV"}
@@ -1,17 +0,0 @@
1
- /// <reference types="node" />
2
- import { BaseMethod } from '../BaseMethod';
3
- import type { ZcashSignPczt as HardwareZcashSignPczt } from '@onekeyfe/hd-transport';
4
- import type { TypedCall, TypedResponseMessage } from '../../device/DeviceCommands';
5
- import type { ZcashSignedPczt } from '../../types/api/zcashSignPczt';
6
- import type { DeviceFirmwareRange } from '../../types';
7
- export declare const ZCASH_PCZT_MAX_BYTES: number;
8
- export default class ZcashSignPczt extends BaseMethod<HardwareZcashSignPczt> {
9
- pczt: Buffer;
10
- getSupportedProtocols(): readonly ["V2"];
11
- init(): void;
12
- getVersionRange(): DeviceFirmwareRange;
13
- uploadPczt: (typedCall: TypedCall, res: TypedResponseMessage<'ZcashSignedPczt'> | TypedResponseMessage<'ZcashPcztChunkRequest'>, offset: number) => Promise<TypedResponseMessage<'ZcashSignedPczt'>>;
14
- downloadSignedPczt: (typedCall: TypedCall, res: TypedResponseMessage<'ZcashSignedPczt'>) => Promise<Buffer>;
15
- run(): Promise<ZcashSignedPczt>;
16
- }
17
- //# sourceMappingURL=ZcashSignPczt.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ZcashSignPczt.d.ts","sourceRoot":"","sources":["../../../src/api/zcash/ZcashSignPczt.ts"],"names":[],"mappings":";AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAK3C,OAAO,KAAK,EAAE,aAAa,IAAI,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AACrF,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGvD,eAAO,MAAM,oBAAoB,QAAY,CAAC;AAG9C,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,UAAU,CAAC,qBAAqB,CAAC;IAC1E,IAAI,EAAE,MAAM,CAAmB;IAE/B,qBAAqB;IAIrB,IAAI;IAqBJ,eAAe,IAAI,mBAAmB;IAUtC,UAAU,cACG,SAAS,OACf,qBAAqB,iBAAiB,CAAC,GAAG,qBAAqB,uBAAuB,CAAC,UACpF,MAAM,KACb,QAAQ,qBAAqB,iBAAiB,CAAC,CAAC,CAiCjD;IAIF,kBAAkB,cACL,SAAS,OACf,qBAAqB,iBAAiB,CAAC,KAC3C,QAAQ,MAAM,CAAC,CAmChB;IAEI,GAAG,IAAI,OAAO,CAAC,eAAe,CAAC;CAgBtC"}
@@ -1,22 +0,0 @@
1
- import type { ZcashAddressScope, ZcashAddressType } from '@onekeyfe/hd-transport';
2
- import type { CommonParams, Response } from '../params';
3
- export type ZcashAddress = {
4
- path: string;
5
- address: string;
6
- ufvk?: string;
7
- seedFingerprint?: string;
8
- };
9
- export type ZcashGetAddressParams = {
10
- path: string | number[];
11
- showOnOneKey?: boolean;
12
- diversifierIndex?: number;
13
- addressType?: ZcashAddressType;
14
- scope?: ZcashAddressScope;
15
- includeUfvk?: boolean;
16
- includeSeedFingerprint?: boolean;
17
- };
18
- export declare function zcashGetAddress(connectId: string, deviceId: string, params: CommonParams & ZcashGetAddressParams): Response<ZcashAddress>;
19
- export declare function zcashGetAddress(connectId: string, deviceId: string, params: CommonParams & {
20
- bundle?: ZcashGetAddressParams[];
21
- }): Response<Array<ZcashAddress>>;
22
- //# sourceMappingURL=zcashGetAddress.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"zcashGetAddress.d.ts","sourceRoot":"","sources":["../../../src/types/api/zcashGetAddress.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAElF,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAExD,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IAEb,OAAO,EAAE,MAAM,CAAC;IAEhB,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAElC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAC/B,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,eAAe,CACrC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,YAAY,GAAG,qBAAqB,GAC3C,QAAQ,CAAC,YAAY,CAAC,CAAC;AAE1B,MAAM,CAAC,OAAO,UAAU,eAAe,CACrC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,YAAY,GAAG;IAAE,MAAM,CAAC,EAAE,qBAAqB,EAAE,CAAA;CAAE,GAC1D,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC"}
@@ -1,9 +0,0 @@
1
- import type { CommonParams, Response } from '../params';
2
- export type ZcashSignPcztParams = {
3
- pczt: string;
4
- };
5
- export type ZcashSignedPczt = {
6
- pczt: string;
7
- };
8
- export declare function zcashSignPczt(connectId: string, deviceId: string, params: CommonParams & ZcashSignPcztParams): Response<ZcashSignedPczt>;
9
- //# sourceMappingURL=zcashSignPczt.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"zcashSignPczt.d.ts","sourceRoot":"","sources":["../../../src/types/api/zcashSignPczt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAExD,MAAM,MAAM,mBAAmB,GAAG;IAGhC,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAE5B,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,aAAa,CACnC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,YAAY,GAAG,mBAAmB,GACzC,QAAQ,CAAC,eAAe,CAAC,CAAC"}
@@ -1,121 +0,0 @@
1
- import { ZcashAddressScope, ZcashAddressType } from '@onekeyfe/hd-transport';
2
-
3
- import { BaseMethod } from '../BaseMethod';
4
- import { serializedPath, toHardened, validatePath } from '../helpers/pathUtils';
5
- import { invalidParameter, validateParams, validateResult } from '../helpers/paramsValidator';
6
- import { UI_REQUEST } from '../../constants/ui-request';
7
-
8
- import type { ZcashGetAddress as HardwareZcashGetAddress } from '@onekeyfe/hd-transport';
9
- import type { ZcashGetAddressParams, ZcashAddress } from '../../types/api/zcashGetAddress';
10
- import type { DeviceFirmwareRange } from '../../types';
11
-
12
- export default class ZcashGetAddress extends BaseMethod<HardwareZcashGetAddress[]> {
13
- hasBundle = false;
14
-
15
- getSupportedProtocols() {
16
- return ['V2'] as const;
17
- }
18
-
19
- init() {
20
- this.checkDeviceId = true;
21
- this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
22
- this.strictCheckDeviceSupport = true;
23
-
24
- this.hasBundle = !!this.payload?.bundle;
25
- const payload = this.hasBundle ? this.payload : { bundle: [this.payload] };
26
-
27
- validateParams(payload, [{ name: 'bundle', type: 'array' }]);
28
-
29
- this.params = [];
30
- payload.bundle.forEach((batch: ZcashGetAddressParams) => {
31
- // ZIP-32 account path: m/32'/133'/account'
32
- const addressN = validatePath(batch.path, 3);
33
- if (
34
- addressN.length !== 3 ||
35
- addressN[0] !== toHardened(32) ||
36
- addressN[1] !== toHardened(133) ||
37
- addressN[2] < toHardened(0) ||
38
- addressN[2] > 0xffffffff
39
- ) {
40
- throw invalidParameter("Zcash requires a ZIP-32 account path m/32'/133'/account'");
41
- }
42
- const addressType = batch.addressType ?? ZcashAddressType.UNIFIED_ORCHARD_P2PKH;
43
- const scope = batch.scope ?? ZcashAddressScope.EXTERNAL;
44
- const diversifierIndex = batch.diversifierIndex ?? 0;
45
- if (
46
- ![
47
- ZcashAddressType.UNIFIED_ORCHARD_P2PKH,
48
- ZcashAddressType.TRANSPARENT_P2PKH,
49
- ZcashAddressType.UNIFIED_ORCHARD,
50
- ].includes(addressType) ||
51
- ![ZcashAddressScope.EXTERNAL, ZcashAddressScope.INTERNAL].includes(scope)
52
- ) {
53
- throw invalidParameter('Invalid Zcash address type or scope');
54
- }
55
- const maxIndex = addressType === ZcashAddressType.UNIFIED_ORCHARD ? 0xffffffff : 0x7fffffff;
56
- if (
57
- !Number.isSafeInteger(diversifierIndex) ||
58
- diversifierIndex < 0 ||
59
- diversifierIndex > maxIndex
60
- ) {
61
- throw invalidParameter('Invalid Zcash diversifier index');
62
- }
63
-
64
- validateParams(batch, [
65
- { name: 'path', required: true },
66
- { name: 'showOnOneKey', type: 'boolean' },
67
- { name: 'includeUfvk', type: 'boolean' },
68
- { name: 'includeSeedFingerprint', type: 'boolean' },
69
- ]);
70
-
71
- this.params.push({
72
- address_n: addressN,
73
- address_type: addressType,
74
- scope,
75
- diversifier_index: diversifierIndex,
76
- show_display: batch.showOnOneKey ?? true,
77
- include_ufvk: batch.includeUfvk ?? false,
78
- include_seed_fingerprint: batch.includeSeedFingerprint ?? false,
79
- });
80
- });
81
- }
82
-
83
- getVersionRange(): DeviceFirmwareRange {
84
- return {
85
- model_pro2: {
86
- min: '0.0.0',
87
- },
88
- };
89
- }
90
-
91
- async run() {
92
- const responses: ZcashAddress[] = [];
93
-
94
- for (let i = 0; i < this.params.length; i++) {
95
- const param = this.params[i];
96
-
97
- const res = await this.device.commands.typedCall('ZcashGetAddress', 'ZcashAddress', {
98
- ...param,
99
- });
100
-
101
- const path = serializedPath(param.address_n);
102
- responses.push({
103
- path,
104
- address: res.message.address,
105
- ufvk: res.message.ufvk,
106
- seedFingerprint: res.message.seed_fingerprint,
107
- });
108
-
109
- this.postPreviousAddressMessage({
110
- address: res.message.address,
111
- path,
112
- });
113
- }
114
-
115
- validateResult(responses, ['address'], {
116
- expectedLength: this.params.length,
117
- });
118
-
119
- return Promise.resolve(this.hasBundle ? responses : responses[0]);
120
- }
121
- }
@@ -1,153 +0,0 @@
1
- import { bytesToHex } from '@noble/hashes/utils';
2
- import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
3
-
4
- import { BaseMethod } from '../BaseMethod';
5
- import { invalidParameter, validateParams } from '../helpers/paramsValidator';
6
- import { formatAnyHex } from '../helpers/hexUtils';
7
- import { UI_REQUEST } from '../../constants/ui-request';
8
-
9
- import type { ZcashSignPczt as HardwareZcashSignPczt } from '@onekeyfe/hd-transport';
10
- import type { TypedCall, TypedResponseMessage } from '../../device/DeviceCommands';
11
- import type { ZcashSignedPczt } from '../../types/api/zcashSignPczt';
12
- import type { DeviceFirmwareRange } from '../../types';
13
-
14
- // Firmware buffers the whole PCZT in RAM in both directions.
15
- export const ZCASH_PCZT_MAX_BYTES = 24 * 1024;
16
- const CHUNK_BYTE_SIZE = 1024;
17
-
18
- export default class ZcashSignPczt extends BaseMethod<HardwareZcashSignPczt> {
19
- pczt: Buffer = Buffer.alloc(0);
20
-
21
- getSupportedProtocols() {
22
- return ['V2'] as const;
23
- }
24
-
25
- init() {
26
- this.checkDeviceId = true;
27
- this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
28
- this.strictCheckDeviceSupport = true;
29
-
30
- validateParams(this.payload, [{ name: 'pczt', type: 'hexString', required: true }]);
31
-
32
- this.pczt = Buffer.from(formatAnyHex(this.payload.pczt), 'hex');
33
- if (this.pczt.length === 0) {
34
- throw invalidParameter('pczt is empty');
35
- }
36
- if (this.pczt.length > ZCASH_PCZT_MAX_BYTES) {
37
- throw invalidParameter(`pczt exceeds ${ZCASH_PCZT_MAX_BYTES} bytes (${this.pczt.length})`);
38
- }
39
-
40
- this.params = {
41
- pczt_length: this.pczt.length,
42
- pczt_initial_chunk: bytesToHex(this.pczt.subarray(0, CHUNK_BYTE_SIZE)),
43
- };
44
- }
45
-
46
- getVersionRange(): DeviceFirmwareRange {
47
- return {
48
- model_pro2: {
49
- min: '0.0.0',
50
- },
51
- };
52
- }
53
-
54
- // Upload: the device decides every chunk length via ZcashPcztChunkRequest and
55
- // the host must answer with exactly that many bytes.
56
- uploadPczt = async (
57
- typedCall: TypedCall,
58
- res: TypedResponseMessage<'ZcashSignedPczt'> | TypedResponseMessage<'ZcashPcztChunkRequest'>,
59
- offset: number
60
- ): Promise<TypedResponseMessage<'ZcashSignedPczt'>> => {
61
- if (res.type === 'ZcashSignedPczt') {
62
- if (offset !== this.pczt.length) {
63
- throw ERRORS.TypedError(
64
- HardwareErrorCode.ResponseUnexpectTypeError,
65
- 'device completed signing before receiving the whole pczt'
66
- );
67
- }
68
- return res;
69
- }
70
-
71
- const { chunk_length: chunkLength } = res.message;
72
- if (
73
- !Number.isSafeInteger(chunkLength) ||
74
- chunkLength <= 0 ||
75
- offset + chunkLength > this.pczt.length
76
- ) {
77
- throw ERRORS.TypedError(
78
- HardwareErrorCode.ResponseUnexpectTypeError,
79
- `device requested ${chunkLength} bytes at offset ${offset} of ${this.pczt.length}`
80
- );
81
- }
82
-
83
- const chunk = this.pczt.subarray(offset, offset + chunkLength);
84
- const next = await typedCall(
85
- 'ZcashPcztChunkAck',
86
- ['ZcashSignedPczt', 'ZcashPcztChunkRequest'],
87
- {
88
- data_chunk: bytesToHex(chunk),
89
- }
90
- );
91
-
92
- return this.uploadPczt(typedCall, next, offset + chunkLength);
93
- };
94
-
95
- // Download: the host decides chunk lengths via ZcashSignedPcztChunkRequest
96
- // until the announced pczt_length has been received.
97
- downloadSignedPczt = async (
98
- typedCall: TypedCall,
99
- res: TypedResponseMessage<'ZcashSignedPczt'>
100
- ): Promise<Buffer> => {
101
- const { pczt_length: total, pczt_initial_chunk: initial } = res.message;
102
- if (!Number.isSafeInteger(total) || total <= 0 || total > ZCASH_PCZT_MAX_BYTES) {
103
- throw ERRORS.TypedError(
104
- HardwareErrorCode.ResponseUnexpectTypeError,
105
- `device announced invalid signed pczt length ${total}`
106
- );
107
- }
108
-
109
- const parts: Buffer[] = [Buffer.from(initial ?? '', 'hex')];
110
- let received = parts[0].length;
111
- if (received > total) {
112
- throw ERRORS.TypedError(
113
- HardwareErrorCode.ResponseUnexpectTypeError,
114
- 'device returned more initial pczt bytes than announced'
115
- );
116
- }
117
-
118
- while (received < total) {
119
- const chunkLength = Math.min(CHUNK_BYTE_SIZE, total - received);
120
- const ack = await typedCall('ZcashSignedPcztChunkRequest', 'ZcashPcztChunkAck', {
121
- chunk_length: chunkLength,
122
- });
123
- const chunk = Buffer.from(ack.message.data_chunk ?? '', 'hex');
124
- if (chunk.length === 0 || received + chunk.length > total) {
125
- throw ERRORS.TypedError(
126
- HardwareErrorCode.ResponseUnexpectTypeError,
127
- `device returned ${chunk.length} bytes at offset ${received} of ${total}`
128
- );
129
- }
130
- parts.push(chunk);
131
- received += chunk.length;
132
- }
133
-
134
- return Buffer.concat(parts);
135
- };
136
-
137
- async run(): Promise<ZcashSignedPczt> {
138
- const typedCall = this.device.getCommands().typedCall.bind(this.device.getCommands());
139
-
140
- const first = await typedCall('ZcashSignPczt', ['ZcashSignedPczt', 'ZcashPcztChunkRequest'], {
141
- ...this.params,
142
- });
143
-
144
- const signed = await this.uploadPczt(
145
- typedCall,
146
- first,
147
- Math.min(CHUNK_BYTE_SIZE, this.pczt.length)
148
- );
149
- const pczt = await this.downloadSignedPczt(typedCall, signed);
150
-
151
- return { pczt: bytesToHex(pczt) };
152
- }
153
- }
@@ -1,36 +0,0 @@
1
- import type { ZcashAddressScope, ZcashAddressType } from '@onekeyfe/hd-transport';
2
-
3
- import type { CommonParams, Response } from '../params';
4
-
5
- export type ZcashAddress = {
6
- path: string;
7
- // ZIP-316 unified address or transparent P2PKH address
8
- address: string;
9
- // ZIP-316 unified full viewing key, present when includeUfvk was requested
10
- ufvk?: string;
11
- // ZIP-32 seed fingerprint (hex), present when includeSeedFingerprint was requested
12
- seedFingerprint?: string;
13
- };
14
-
15
- export type ZcashGetAddressParams = {
16
- // ZIP-32 account path, m/32'/133'/account'
17
- path: string | number[];
18
- showOnOneKey?: boolean;
19
- diversifierIndex?: number;
20
- addressType?: ZcashAddressType;
21
- scope?: ZcashAddressScope;
22
- includeUfvk?: boolean;
23
- includeSeedFingerprint?: boolean;
24
- };
25
-
26
- export declare function zcashGetAddress(
27
- connectId: string,
28
- deviceId: string,
29
- params: CommonParams & ZcashGetAddressParams
30
- ): Response<ZcashAddress>;
31
-
32
- export declare function zcashGetAddress(
33
- connectId: string,
34
- deviceId: string,
35
- params: CommonParams & { bundle?: ZcashGetAddressParams[] }
36
- ): Response<Array<ZcashAddress>>;
@@ -1,18 +0,0 @@
1
- import type { CommonParams, Response } from '../params';
2
-
3
- export type ZcashSignPcztParams = {
4
- // Unproved PCZT (v2, tx v6) as hex; the device signs it and returns a
5
- // redacted copy with signatures filled in.
6
- pczt: string;
7
- };
8
-
9
- export type ZcashSignedPczt = {
10
- // Signed, redacted PCZT as hex
11
- pczt: string;
12
- };
13
-
14
- export declare function zcashSignPczt(
15
- connectId: string,
16
- deviceId: string,
17
- params: CommonParams & ZcashSignPcztParams
18
- ): Response<ZcashSignedPczt>;