@onekeyfe/hd-core 1.2.2-alpha.9 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +503 -10
- package/__tests__/DeviceCommands.test.ts +254 -1
- package/__tests__/core-error-output.test.ts +169 -1
- package/__tests__/device-lifecycle-events.test.ts +395 -15
- package/__tests__/logBlockEvent.test.ts +45 -122
- package/__tests__/open-wallet-session-error-response.test.ts +2 -2
- package/__tests__/open-wallet-session.test.ts +8 -358
- package/__tests__/protocol-v2.test.ts +130 -0
- package/__tests__/public-device-state-api.test.ts +2 -7
- package/__tests__/search-devices.test.ts +196 -8
- package/__tests__/sol-sign-offchain-message.test.ts +64 -0
- package/dist/api/FirmwareUpdateV4.d.ts +1 -0
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/GetFeatures.d.ts.map +1 -1
- package/dist/api/GetPassphraseState.d.ts.map +1 -1
- package/dist/api/OpenWalletSession.d.ts.map +1 -1
- package/dist/api/SearchDevices.d.ts +2 -15
- package/dist/api/SearchDevices.d.ts.map +1 -1
- package/dist/api/UploadPortfolio.d.ts +1 -0
- package/dist/api/UploadPortfolio.d.ts.map +1 -1
- package/dist/api/allnetwork/AllNetworkGetAddress.d.ts +2 -0
- package/dist/api/allnetwork/AllNetworkGetAddress.d.ts.map +1 -1
- package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts +7 -1
- package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
- package/dist/api/allnetwork/AllNetworkGetAddressByLoop.d.ts.map +1 -1
- package/dist/api/device/DeviceVerify.d.ts.map +1 -1
- package/dist/api/solana/SolSignOffchainMessage.d.ts.map +1 -1
- package/dist/core/RequestQueue.d.ts +1 -0
- package/dist/core/RequestQueue.d.ts.map +1 -1
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/uiPromiseRegistry.d.ts +1 -1
- package/dist/data-manager/TransportManager.d.ts +2 -0
- package/dist/data-manager/TransportManager.d.ts.map +1 -1
- package/dist/device/Device.d.ts +2 -0
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts +5 -4
- package/dist/device/DeviceCommands.d.ts.map +1 -1
- package/dist/events/logBlockEvent.d.ts.map +1 -1
- package/dist/index.d.ts +35 -30
- package/dist/index.js +587 -314
- package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
- package/dist/types/api/getFeatures.d.ts.map +1 -1
- package/dist/types/api/getPassphraseState.d.ts.map +1 -1
- package/dist/types/api/openWalletSession.d.ts +1 -10
- package/dist/types/api/openWalletSession.d.ts.map +1 -1
- package/dist/types/api/protocolV2.d.ts +3 -4
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/api/solSignOffchainMessage.d.ts +1 -0
- package/dist/types/api/solSignOffchainMessage.d.ts.map +1 -1
- package/dist/types/params.d.ts.map +1 -1
- package/dist/utils/patch.d.ts +1 -1
- package/dist/utils/patch.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/FirmwareUpdateV4.ts +9 -4
- package/src/api/GetFeatures.ts +1 -0
- package/src/api/GetPassphraseState.ts +1 -0
- package/src/api/OpenWalletSession.ts +7 -77
- package/src/api/SearchDevices.ts +121 -27
- package/src/api/UploadPortfolio.ts +5 -4
- package/src/api/allnetwork/AllNetworkGetAddress.ts +79 -45
- package/src/api/allnetwork/AllNetworkGetAddressBase.ts +95 -24
- package/src/api/allnetwork/AllNetworkGetAddressByLoop.ts +3 -0
- package/src/api/device/DeviceVerify.ts +8 -0
- package/src/api/solana/SolSignOffchainMessage.ts +44 -4
- package/src/core/RequestQueue.ts +20 -0
- package/src/core/index.ts +159 -52
- package/src/data/messages/messages-protocol-v2.json +49 -33
- package/src/data/messages/messages.json +8 -5
- package/src/data-manager/TransportManager.ts +14 -3
- package/src/device/Device.ts +58 -27
- package/src/device/DeviceCommands.ts +29 -2
- package/src/events/logBlockEvent.ts +6 -75
- package/src/protocols/protocol-v2/walletSession.ts +14 -2
- package/src/types/api/getFeatures.ts +2 -1
- package/src/types/api/getPassphraseState.ts +2 -5
- package/src/types/api/openWalletSession.ts +7 -19
- package/src/types/api/protocolV2.ts +3 -4
- package/src/types/api/solSignOffchainMessage.ts +2 -0
- package/src/types/params.ts +7 -0
package/src/device/Device.ts
CHANGED
|
@@ -297,6 +297,8 @@ export class Device extends EventEmitter {
|
|
|
297
297
|
/** Resolves only after the active run has completed its release path. */
|
|
298
298
|
private runCleanupPromise?: Promise<void>;
|
|
299
299
|
|
|
300
|
+
private userInterruption?: { attempt: number; promise: Promise<void> };
|
|
301
|
+
|
|
300
302
|
externalState: string[] = [];
|
|
301
303
|
|
|
302
304
|
unavailableCapabilities: UnavailableCapabilities = {};
|
|
@@ -1462,6 +1464,10 @@ export class Device extends EventEmitter {
|
|
|
1462
1464
|
this.invalidateProtocolV2RuntimeState();
|
|
1463
1465
|
}
|
|
1464
1466
|
|
|
1467
|
+
waitForRunCleanup(): Promise<void> {
|
|
1468
|
+
return this.runCleanupPromise ?? Promise.resolve();
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1465
1471
|
async run(fn?: () => Promise<void>, options?: RunOptions) {
|
|
1466
1472
|
if (this.runPromise) {
|
|
1467
1473
|
await this.interruptionFromOutside();
|
|
@@ -1596,45 +1602,70 @@ export class Device extends EventEmitter {
|
|
|
1596
1602
|
}
|
|
1597
1603
|
}
|
|
1598
1604
|
|
|
1599
|
-
|
|
1605
|
+
interruptionFromUser(): Promise<void> {
|
|
1606
|
+
const attempt = this.connectionAttempt;
|
|
1607
|
+
if (this.userInterruption?.attempt === attempt) {
|
|
1608
|
+
return this.userInterruption.promise;
|
|
1609
|
+
}
|
|
1600
1610
|
const error = ERRORS.TypedError(HardwareErrorCode.DeviceInterruptedFromUser);
|
|
1601
|
-
this.interruptedAttempt =
|
|
1611
|
+
this.interruptedAttempt = attempt;
|
|
1602
1612
|
const cleanupPromise = this.runCleanupPromise;
|
|
1603
|
-
const { cancelableAction } = this;
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1613
|
+
const { cancelableAction, commands, runPromise, deviceConnector, mainId } = this;
|
|
1614
|
+
const sendFallbackCancel = this.shouldSendFallbackProtocolCancel();
|
|
1615
|
+
const acquired = this.hasDeviceAcquire();
|
|
1616
|
+
const promise = (async () => {
|
|
1617
|
+
try {
|
|
1618
|
+
if (cancelableAction) {
|
|
1619
|
+
await cancelableAction(error);
|
|
1620
|
+
} else if (sendFallbackCancel) {
|
|
1621
|
+
await commands?.cancelDevice?.().catch(cancelError => {
|
|
1622
|
+
Log.debug('Protocol V2 fallback cancel error', cancelError);
|
|
1623
|
+
});
|
|
1624
|
+
} else if (!acquired) {
|
|
1625
|
+
// Abort setup without acquiring a session just to send Cancel.
|
|
1626
|
+
if (mainId && deviceConnector?.disconnect) {
|
|
1627
|
+
// The connector drops the link silently, so without this line a
|
|
1628
|
+
// user-cancel teardown is indistinguishable in field logs from an
|
|
1629
|
+
// idle keep-alive release or a device that left on its own.
|
|
1630
|
+
Log.debug(
|
|
1631
|
+
'interruptionFromUser: disconnecting device without acquire, mainId:',
|
|
1632
|
+
mainId
|
|
1633
|
+
);
|
|
1634
|
+
await deviceConnector.disconnect(mainId);
|
|
1635
|
+
}
|
|
1636
|
+
if (this.connectionAttempt === attempt) this.markTransportDisconnected();
|
|
1637
|
+
}
|
|
1638
|
+
await commands?.cancel();
|
|
1639
|
+
} catch (cleanupError) {
|
|
1640
|
+
Log.warn('User cancellation cleanup failed; disconnecting device', cleanupError);
|
|
1641
|
+
if (mainId && deviceConnector?.disconnect) {
|
|
1642
|
+
await deviceConnector.disconnect(mainId).catch(disconnectError => {
|
|
1643
|
+
Log.debug('User cancellation fallback disconnect failed', disconnectError);
|
|
1644
|
+
});
|
|
1645
|
+
}
|
|
1646
|
+
if (this.connectionAttempt === attempt) this.markTransportDisconnected();
|
|
1647
|
+
} finally {
|
|
1648
|
+
runPromise?.reject(error);
|
|
1649
|
+
if (this.runPromise === runPromise) this.runPromise = null;
|
|
1650
|
+
await cleanupPromise?.catch(() => undefined);
|
|
1617
1651
|
}
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
this.runPromise.reject(error);
|
|
1624
|
-
this.runPromise = null;
|
|
1625
|
-
}
|
|
1626
|
-
await cleanupPromise?.catch(() => undefined);
|
|
1652
|
+
})();
|
|
1653
|
+
// Keep the settled promise for this attempt so a duplicate close/finally
|
|
1654
|
+
// cannot send a second wire Cancel. A new attempt gets its own cleanup.
|
|
1655
|
+
this.userInterruption = { attempt, promise };
|
|
1656
|
+
return promise;
|
|
1627
1657
|
}
|
|
1628
1658
|
|
|
1629
1659
|
setCancelableAction(callback: (err?: Error) => Promise<unknown>) {
|
|
1630
|
-
|
|
1660
|
+
const action = (e?: Error) =>
|
|
1631
1661
|
callback(e)
|
|
1632
1662
|
.catch(e2 => {
|
|
1633
1663
|
Log.debug('cancelableAction error', e2);
|
|
1634
1664
|
})
|
|
1635
1665
|
.finally(() => {
|
|
1636
|
-
this.clearCancelableAction();
|
|
1666
|
+
if (this.cancelableAction === action) this.clearCancelableAction();
|
|
1637
1667
|
});
|
|
1668
|
+
this.cancelableAction = action;
|
|
1638
1669
|
}
|
|
1639
1670
|
|
|
1640
1671
|
clearCancelableAction() {
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from '@onekeyfe/hd-transport';
|
|
12
12
|
|
|
13
13
|
import TransportManager from '../data-manager/TransportManager';
|
|
14
|
-
import { LoggerNames, getLogger, patchFeatures } from '../utils';
|
|
14
|
+
import { LoggerNames, getLogger, patchFeatures, wait } from '../utils';
|
|
15
15
|
import { DEVICE, type PassphraseRequestPayload } from '../events';
|
|
16
16
|
import { DeviceModelToTypes } from '../types';
|
|
17
17
|
import {
|
|
@@ -198,6 +198,8 @@ export class DeviceCommands {
|
|
|
198
198
|
|
|
199
199
|
disposed: boolean;
|
|
200
200
|
|
|
201
|
+
private disposalToken?: object;
|
|
202
|
+
|
|
201
203
|
callPromise?: Promise<DefaultMessageResponse>;
|
|
202
204
|
|
|
203
205
|
constructor(device: Device, mainId: string) {
|
|
@@ -212,6 +214,7 @@ export class DeviceCommands {
|
|
|
212
214
|
|
|
213
215
|
async dispose(_cancelRequest: boolean) {
|
|
214
216
|
this.disposed = true;
|
|
217
|
+
this.disposalToken = {};
|
|
215
218
|
await this.transport.cancel?.();
|
|
216
219
|
}
|
|
217
220
|
|
|
@@ -439,7 +442,31 @@ export class DeviceCommands {
|
|
|
439
442
|
msg?: DefaultMessageResponse['message'],
|
|
440
443
|
options?: TransportCallOptions
|
|
441
444
|
) {
|
|
442
|
-
const
|
|
445
|
+
const { disposalToken } = this;
|
|
446
|
+
let resp = await this.call(type, msg, options);
|
|
447
|
+
// Session busy failures precede wallet derivation or reject an occupied flow.
|
|
448
|
+
// Three retries cover the 240 ms PIN dismissal animation on older V2 firmware.
|
|
449
|
+
for (
|
|
450
|
+
let retry = 0;
|
|
451
|
+
retry < 3 &&
|
|
452
|
+
this.device.isProtocolV2() &&
|
|
453
|
+
DEVICE_SESSION_CALLS.has(type) &&
|
|
454
|
+
resp.type === 'Failure' &&
|
|
455
|
+
(resp.message.code as string | FailureType) === 'Failure_ProcessError' &&
|
|
456
|
+
resp.message.subcode === DeviceSessionErrorCode.DeviceSessionError_Busy;
|
|
457
|
+
retry += 1
|
|
458
|
+
) {
|
|
459
|
+
await wait(100);
|
|
460
|
+
if (this.device.wasInterruptedByUser()) {
|
|
461
|
+
throw ERRORS.TypedError(HardwareErrorCode.DeviceInterruptedFromUser);
|
|
462
|
+
}
|
|
463
|
+
this.checkDisposed();
|
|
464
|
+
if (this.disposalToken !== disposalToken) {
|
|
465
|
+
// React Native can revive this instance. A stale retry must not release the new run.
|
|
466
|
+
throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'DeviceCommands lifecycle changed');
|
|
467
|
+
}
|
|
468
|
+
resp = await this.call(type, msg, options);
|
|
469
|
+
}
|
|
443
470
|
return this._filterCommonTypes(resp, type, options);
|
|
444
471
|
}
|
|
445
472
|
|
|
@@ -8,8 +8,9 @@ export const LogBlockEvent: Set<string> = new Set([
|
|
|
8
8
|
UI_RESPONSE.RECEIVE_PASSPHRASE,
|
|
9
9
|
]);
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
// These resource/file APIs did not exist in 1.1.32. Skip the payload so
|
|
12
|
+
// the log layer does not copy huge Base64 or binary data.
|
|
13
|
+
const LogPayloadBlockMethod: Set<string> = new Set([
|
|
13
14
|
'deviceUploadNft',
|
|
14
15
|
'deviceUploadWallpaper',
|
|
15
16
|
'uploadPortfolio',
|
|
@@ -17,61 +18,6 @@ const LogLabelMethod: Set<string> = new Set([
|
|
|
17
18
|
'fileRead',
|
|
18
19
|
]);
|
|
19
20
|
|
|
20
|
-
// 资源上传参数可能包含很大的 Base64 字符串。这里按方法整段跳过,避免日志层
|
|
21
|
-
// 递归复制和序列化这些数据;资源 API 与传输内容本身保持不变。
|
|
22
|
-
const LogPayloadBlockMethod: Set<string> = new Set([
|
|
23
|
-
'deviceUploadNft',
|
|
24
|
-
'deviceUploadWallpaper',
|
|
25
|
-
'uploadPortfolio',
|
|
26
|
-
]);
|
|
27
|
-
|
|
28
|
-
const SensitiveLogKeys: Set<string> = new Set([
|
|
29
|
-
'devicestate',
|
|
30
|
-
'entropy',
|
|
31
|
-
'expectedpassphrasestate',
|
|
32
|
-
'mnemonic',
|
|
33
|
-
'passphrase',
|
|
34
|
-
'passphrasestate',
|
|
35
|
-
'password',
|
|
36
|
-
'pin',
|
|
37
|
-
'privatekey',
|
|
38
|
-
'seed',
|
|
39
|
-
'session',
|
|
40
|
-
'sessionid',
|
|
41
|
-
'walletsessionid',
|
|
42
|
-
'xprv',
|
|
43
|
-
]);
|
|
44
|
-
|
|
45
|
-
const normalizeLogKey = (key: string) => key.replace(/[_-]/g, '').toLowerCase();
|
|
46
|
-
|
|
47
|
-
const isSigningMethod = (methodName: string) => /sign/i.test(methodName);
|
|
48
|
-
|
|
49
|
-
const redactLogValue = (value: unknown, seen: WeakSet<object>): unknown => {
|
|
50
|
-
if (ArrayBuffer.isView(value)) {
|
|
51
|
-
return `[BINARY:${value.byteLength}]`;
|
|
52
|
-
}
|
|
53
|
-
if (value instanceof ArrayBuffer) {
|
|
54
|
-
return `[BINARY:${value.byteLength}]`;
|
|
55
|
-
}
|
|
56
|
-
if (Array.isArray(value)) {
|
|
57
|
-
return value.map(item => redactLogValue(item, seen));
|
|
58
|
-
}
|
|
59
|
-
if (!value || typeof value !== 'object') return value;
|
|
60
|
-
if (seen.has(value)) return '[CIRCULAR]';
|
|
61
|
-
|
|
62
|
-
seen.add(value);
|
|
63
|
-
const redacted = Object.fromEntries(
|
|
64
|
-
Object.entries(value as Record<string, unknown>).map(([key, item]) => [
|
|
65
|
-
key,
|
|
66
|
-
SensitiveLogKeys.has(normalizeLogKey(key)) && item !== null && item !== undefined
|
|
67
|
-
? '[REDACTED]'
|
|
68
|
-
: redactLogValue(item, seen),
|
|
69
|
-
])
|
|
70
|
-
);
|
|
71
|
-
seen.delete(value);
|
|
72
|
-
return redacted;
|
|
73
|
-
};
|
|
74
|
-
|
|
75
21
|
export function getLogBlockLabel(message: unknown): string | undefined {
|
|
76
22
|
if (!message || typeof message !== 'object') return undefined;
|
|
77
23
|
|
|
@@ -86,7 +32,7 @@ export function getLogBlockLabel(message: unknown): string | undefined {
|
|
|
86
32
|
}
|
|
87
33
|
|
|
88
34
|
const methodName = method ?? payload?.method;
|
|
89
|
-
if (methodName &&
|
|
35
|
+
if (methodName && LogPayloadBlockMethod.has(methodName)) {
|
|
90
36
|
return methodName;
|
|
91
37
|
}
|
|
92
38
|
|
|
@@ -94,25 +40,10 @@ export function getLogBlockLabel(message: unknown): string | undefined {
|
|
|
94
40
|
}
|
|
95
41
|
|
|
96
42
|
export function getSafeLogPayload(value: unknown, blockLabel?: string): unknown {
|
|
97
|
-
if (
|
|
98
|
-
blockLabel &&
|
|
99
|
-
(LogBlockEvent.has(blockLabel) ||
|
|
100
|
-
LogPayloadBlockMethod.has(blockLabel) ||
|
|
101
|
-
isSigningMethod(blockLabel))
|
|
102
|
-
) {
|
|
43
|
+
if (blockLabel) {
|
|
103
44
|
return { method: blockLabel, payload: '[REDACTED]' };
|
|
104
45
|
}
|
|
105
|
-
|
|
106
|
-
const redactedValue = redactLogValue(value, new WeakSet());
|
|
107
|
-
if (
|
|
108
|
-
blockLabel &&
|
|
109
|
-
redactedValue &&
|
|
110
|
-
typeof redactedValue === 'object' &&
|
|
111
|
-
!Array.isArray(redactedValue)
|
|
112
|
-
) {
|
|
113
|
-
return { ...redactedValue, method: blockLabel };
|
|
114
|
-
}
|
|
115
|
-
return redactedValue;
|
|
46
|
+
return value;
|
|
116
47
|
}
|
|
117
48
|
|
|
118
49
|
export function formatLogMethodLabel(label: string, methodName?: string): string {
|
|
@@ -234,9 +234,9 @@ export async function getProtocolV2WalletSession(
|
|
|
234
234
|
const forceWalletSelection =
|
|
235
235
|
options?.forceWalletSelection === true || options?.initSession === true;
|
|
236
236
|
const readCurrentAttachPinSession = options?.readCurrentAttachPinSession === true;
|
|
237
|
-
const sessionIsAttachPinWallet = (session?:
|
|
237
|
+
const sessionIsAttachPinWallet = (session?: unknown) =>
|
|
238
238
|
readCurrentAttachPinSession ||
|
|
239
|
-
session?.viaAttachPin === true ||
|
|
239
|
+
(session as { viaAttachPin?: boolean } | undefined)?.viaAttachPin === true ||
|
|
240
240
|
device.features?.unlockedAttachPin === true;
|
|
241
241
|
|
|
242
242
|
if (forceWalletSelection) {
|
|
@@ -268,6 +268,7 @@ export async function getProtocolV2WalletSession(
|
|
|
268
268
|
? device.getInternalState()
|
|
269
269
|
: undefined;
|
|
270
270
|
let response;
|
|
271
|
+
let walletSelectionRequested = false;
|
|
271
272
|
let resumed = false;
|
|
272
273
|
let walletStatusRefreshed = false;
|
|
273
274
|
const markWalletStatusRefreshed = () => {
|
|
@@ -455,6 +456,11 @@ export async function getProtocolV2WalletSession(
|
|
|
455
456
|
throw error;
|
|
456
457
|
}
|
|
457
458
|
resumed = false;
|
|
459
|
+
if (device.features?.unlockedAttachPin === true) {
|
|
460
|
+
// Locking invalidates the old handle, but Attach PIN already selected the wallet.
|
|
461
|
+
// Read the current session and validate its passphrase state below.
|
|
462
|
+
response = await getDeviceSession(device, sessionGetRequest());
|
|
463
|
+
}
|
|
458
464
|
}
|
|
459
465
|
} else if (expectedPassphraseState) {
|
|
460
466
|
try {
|
|
@@ -477,6 +483,7 @@ export async function getProtocolV2WalletSession(
|
|
|
477
483
|
throw ERRORS.TypedError(HardwareErrorCode.WalletSessionInvalid);
|
|
478
484
|
}
|
|
479
485
|
await lockAttachPinBeforePassphraseSelection();
|
|
486
|
+
walletSelectionRequested = true;
|
|
480
487
|
response = await selectDeviceSession(
|
|
481
488
|
device,
|
|
482
489
|
expectedPassphraseState,
|
|
@@ -503,6 +510,11 @@ export async function getProtocolV2WalletSession(
|
|
|
503
510
|
device.clearInternalState();
|
|
504
511
|
throw ERRORS.TypedError(HardwareErrorCode.WalletSessionInvalid);
|
|
505
512
|
}
|
|
513
|
+
// Report a fresh selection mismatch before asking for input again.
|
|
514
|
+
if (walletSelectionRequested) {
|
|
515
|
+
clearCurrentWalletSession();
|
|
516
|
+
throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckPassphraseStateError);
|
|
517
|
+
}
|
|
506
518
|
if (options?.onlyMainPin) {
|
|
507
519
|
device.clearStandardInternalState?.();
|
|
508
520
|
await selectStandardWallet(true);
|
|
@@ -2,6 +2,7 @@ import type { CommonParams, Response } from '../params';
|
|
|
2
2
|
import type { Features } from '../device';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* @deprecated Use `getDeviceState` for both Protocol V1 and Protocol V2
|
|
5
|
+
* @deprecated Use `getDeviceState` for both Protocol V1 and Protocol V2.
|
|
6
|
+
* Existing calls still work. Read `payload.identity.deviceId` from `getDeviceState`.
|
|
6
7
|
*/
|
|
7
8
|
export declare function getFeatures(connectId?: string, params?: CommonParams): Response<Features>;
|
|
@@ -3,11 +3,8 @@ import type { CommonParams, Response } from '../params';
|
|
|
3
3
|
export type GetPassphraseStateParams = CommonParams;
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* Protocol V1 keeps its parameterless firmware flow. Protocol V2 maps the existing
|
|
9
|
-
* `useEmptyPassphrase` and `initSession` intent to the device-only wallet-session flow.
|
|
10
|
-
* New integrations should prefer `openWalletSession` for explicit wallet intent.
|
|
6
|
+
* @deprecated Use `openWalletSession` for both Protocol V1 and Protocol V2.
|
|
7
|
+
* Existing calls still work. Persist `deviceId + passphraseState`; do not persist firmware `session_id`.
|
|
11
8
|
*/
|
|
12
9
|
export declare function getPassphraseState(
|
|
13
10
|
connectId?: string,
|
|
@@ -3,28 +3,16 @@ import type { CommonParams, Response } from '../params';
|
|
|
3
3
|
export const OpenWalletSessionMode = {
|
|
4
4
|
Standard: 'standard',
|
|
5
5
|
SelectHidden: 'select-hidden',
|
|
6
|
-
ResumeHidden: 'resume-hidden',
|
|
7
6
|
} as const;
|
|
8
7
|
|
|
9
8
|
export type OpenWalletSessionModeValue =
|
|
10
9
|
(typeof OpenWalletSessionMode)[keyof typeof OpenWalletSessionMode];
|
|
11
10
|
|
|
12
|
-
export type OpenWalletSessionParams =
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
| {
|
|
19
|
-
mode: typeof OpenWalletSessionMode.SelectHidden;
|
|
20
|
-
deviceId?: never;
|
|
21
|
-
passphraseState?: never;
|
|
22
|
-
}
|
|
23
|
-
| {
|
|
24
|
-
mode: typeof OpenWalletSessionMode.ResumeHidden;
|
|
25
|
-
deviceId: string;
|
|
26
|
-
passphraseState: string;
|
|
27
|
-
};
|
|
11
|
+
export type OpenWalletSessionParams = {
|
|
12
|
+
mode: OpenWalletSessionModeValue;
|
|
13
|
+
deviceId?: never;
|
|
14
|
+
passphraseState?: never;
|
|
15
|
+
};
|
|
28
16
|
|
|
29
17
|
type OpenWalletSessionPayloadBase = {
|
|
30
18
|
protocol: 'V1' | 'V2';
|
|
@@ -45,8 +33,8 @@ export type OpenWalletSessionPayload = OpenWalletSessionPayloadBase &
|
|
|
45
33
|
);
|
|
46
34
|
|
|
47
35
|
/**
|
|
48
|
-
* Opens the standard
|
|
49
|
-
*
|
|
36
|
+
* Opens the standard or hidden wallet through a unified Protocol V1/V2 API.
|
|
37
|
+
* Resume a bound hidden wallet by passing passphraseState on later methods.
|
|
50
38
|
*/
|
|
51
39
|
export declare function openWalletSession(
|
|
52
40
|
connectId: string,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { CommonParams, Response } from '../params';
|
|
2
2
|
import type { OnboardingStatus, Success } from '@onekeyfe/hd-transport';
|
|
3
3
|
import type { DeviceRebootParams } from '../../api/protocol-v2/helpers';
|
|
4
|
+
import type { UploadPortfolioParams } from '../../api/UploadPortfolio';
|
|
4
5
|
import type {
|
|
5
6
|
DeviceUploadWallpaperParams,
|
|
6
7
|
DeviceUploadWallpaperResponse,
|
|
@@ -12,6 +13,7 @@ import type {
|
|
|
12
13
|
|
|
13
14
|
// Re-export implementation parameter types as the single source of truth.
|
|
14
15
|
export type { DeviceRebootParams, RebootTypeInput } from '../../api/protocol-v2/helpers';
|
|
16
|
+
export type { UploadPortfolioParams } from '../../api/UploadPortfolio';
|
|
15
17
|
export type {
|
|
16
18
|
DeviceUploadWallpaperParams,
|
|
17
19
|
DeviceUploadWallpaperResponse,
|
|
@@ -67,8 +69,5 @@ export declare function deviceUploadNft(
|
|
|
67
69
|
|
|
68
70
|
export declare function uploadPortfolio(
|
|
69
71
|
connectId: string,
|
|
70
|
-
params:
|
|
71
|
-
packageBase64: string;
|
|
72
|
-
timeoutMs?: number | string;
|
|
73
|
-
}
|
|
72
|
+
params: UploadPortfolioParams
|
|
74
73
|
): Response<FileInfo & { portfolioUpdated: true }>;
|
|
@@ -15,6 +15,8 @@ export type SolSignOffchainMessageParams = {
|
|
|
15
15
|
messageVersion?: SolanaOffChainMessageVersion;
|
|
16
16
|
messageFormat?: SolanaOffChainMessageFormat;
|
|
17
17
|
applicationDomainHex?: string;
|
|
18
|
+
/** 32-byte public keys encoded as hex, strictly sorted and unique. */
|
|
19
|
+
requiredSigners?: string[];
|
|
18
20
|
};
|
|
19
21
|
|
|
20
22
|
export declare function solSignOffchainMessage(
|
package/src/types/params.ts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import type { HardwareConnectProtocol } from '@onekeyfe/hd-shared';
|
|
2
2
|
|
|
3
3
|
export interface CommonParams {
|
|
4
|
+
/**
|
|
5
|
+
* Keep the transport session after this call instead of releasing it.
|
|
6
|
+
* This is a Device.run() hold flag, not a wallet identity. It does not replace
|
|
7
|
+
* `useEmptyPassphrase`, `passphraseState`, or `openWalletSession`.
|
|
8
|
+
* USB multi-step flows and Electron BLE firmware windows still need this to
|
|
9
|
+
* avoid dropping the link between calls.
|
|
10
|
+
*/
|
|
4
11
|
keepSession?: boolean;
|
|
5
12
|
/**
|
|
6
13
|
* polling connect max retry count
|