@onekeyfe/hd-core 1.2.2-alpha.14 → 1.2.2-alpha.17

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.
@@ -6,9 +6,9 @@ import {
6
6
  initConnector,
7
7
  initCore,
8
8
  isMissingDetectedProtocolV2Error,
9
- isProtocolV2PeerRemovedPairingError,
10
9
  isRetryableBleConnectionError,
11
10
  isRetryableBleProtocolV2ProbeError,
11
+ isTerminalBleStaleBondError,
12
12
  resolveBleConnectProtocol,
13
13
  } from '../src/core';
14
14
  import { DataManager } from '../src/data-manager';
@@ -378,22 +378,28 @@ describe('public device lifecycle events', () => {
378
378
  expect(isRetryableBleConnectionError(method, error)).toBe(expected);
379
379
  });
380
380
 
381
+ test('does not retry the desktop acquire deadline fallback', () => {
382
+ const method = { payload: { connectProtocol: 'V2' } } as never;
383
+ const error = {
384
+ errorCode: HardwareErrorCode.BleTimeoutError,
385
+ params: { acquireDeadlineExceeded: true },
386
+ };
387
+
388
+ expect(isRetryableBleConnectionError(method, error)).toBe(false);
389
+ });
390
+
381
391
  test.each([
382
- ['V2', HardwareErrorCode.BlePeerRemovedPairingInformation, true],
383
- ['V2', HardwareErrorCode.BleBondInvalid, true],
384
- ['V1', HardwareErrorCode.BleBondInvalid, false],
385
- [undefined, HardwareErrorCode.BleBondInvalid, false],
386
- ] as const)(
387
- 'treats stale pairing as terminal for Protocol %s with error code %s: %s',
388
- (connectProtocol, errorCode, expected) => {
389
- const method = { payload: { connectProtocol } } as never;
390
- const error = {
391
- errorCode,
392
- };
392
+ [HardwareErrorCode.BleDeviceBondError, true],
393
+ [HardwareErrorCode.BlePeerRemovedPairingInformation, true],
394
+ [HardwareErrorCode.BleBondInvalid, true],
395
+ [HardwareErrorCode.DeviceNotFound, false],
396
+ ] as const)('treats BLE stale-bond error code %s as terminal: %s', (errorCode, expected) => {
397
+ const error = {
398
+ errorCode,
399
+ };
393
400
 
394
- expect(isProtocolV2PeerRemovedPairingError(method, error)).toBe(expected);
395
- }
396
- );
401
+ expect(isTerminalBleStaleBondError(error)).toBe(expected);
402
+ });
397
403
 
398
404
  test('converts an internal transport disconnect into a public KnownDevice snapshot', () => {
399
405
  jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
@@ -555,7 +555,9 @@ describe('UploadPortfolio', () => {
555
555
  method.init();
556
556
  await method.run();
557
557
 
558
+ expect(method.unlockPolicy).toBe('none');
558
559
  expect(method.protocolV2UiMode).toBe('auto');
560
+ expect(method.protocolV2UiInteraction).toBeUndefined();
559
561
  expect(method.payload.emitProgress).toBe(true);
560
562
  expect(method.postMessage).toHaveBeenCalledWith({
561
563
  event: 'UI_EVENT',
@@ -0,0 +1,73 @@
1
+ import { SolanaOffChainMessageFormat, SolanaOffChainMessageVersion } from '@onekeyfe/hd-transport';
2
+
3
+ import SolSignOffchainMessage from '../src/api/solana/SolSignOffchainMessage';
4
+
5
+ import type { Device } from '../src/device/Device';
6
+
7
+ jest.mock('../src/data/config', () => ({
8
+ getSDKVersion: jest.fn(() => '1.0.0'),
9
+ DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0/',
10
+ }));
11
+
12
+ const signerA = '11'.repeat(32);
13
+ const signerB = '22'.repeat(32);
14
+
15
+ const createMethod = (overrides: Record<string, unknown> = {}) =>
16
+ new SolSignOffchainMessage({
17
+ id: 1,
18
+ payload: {
19
+ method: 'solSignOffchainMessage',
20
+ path: "m/44'/501'/0'/0'",
21
+ messageHex: '48656c6c6f',
22
+ messageVersion: SolanaOffChainMessageVersion.MESSAGE_VERSION_1,
23
+ messageFormat: SolanaOffChainMessageFormat.V0_LIMITED_UTF8,
24
+ applicationDomainHex: `0x${'aa'.repeat(32)}`,
25
+ sourceFingerprint: 0x12345678,
26
+ requiredSigners: [`0x${signerA.toUpperCase()}`, signerB],
27
+ ...overrides,
28
+ },
29
+ });
30
+
31
+ describe('SolSignOffchainMessage', () => {
32
+ test('maps V1 public parameters to Protocol V2 fields', async () => {
33
+ const method = createMethod();
34
+ method.init();
35
+
36
+ const typedCall = jest.fn().mockResolvedValue({
37
+ message: { signature: 'signature', public_key: signerA },
38
+ });
39
+ method.device = { commands: { typedCall } } as unknown as Device;
40
+
41
+ await expect(method.run()).resolves.toEqual({ signature: 'signature', pub: signerA });
42
+ expect(typedCall).toHaveBeenCalledWith('SolanaSignOffChainMessage', 'SolanaMessageSignature', {
43
+ address_n: [2147483692, 2147484149, 2147483648, 2147483648],
44
+ message: '48656c6c6f',
45
+ message_version: SolanaOffChainMessageVersion.MESSAGE_VERSION_1,
46
+ message_format: SolanaOffChainMessageFormat.V0_LIMITED_UTF8,
47
+ application_domain: 'aa'.repeat(32),
48
+ source_fingerprint: 0x12345678,
49
+ required_signers: [signerA, signerB],
50
+ });
51
+ });
52
+
53
+ test.each([
54
+ { requiredSigners: ['11'], error: '32-byte hex public key' },
55
+ { requiredSigners: [signerB, signerA], error: 'strictly sorted and unique' },
56
+ { requiredSigners: [signerA, signerA], error: 'strictly sorted and unique' },
57
+ {
58
+ requiredSigners: Array.from({ length: 11 }, (_, index) =>
59
+ index.toString(16).padStart(64, '0')
60
+ ),
61
+ error: 'at most 10 entries',
62
+ },
63
+ ])('rejects invalid required signers: $error', ({ requiredSigners, error }) => {
64
+ expect(() => createMethod({ requiredSigners }).init()).toThrow(error);
65
+ });
66
+
67
+ test.each([-1, 0x100000000, 1.5])(
68
+ 'rejects an invalid source fingerprint: %s',
69
+ sourceFingerprint => {
70
+ expect(() => createMethod({ sourceFingerprint }).init()).toThrow('uint32');
71
+ }
72
+ );
73
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"UploadPortfolio.d.ts","sourceRoot":"","sources":["../../src/api/UploadPortfolio.ts"],"names":[],"mappings":"AAIA,OAAO,SAAS,MAAM,aAAa,CAAC;AAEpC,MAAM,MAAM,qBAAqB,GAAG;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;CAChC,CAAC;AAQF,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,SAAS;IACpD,IAAI;IAuBE,GAAG;;;;;;;;CAsBV"}
1
+ {"version":3,"file":"UploadPortfolio.d.ts","sourceRoot":"","sources":["../../src/api/UploadPortfolio.ts"],"names":[],"mappings":"AAIA,OAAO,SAAS,MAAM,aAAa,CAAC;AAEpC,MAAM,MAAM,qBAAqB,GAAG;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAE5B,MAAM,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;CAChC,CAAC;AAQF,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,SAAS;IACpD,IAAI;IAuBE,GAAG;;;;;;;;CAsBV"}
@@ -1 +1 @@
1
- {"version":3,"file":"SolSignOffchainMessage.d.ts","sourceRoot":"","sources":["../../../src/api/solana/SolSignOffchainMessage.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAI3C,OAAO,KAAK,EAAE,yBAAyB,IAAI,8BAA8B,EAAE,MAAM,wBAAwB,CAAC;AAE1G,MAAM,CAAC,OAAO,OAAO,sBAAuB,SAAQ,UAAU,CAAC,8BAA8B,CAAC;IAC5F,qBAAqB;IAIrB,IAAI;IA2BJ,eAAe;;;;;;;;;;;IAcT,GAAG;;;;CAcV"}
1
+ {"version":3,"file":"SolSignOffchainMessage.d.ts","sourceRoot":"","sources":["../../../src/api/solana/SolSignOffchainMessage.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAI3C,OAAO,KAAK,EAAE,yBAAyB,IAAI,8BAA8B,EAAE,MAAM,wBAAwB,CAAC;AAmC1G,MAAM,CAAC,OAAO,OAAO,sBAAuB,SAAQ,UAAU,CAAC,8BAA8B,CAAC;IAC5F,qBAAqB;IAIrB,IAAI;IAqDJ,eAAe;;;;;;;;;;;IAcT,GAAG;;;;CAcV"}
@@ -11,7 +11,7 @@ export declare const callAPI: (context: CoreContext, message: CoreMessage) => Pr
11
11
  export declare function isRetryableBleProtocolV2ProbeError(method: BaseMethod, error: unknown): boolean;
12
12
  export declare function isRetryableBleConnectionError(method: BaseMethod, error: unknown): boolean;
13
13
  export declare function isMissingDetectedProtocolV2Error(method: BaseMethod, error: unknown): boolean;
14
- export declare function isProtocolV2PeerRemovedPairingError(method: BaseMethod, error: unknown): boolean;
14
+ export declare function isTerminalBleStaleBondError(error: unknown): boolean;
15
15
  export declare function resolveBleConnectProtocol(method: BaseMethod): ProtocolType | undefined;
16
16
  export declare const cancel: (context: CoreContext, connectId?: string) => void;
17
17
  export declare const onDeviceButtonHandler: (__0_0: Device, __0_1: import("../events").DeviceButtonRequestPayload) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":";AACA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAClC,OAAO,EAEL,KAAK,6BAA6B,EAElC,KAAK,YAAY,EAIlB,MAAM,wBAAwB,CAAC;AA+BhC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAsB1C,OAAO,eAAe,MAAM,2BAA2B,CAAC;AAYxD,OAAO,KAAK,EAAE,eAAe,EAAyB,MAAM,UAAU,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAmD,MAAM,WAAW,CAAC;AAI9F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAWpD,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;AA0E7D,eAAO,MAAM,OAAO,YAAmB,WAAW,WAAW,WAAW,iBAoFvE,CAAC;AAyqBF,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,WAWpF;AAED,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,WAW/E;AAED,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,WAQlF;AAED,wBAAgB,mCAAmC,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,WAOrF;AA6JD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,UAAU,GAAG,YAAY,GAAG,SAAS,CAMtF;AAwLD,eAAO,MAAM,MAAM,YAAa,WAAW,cAAc,MAAM,SA4G9D,CAAC;AA8GF,eAAO,MAAM,qBAAqB,gFAejC,CAAC;AAiLF,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,YAAY;IAC5C,OAAO,CAAC,cAAc,CAAoB;IAE1C,SAAgB,aAAa,EAAE,MAAM,CAAC;IAEtC,OAAO,CAAC,YAAY,CAAsB;IAE1C,OAAO,CAAC,cAAc,CAAC,CAAgB;IAGvC,OAAO,CAAC,sBAAsB,CAAoC;IAElE,OAAO,CAAC,iBAAiB,CAAoB;;IAS7C,OAAO,CAAC,cAAc;IA6BhB,aAAa,CAAC,OAAO,EAAE,WAAW;IAuExC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YAOV,gBAAgB;CAiC/B;AAED,eAAO,MAAM,QAAQ,YAIpB,CAAC;AAEF,eAAO,MAAM,aAAa,uBAYzB,CAAC;AAMF,eAAO,MAAM,IAAI,aACL,eAAe,aACd,GAAG,WACL,6BAA6B,8BAiBvC,CAAC;AAEF,eAAO,MAAM,eAAe;SAKrB,eAAe,CAAC,KAAK,CAAC;eAChB,GAAG;;UASf,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":";AACA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAClC,OAAO,EAEL,KAAK,6BAA6B,EAElC,KAAK,YAAY,EAIlB,MAAM,wBAAwB,CAAC;AAgChC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAsB1C,OAAO,eAAe,MAAM,2BAA2B,CAAC;AAYxD,OAAO,KAAK,EAAE,eAAe,EAAyB,MAAM,UAAU,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAmD,MAAM,WAAW,CAAC;AAI9F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAWpD,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;AA0E7D,eAAO,MAAM,OAAO,YAAmB,WAAW,WAAW,WAAW,iBAoFvE,CAAC;AAyqBF,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,WAWpF;AAED,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,WAoB/E;AAED,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,WAQlF;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,WAEzD;AA8JD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,UAAU,GAAG,YAAY,GAAG,SAAS,CAMtF;AAwLD,eAAO,MAAM,MAAM,YAAa,WAAW,cAAc,MAAM,SA4G9D,CAAC;AA8GF,eAAO,MAAM,qBAAqB,gFAejC,CAAC;AAiLF,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,YAAY;IAC5C,OAAO,CAAC,cAAc,CAAoB;IAE1C,SAAgB,aAAa,EAAE,MAAM,CAAC;IAEtC,OAAO,CAAC,YAAY,CAAsB;IAE1C,OAAO,CAAC,cAAc,CAAC,CAAgB;IAGvC,OAAO,CAAC,sBAAsB,CAAoC;IAElE,OAAO,CAAC,iBAAiB,CAAoB;;IAS7C,OAAO,CAAC,cAAc;IA6BhB,aAAa,CAAC,OAAO,EAAE,WAAW;IAuExC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YAOV,gBAAgB;CAiC/B;AAED,eAAO,MAAM,QAAQ,YAIpB,CAAC;AAEF,eAAO,MAAM,aAAa,uBAYzB,CAAC;AAMF,eAAO,MAAM,IAAI,aACL,eAAe,aACd,GAAG,WACL,6BAA6B,8BAiBvC,CAAC;AAEF,eAAO,MAAM,eAAe;SAKrB,eAAe,CAAC,KAAK,CAAC;eAChB,GAAG;;UASf,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1116,6 +1116,7 @@ declare const switchTransport: ({ env, Transport, plugin, }: {
1116
1116
  type UploadPortfolioParams = {
1117
1117
  packageBase64: string;
1118
1118
  timeoutMs?: number | string;
1119
+ /** Controls transfer progress UI events. Defaults to `silent`. */
1119
1120
  uiMode?: 'silent' | 'progress';
1120
1121
  };
1121
1122
 
@@ -2476,6 +2477,9 @@ type SolSignOffchainMessageParams = {
2476
2477
  messageVersion?: SolanaOffChainMessageVersion;
2477
2478
  messageFormat?: SolanaOffChainMessageFormat;
2478
2479
  applicationDomainHex?: string;
2480
+ sourceFingerprint?: number;
2481
+ /** 32-byte public keys encoded as hex, strictly sorted and unique. */
2482
+ requiredSigners?: string[];
2479
2483
  };
2480
2484
  declare function solSignOffchainMessage(connectId: string, deviceId: string, params: CommonParams & SolSignOffchainMessageParams): Response<SolSignOffchainMessageResponse>;
2481
2485
 
package/dist/index.js CHANGED
@@ -13203,7 +13203,8 @@ var nested$2 = {
13203
13203
  },
13204
13204
  SolanaOffChainMessageVersion: {
13205
13205
  values: {
13206
- MESSAGE_VERSION_0: 0
13206
+ MESSAGE_VERSION_0: 0,
13207
+ MESSAGE_VERSION_1: 1
13207
13208
  }
13208
13209
  },
13209
13210
  SolanaOffChainMessageFormat: {
@@ -13236,14 +13237,16 @@ var nested$2 = {
13236
13237
  },
13237
13238
  message_format: {
13238
13239
  type: "SolanaOffChainMessageFormat",
13239
- id: 4,
13240
- options: {
13241
- "default": "V0_RESTRICTED_ASCII"
13242
- }
13240
+ id: 4
13243
13241
  },
13244
13242
  application_domain: {
13245
13243
  type: "bytes",
13246
13244
  id: 5
13245
+ },
13246
+ required_signers: {
13247
+ rule: "repeated",
13248
+ type: "bytes",
13249
+ id: 7
13247
13250
  }
13248
13251
  }
13249
13252
  },
@@ -36027,7 +36030,8 @@ var nested = {
36027
36030
  },
36028
36031
  SolanaOffChainMessageVersion: {
36029
36032
  values: {
36030
- MESSAGE_VERSION_0: 0
36033
+ MESSAGE_VERSION_0: 0,
36034
+ MESSAGE_VERSION_1: 1
36031
36035
  }
36032
36036
  },
36033
36037
  SolanaOffChainMessageFormat: {
@@ -36115,10 +36119,7 @@ var nested = {
36115
36119
  },
36116
36120
  message_format: {
36117
36121
  type: "SolanaOffChainMessageFormat",
36118
- id: 4,
36119
- options: {
36120
- "default": "V0_RESTRICTED_ASCII"
36121
- }
36122
+ id: 4
36122
36123
  },
36123
36124
  application_domain: {
36124
36125
  type: "bytes",
@@ -36127,6 +36128,11 @@ var nested = {
36127
36128
  source_fingerprint: {
36128
36129
  type: "uint32",
36129
36130
  id: 6
36131
+ },
36132
+ required_signers: {
36133
+ rule: "repeated",
36134
+ type: "bytes",
36135
+ id: 7
36130
36136
  }
36131
36137
  }
36132
36138
  },
@@ -59463,6 +59469,29 @@ class SolSignTransaction extends BaseMethod {
59463
59469
  }
59464
59470
  }
59465
59471
 
59472
+ const SOLANA_PUBLIC_KEY_LENGTH = 32;
59473
+ const SOLANA_APPLICATION_DOMAIN_LENGTH = 32;
59474
+ const MAX_REQUIRED_SIGNERS = 10;
59475
+ const normalizeRequiredSigners = (requiredSigners) => {
59476
+ if (!requiredSigners)
59477
+ return undefined;
59478
+ if (requiredSigners.length > MAX_REQUIRED_SIGNERS) {
59479
+ throw invalidParameter(`Parameter [requiredSigners] supports at most ${MAX_REQUIRED_SIGNERS} entries.`);
59480
+ }
59481
+ const normalized = requiredSigners.map((signer, index) => {
59482
+ if (typeof signer !== 'string' ||
59483
+ !isHexString(addHexPrefix(signer), SOLANA_PUBLIC_KEY_LENGTH)) {
59484
+ throw invalidParameter(`Parameter [requiredSigners][${index}] must be a ${SOLANA_PUBLIC_KEY_LENGTH}-byte hex public key.`);
59485
+ }
59486
+ return stripHexPrefix(signer).toLowerCase();
59487
+ });
59488
+ for (let index = 1; index < normalized.length; index += 1) {
59489
+ if (normalized[index - 1] >= normalized[index]) {
59490
+ throw invalidParameter('Parameter [requiredSigners] must be strictly sorted and unique.');
59491
+ }
59492
+ }
59493
+ return normalized;
59494
+ };
59466
59495
  class SolSignOffchainMessage extends BaseMethod {
59467
59496
  getSupportedProtocols() {
59468
59497
  return ['V1', 'V2'];
@@ -59477,15 +59506,29 @@ class SolSignOffchainMessage extends BaseMethod {
59477
59506
  { name: 'messageVersion', type: 'number', required: false },
59478
59507
  { name: 'messageFormat', type: 'number', required: false },
59479
59508
  { name: 'applicationDomainHex', type: 'hexString', required: false },
59509
+ { name: 'sourceFingerprint', type: 'number', required: false },
59510
+ { name: 'requiredSigners', type: 'array', required: false, allowEmpty: true },
59480
59511
  ]);
59481
- const { path, messageHex, messageVersion, messageFormat, applicationDomainHex } = this.payload;
59512
+ const { path, messageHex, messageVersion, messageFormat, applicationDomainHex, sourceFingerprint, requiredSigners, } = this.payload;
59482
59513
  const addressN = validatePath(path, 3);
59514
+ if (sourceFingerprint !== undefined &&
59515
+ (!Number.isInteger(sourceFingerprint) ||
59516
+ sourceFingerprint < 0 ||
59517
+ sourceFingerprint > 0xffffffff)) {
59518
+ throw invalidParameter('Parameter [sourceFingerprint] must be a uint32 number.');
59519
+ }
59520
+ if (applicationDomainHex !== undefined &&
59521
+ !isHexString(addHexPrefix(applicationDomainHex), SOLANA_APPLICATION_DOMAIN_LENGTH)) {
59522
+ throw invalidParameter('Parameter [applicationDomainHex] must be 32 bytes.');
59523
+ }
59483
59524
  this.params = {
59484
59525
  address_n: addressN,
59485
59526
  message: stripHexPrefix(messageHex),
59486
59527
  message_version: messageVersion !== null && messageVersion !== void 0 ? messageVersion : undefined,
59487
59528
  message_format: messageFormat !== null && messageFormat !== void 0 ? messageFormat : undefined,
59488
- application_domain: applicationDomainHex !== null && applicationDomainHex !== void 0 ? applicationDomainHex : undefined,
59529
+ application_domain: applicationDomainHex ? stripHexPrefix(applicationDomainHex) : undefined,
59530
+ source_fingerprint: sourceFingerprint !== null && sourceFingerprint !== void 0 ? sourceFingerprint : undefined,
59531
+ required_signers: normalizeRequiredSigners(requiredSigners),
59489
59532
  };
59490
59533
  }
59491
59534
  getVersionRange() {
@@ -66329,11 +66372,15 @@ function isRetryableBleProtocolV2ProbeError(method, error) {
66329
66372
  message.includes('did not respond to expected protocol'));
66330
66373
  }
66331
66374
  function isRetryableBleConnectionError(method, error) {
66332
- var _a;
66375
+ var _a, _b;
66333
66376
  if ((_a = method.device) === null || _a === void 0 ? void 0 : _a.wasInterruptedByUser()) {
66334
66377
  return false;
66335
66378
  }
66336
66379
  const typedError = error;
66380
+ if ((typedError === null || typedError === void 0 ? void 0 : typedError.errorCode) === hdShared.HardwareErrorCode.BleTimeoutError &&
66381
+ ((_b = typedError.params) === null || _b === void 0 ? void 0 : _b.acquireDeadlineExceeded) === true) {
66382
+ return false;
66383
+ }
66337
66384
  return ((typedError === null || typedError === void 0 ? void 0 : typedError.errorCode) === hdShared.HardwareErrorCode.BleTimeoutError ||
66338
66385
  (typedError === null || typedError === void 0 ? void 0 : typedError.errorCode) === hdShared.HardwareErrorCode.BleConnectedError ||
66339
66386
  isRetryableBleProtocolV2ProbeError(method, error) ||
@@ -66346,11 +66393,8 @@ function isMissingDetectedProtocolV2Error(method, error) {
66346
66393
  typeof typedError.message === 'string' &&
66347
66394
  typedError.message.includes('Device protocol has not been detected'));
66348
66395
  }
66349
- function isProtocolV2PeerRemovedPairingError(method, error) {
66350
- const errorCode = error === null || error === void 0 ? void 0 : error.errorCode;
66351
- return (method.payload.connectProtocol === 'V2' &&
66352
- (errorCode === hdShared.HardwareErrorCode.BlePeerRemovedPairingInformation ||
66353
- errorCode === hdShared.HardwareErrorCode.BleBondInvalid));
66396
+ function isTerminalBleStaleBondError(error) {
66397
+ return hdShared.isBleStaleBondHardwareError(error);
66354
66398
  }
66355
66399
  const BLE_ACQUIRE_DEADLINE_MS = 60 * 1000;
66356
66400
  function raceBleAcquire(acquirePromise, abortSignal) {
@@ -66365,7 +66409,7 @@ function raceBleAcquire(acquirePromise, abortSignal) {
66365
66409
  fn();
66366
66410
  };
66367
66411
  const onAbort = () => settle(() => reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled)));
66368
- const deadline = setTimeout(() => settle(() => reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, `BLE acquire exceeded ${BLE_ACQUIRE_DEADLINE_MS}ms deadline`))), BLE_ACQUIRE_DEADLINE_MS);
66412
+ const deadline = setTimeout(() => settle(() => reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, `BLE acquire exceeded ${BLE_ACQUIRE_DEADLINE_MS}ms deadline`, { acquireDeadlineExceeded: true }))), BLE_ACQUIRE_DEADLINE_MS);
66369
66413
  acquirePromise.then(value => settle(() => resolve(value)), error => settle(() => reject(error)));
66370
66414
  if (abortSignal) {
66371
66415
  if (abortSignal.aborted) {
@@ -66582,7 +66626,7 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
66582
66626
  hdShared.HardwareErrorCode.DeviceInterruptedFromUser,
66583
66627
  hdShared.HardwareErrorCode.CallQueueActionCancelled,
66584
66628
  ].includes(error.errorCode) ||
66585
- isProtocolV2PeerRemovedPairingError(method, error)) {
66629
+ isTerminalBleStaleBondError(error)) {
66586
66630
  reject(error);
66587
66631
  return;
66588
66632
  }
@@ -10,6 +10,8 @@ export type SolSignOffchainMessageParams = {
10
10
  messageVersion?: SolanaOffChainMessageVersion;
11
11
  messageFormat?: SolanaOffChainMessageFormat;
12
12
  applicationDomainHex?: string;
13
+ sourceFingerprint?: number;
14
+ requiredSigners?: string[];
13
15
  };
14
16
  export declare function solSignOffchainMessage(connectId: string, deviceId: string, params: CommonParams & SolSignOffchainMessageParams): Response<SolSignOffchainMessageResponse>;
15
17
  //# sourceMappingURL=solSignOffchainMessage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"solSignOffchainMessage.d.ts","sourceRoot":"","sources":["../../../src/types/api/solSignOffchainMessage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,2BAA2B,EAC3B,4BAA4B,EAC7B,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAExD,MAAM,MAAM,8BAA8B,GAAG;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,4BAA4B,CAAC;IAC9C,aAAa,CAAC,EAAE,2BAA2B,CAAC;IAC5C,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,sBAAsB,CAC5C,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,YAAY,GAAG,4BAA4B,GAClD,QAAQ,CAAC,8BAA8B,CAAC,CAAC"}
1
+ {"version":3,"file":"solSignOffchainMessage.d.ts","sourceRoot":"","sources":["../../../src/types/api/solSignOffchainMessage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,2BAA2B,EAC3B,4BAA4B,EAC7B,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAExD,MAAM,MAAM,8BAA8B,GAAG;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,4BAA4B,CAAC;IAC9C,aAAa,CAAC,EAAE,2BAA2B,CAAC;IAC5C,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,sBAAsB,CAC5C,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,YAAY,GAAG,4BAA4B,GAClD,QAAQ,CAAC,8BAA8B,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-core",
3
- "version": "1.2.2-alpha.14",
3
+ "version": "1.2.2-alpha.17",
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,8 +25,8 @@
25
25
  "url": "https://github.com/OneKeyHQ/hardware-js-sdk/issues"
26
26
  },
27
27
  "dependencies": {
28
- "@onekeyfe/hd-shared": "1.2.2-alpha.14",
29
- "@onekeyfe/hd-transport": "1.2.2-alpha.14",
28
+ "@onekeyfe/hd-shared": "1.2.2-alpha.17",
29
+ "@onekeyfe/hd-transport": "1.2.2-alpha.17",
30
30
  "axios": "1.15.2",
31
31
  "bignumber.js": "^9.0.2",
32
32
  "buffer": "^6.0.3",
@@ -46,5 +46,5 @@
46
46
  "@types/w3c-web-usb": "^1.0.10",
47
47
  "@types/web-bluetooth": "^0.0.21"
48
48
  },
49
- "gitHead": "1b3bf0576a53bedbc5f4a82308c48e11ffc00b16"
49
+ "gitHead": "b6c48b842d1c325dcd5ce42c03a07ee4377002dd"
50
50
  }
@@ -7,6 +7,7 @@ import FileWrite from './FileWrite';
7
7
  export type UploadPortfolioParams = {
8
8
  packageBase64: string;
9
9
  timeoutMs?: number | string;
10
+ /** Controls transfer progress UI events. Defaults to `silent`. */
10
11
  uiMode?: 'silent' | 'progress';
11
12
  };
12
13
 
@@ -1,11 +1,44 @@
1
1
  import { UI_REQUEST } from '../../constants/ui-request';
2
2
  import { validatePath } from '../helpers/pathUtils';
3
3
  import { BaseMethod } from '../BaseMethod';
4
- import { validateParams } from '../helpers/paramsValidator';
5
- import { stripHexPrefix } from '../helpers/hexUtils';
4
+ import { invalidParameter, validateParams } from '../helpers/paramsValidator';
5
+ import { addHexPrefix, isHexString, stripHexPrefix } from '../helpers/hexUtils';
6
6
 
7
7
  import type { SolanaSignOffChainMessage as HardwareSolSignOffChainMessage } from '@onekeyfe/hd-transport';
8
8
 
9
+ const SOLANA_PUBLIC_KEY_LENGTH = 32;
10
+ const SOLANA_APPLICATION_DOMAIN_LENGTH = 32;
11
+ const MAX_REQUIRED_SIGNERS = 10;
12
+
13
+ const normalizeRequiredSigners = (requiredSigners?: unknown[]): string[] | undefined => {
14
+ if (!requiredSigners) return undefined;
15
+ if (requiredSigners.length > MAX_REQUIRED_SIGNERS) {
16
+ throw invalidParameter(
17
+ `Parameter [requiredSigners] supports at most ${MAX_REQUIRED_SIGNERS} entries.`
18
+ );
19
+ }
20
+
21
+ const normalized = requiredSigners.map((signer, index) => {
22
+ if (
23
+ typeof signer !== 'string' ||
24
+ !isHexString(addHexPrefix(signer), SOLANA_PUBLIC_KEY_LENGTH)
25
+ ) {
26
+ throw invalidParameter(
27
+ `Parameter [requiredSigners][${index}] must be a ${SOLANA_PUBLIC_KEY_LENGTH}-byte hex public key.`
28
+ );
29
+ }
30
+ return stripHexPrefix(signer).toLowerCase();
31
+ });
32
+
33
+ for (let index = 1; index < normalized.length; index += 1) {
34
+ if (normalized[index - 1] >= normalized[index]) {
35
+ throw invalidParameter('Parameter [requiredSigners] must be strictly sorted and unique.');
36
+ }
37
+ }
38
+
39
+ return normalized;
40
+ };
41
+
9
42
  export default class SolSignOffchainMessage extends BaseMethod<HardwareSolSignOffChainMessage> {
10
43
  getSupportedProtocols() {
11
44
  return ['V1', 'V2'] as const;
@@ -23,10 +56,34 @@ export default class SolSignOffchainMessage extends BaseMethod<HardwareSolSignOf
23
56
  { name: 'messageVersion', type: 'number', required: false },
24
57
  { name: 'messageFormat', type: 'number', required: false },
25
58
  { name: 'applicationDomainHex', type: 'hexString', required: false },
59
+ { name: 'sourceFingerprint', type: 'number', required: false },
60
+ { name: 'requiredSigners', type: 'array', required: false, allowEmpty: true },
26
61
  ]);
27
62
 
28
- const { path, messageHex, messageVersion, messageFormat, applicationDomainHex } = this.payload;
63
+ const {
64
+ path,
65
+ messageHex,
66
+ messageVersion,
67
+ messageFormat,
68
+ applicationDomainHex,
69
+ sourceFingerprint,
70
+ requiredSigners,
71
+ } = this.payload;
29
72
  const addressN = validatePath(path, 3);
73
+ if (
74
+ sourceFingerprint !== undefined &&
75
+ (!Number.isInteger(sourceFingerprint) ||
76
+ sourceFingerprint < 0 ||
77
+ sourceFingerprint > 0xffffffff)
78
+ ) {
79
+ throw invalidParameter('Parameter [sourceFingerprint] must be a uint32 number.');
80
+ }
81
+ if (
82
+ applicationDomainHex !== undefined &&
83
+ !isHexString(addHexPrefix(applicationDomainHex), SOLANA_APPLICATION_DOMAIN_LENGTH)
84
+ ) {
85
+ throw invalidParameter('Parameter [applicationDomainHex] must be 32 bytes.');
86
+ }
30
87
 
31
88
  // init params
32
89
  this.params = {
@@ -34,7 +91,9 @@ export default class SolSignOffchainMessage extends BaseMethod<HardwareSolSignOf
34
91
  message: stripHexPrefix(messageHex),
35
92
  message_version: messageVersion ?? undefined,
36
93
  message_format: messageFormat ?? undefined,
37
- application_domain: applicationDomainHex ?? undefined,
94
+ application_domain: applicationDomainHex ? stripHexPrefix(applicationDomainHex) : undefined,
95
+ source_fingerprint: sourceFingerprint ?? undefined,
96
+ required_signers: normalizeRequiredSigners(requiredSigners),
38
97
  };
39
98
  }
40
99
 
package/src/core/index.ts CHANGED
@@ -22,6 +22,7 @@ import {
22
22
  createNeedUpgradeFirmwareHardwareError,
23
23
  createNewFirmwareForceUpdateHardwareError,
24
24
  createNewFirmwareUnReleaseHardwareError,
25
+ isBleStaleBondHardwareError,
25
26
  } from '@onekeyfe/hd-shared';
26
27
 
27
28
  import { LoggerNames, enableLog, getLogger, setLoggerPostMessage, wait } from '../utils';
@@ -945,7 +946,16 @@ export function isRetryableBleConnectionError(method: BaseMethod, error: unknown
945
946
  if (method.device?.wasInterruptedByUser()) {
946
947
  return false;
947
948
  }
948
- const typedError = error as { errorCode?: unknown };
949
+ const typedError = error as {
950
+ errorCode?: unknown;
951
+ params?: { acquireDeadlineExceeded?: unknown };
952
+ };
953
+ if (
954
+ typedError?.errorCode === HardwareErrorCode.BleTimeoutError &&
955
+ typedError.params?.acquireDeadlineExceeded === true
956
+ ) {
957
+ return false;
958
+ }
949
959
  return (
950
960
  typedError?.errorCode === HardwareErrorCode.BleTimeoutError ||
951
961
  typedError?.errorCode === HardwareErrorCode.BleConnectedError ||
@@ -964,13 +974,8 @@ export function isMissingDetectedProtocolV2Error(method: BaseMethod, error: unkn
964
974
  );
965
975
  }
966
976
 
967
- export function isProtocolV2PeerRemovedPairingError(method: BaseMethod, error: unknown) {
968
- const errorCode = (error as { errorCode?: unknown })?.errorCode;
969
- return (
970
- method.payload.connectProtocol === 'V2' &&
971
- (errorCode === HardwareErrorCode.BlePeerRemovedPairingInformation ||
972
- errorCode === HardwareErrorCode.BleBondInvalid)
973
- );
977
+ export function isTerminalBleStaleBondError(error: unknown) {
978
+ return isBleStaleBondHardwareError(error);
974
979
  }
975
980
 
976
981
  /**
@@ -1002,7 +1007,8 @@ function raceBleAcquire<T>(acquirePromise: Promise<T>, abortSignal?: AbortSignal
1002
1007
  reject(
1003
1008
  ERRORS.TypedError(
1004
1009
  HardwareErrorCode.BleTimeoutError,
1005
- `BLE acquire exceeded ${BLE_ACQUIRE_DEADLINE_MS}ms deadline`
1010
+ `BLE acquire exceeded ${BLE_ACQUIRE_DEADLINE_MS}ms deadline`,
1011
+ { acquireDeadlineExceeded: true }
1006
1012
  )
1007
1013
  )
1008
1014
  ),
@@ -1284,7 +1290,7 @@ const ensureConnected = async (
1284
1290
  HardwareErrorCode.DeviceInterruptedFromUser,
1285
1291
  HardwareErrorCode.CallQueueActionCancelled,
1286
1292
  ].includes(error.errorCode) ||
1287
- isProtocolV2PeerRemovedPairingError(method, error)
1293
+ isTerminalBleStaleBondError(error)
1288
1294
  ) {
1289
1295
  reject(error);
1290
1296
  return;
@@ -8968,7 +8968,8 @@
8968
8968
  },
8969
8969
  "SolanaOffChainMessageVersion": {
8970
8970
  "values": {
8971
- "MESSAGE_VERSION_0": 0
8971
+ "MESSAGE_VERSION_0": 0,
8972
+ "MESSAGE_VERSION_1": 1
8972
8973
  }
8973
8974
  },
8974
8975
  "SolanaOffChainMessageFormat": {
@@ -9056,10 +9057,7 @@
9056
9057
  },
9057
9058
  "message_format": {
9058
9059
  "type": "SolanaOffChainMessageFormat",
9059
- "id": 4,
9060
- "options": {
9061
- "default": "V0_RESTRICTED_ASCII"
9062
- }
9060
+ "id": 4
9063
9061
  },
9064
9062
  "application_domain": {
9065
9063
  "type": "bytes",
@@ -9068,6 +9066,11 @@
9068
9066
  "source_fingerprint": {
9069
9067
  "type": "uint32",
9070
9068
  "id": 6
9069
+ },
9070
+ "required_signers": {
9071
+ "rule": "repeated",
9072
+ "type": "bytes",
9073
+ "id": 7
9071
9074
  }
9072
9075
  }
9073
9076
  },
@@ -10243,7 +10243,8 @@
10243
10243
  },
10244
10244
  "SolanaOffChainMessageVersion": {
10245
10245
  "values": {
10246
- "MESSAGE_VERSION_0": 0
10246
+ "MESSAGE_VERSION_0": 0,
10247
+ "MESSAGE_VERSION_1": 1
10247
10248
  }
10248
10249
  },
10249
10250
  "SolanaOffChainMessageFormat": {
@@ -10276,14 +10277,16 @@
10276
10277
  },
10277
10278
  "message_format": {
10278
10279
  "type": "SolanaOffChainMessageFormat",
10279
- "id": 4,
10280
- "options": {
10281
- "default": "V0_RESTRICTED_ASCII"
10282
- }
10280
+ "id": 4
10283
10281
  },
10284
10282
  "application_domain": {
10285
10283
  "type": "bytes",
10286
10284
  "id": 5
10285
+ },
10286
+ "required_signers": {
10287
+ "rule": "repeated",
10288
+ "type": "bytes",
10289
+ "id": 7
10287
10290
  }
10288
10291
  }
10289
10292
  },
@@ -15,6 +15,9 @@ export type SolSignOffchainMessageParams = {
15
15
  messageVersion?: SolanaOffChainMessageVersion;
16
16
  messageFormat?: SolanaOffChainMessageFormat;
17
17
  applicationDomainHex?: string;
18
+ sourceFingerprint?: number;
19
+ /** 32-byte public keys encoded as hex, strictly sorted and unique. */
20
+ requiredSigners?: string[];
18
21
  };
19
22
 
20
23
  export declare function solSignOffchainMessage(