@onekeyfe/hwk-ledger-adapter 1.1.26-alpha.8 → 1.1.26-patch.1
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/dist/index.d.mts +277 -182
- package/dist/index.d.ts +277 -182
- package/dist/index.js +1575 -589
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1576 -591
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -1,45 +1,22 @@
|
|
|
1
|
-
import { IHardwareWallet, IConnector, TransportType, UiResponseEvent, DeviceInfo, Response, ChainCapability, EvmGetAddressParams, EvmAddress,
|
|
2
|
-
import {
|
|
1
|
+
import { IHardwareWallet, IConnector, TransportType, UiResponseEvent, SearchDevicesOptions, DeviceInfo, Response, ChainCapability, EvmGetAddressParams, EvmAddress, EvmSignTxParams, EvmSignedTx, EvmSignMsgParams, EvmSignature, EvmSignTypedDataParams, BtcGetAddressParams, BtcAddress, BtcGetPublicKeyParams, BtcPublicKey, BtcSignTxParams, BtcSignedTx, BtcSignPsbtParams, BtcSignedPsbt, BtcSignMsgParams, BtcSignature, SolGetAddressParams, SolAddress, SolSignTxParams, SolSignedTx, SolSignMsgParams, SolSignature, TronGetAddressParams, TronAddress, TronSignTxParams, TronSignedTx, TronSignMsgParams, TronSignature, HardwareEventMap, DeviceEventListener, ChainForFingerprint, DeviceDescriptor, DeviceChangeEvent, ConnectionType, ConnectorDevice, ConnectorSession, ConnectorEventType, ConnectorEventMap, Failure, HardwareErrorCode } from '@onekeyfe/hwk-adapter-core';
|
|
2
|
+
import { DeviceActionState as DeviceActionState$1, DiscoveredDevice, ExecuteDeviceActionReturnType, DeviceManagementKit } from '@ledgerhq/device-management-kit';
|
|
3
3
|
import { Address, Signature, SignerEth as SignerEth$1, TypedData } from '@ledgerhq/device-signer-kit-ethereum';
|
|
4
|
+
import { ContextModule } from '@ledgerhq/context-module';
|
|
4
5
|
import { SignerBtc as SignerBtc$1 } from '@ledgerhq/device-signer-kit-bitcoin';
|
|
5
6
|
import { SignerSolana } from '@ledgerhq/device-signer-kit-solana';
|
|
6
7
|
import Transport from '@ledgerhq/hw-transport';
|
|
7
8
|
|
|
8
|
-
interface LedgerAdapterOptions {
|
|
9
|
-
/**
|
|
10
|
-
* `true` — emit `REQUEST_SELECT_DEVICE` on multi-device discovery and await
|
|
11
|
-
* `uiResponse({ type: RECEIVE_SELECT_DEVICE, payload: { sdkConnectId } })`.
|
|
12
|
-
* `false` (default) — silently pick the first device.
|
|
13
|
-
*/
|
|
14
|
-
handleSelectDevice?: boolean;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Ledger hardware wallet adapter that delegates to an IConnector.
|
|
18
|
-
*
|
|
19
|
-
* This is a thin translation layer that:
|
|
20
|
-
* - Accepts a pre-configured IConnector (transport decisions are made at connector creation time)
|
|
21
|
-
* - Translates IHardwareWallet method calls to connector.call() invocations
|
|
22
|
-
* - Maps connector results/errors to our Response<T> format with enriched error messages
|
|
23
|
-
* - Translates connector events to HardwareEventMap events
|
|
24
|
-
* - Emits `REQUEST_DEVICE_PERMISSION` for OS-level permission checks
|
|
25
|
-
*/
|
|
26
9
|
declare class LedgerAdapter implements IHardwareWallet {
|
|
27
10
|
readonly vendor: "ledger";
|
|
28
11
|
private readonly connector;
|
|
29
12
|
private readonly emitter;
|
|
30
|
-
private readonly _handleSelectDevice;
|
|
31
13
|
private _discoveredDevices;
|
|
32
14
|
private _sessions;
|
|
33
15
|
private readonly _uiRegistry;
|
|
16
|
+
private _btcHighIndexConfirmedThisSession;
|
|
34
17
|
private readonly _jobQueue;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
* Classify a method's interruptibility.
|
|
38
|
-
* - Signing / typed data / transaction → 'confirm' (user may decide via preemption UI)
|
|
39
|
-
* - Read-only queries (getAddress / getPublicKey / getMasterFingerprint) → 'safe'
|
|
40
|
-
* (auto-cancels any pending read for the same device)
|
|
41
|
-
*/
|
|
42
|
-
private static _getInterruptibility;
|
|
18
|
+
private _doConnectAbortController;
|
|
19
|
+
constructor(connector: IConnector);
|
|
43
20
|
get activeTransport(): TransportType | null;
|
|
44
21
|
getAvailableTransports(): TransportType[];
|
|
45
22
|
switchTransport(_type: TransportType): Promise<void>;
|
|
@@ -52,24 +29,23 @@ declare class LedgerAdapter implements IHardwareWallet {
|
|
|
52
29
|
resetState(): void;
|
|
53
30
|
dispose(): Promise<void>;
|
|
54
31
|
uiResponse(response: UiResponseEvent): void;
|
|
55
|
-
searchDevices(): Promise<DeviceInfo[]>;
|
|
32
|
+
searchDevices(options?: SearchDevicesOptions): Promise<DeviceInfo[]>;
|
|
33
|
+
private _evictAllSessions;
|
|
34
|
+
private static readonly MAX_BUSINESS_RETRY_BUDGET;
|
|
35
|
+
private static readonly STUCK_APP_RETRY_DELAY_MS;
|
|
36
|
+
private static readonly MAX_DOCONNECT_CONFIRMS;
|
|
37
|
+
private _lastCancelReason;
|
|
38
|
+
private static _createDeviceBusyError;
|
|
56
39
|
connectDevice(connectId: string): Promise<Response<string>>;
|
|
57
40
|
disconnectDevice(connectId: string): Promise<void>;
|
|
58
41
|
getDeviceInfo(connectId: string, deviceId: string): Promise<Response<DeviceInfo>>;
|
|
59
42
|
getSupportedChains(): ChainCapability[];
|
|
60
43
|
private callChain;
|
|
61
|
-
/**
|
|
62
|
-
* Batch version of callChain — checks permission once,
|
|
63
|
-
* fingerprint is verified on the first call inside connectorCall.
|
|
64
|
-
*/
|
|
65
|
-
private callChainBatch;
|
|
66
44
|
evmGetAddress(connectId: string, deviceId: string, params: EvmGetAddressParams): Promise<Response<EvmAddress>>;
|
|
67
|
-
evmGetAddresses(connectId: string, deviceId: string, params: EvmGetAddressParams[], onProgress?: ProgressCallback): Promise<Response<EvmAddress[]>>;
|
|
68
45
|
evmSignTransaction(connectId: string, deviceId: string, params: EvmSignTxParams): Promise<Response<EvmSignedTx>>;
|
|
69
46
|
evmSignMessage(connectId: string, deviceId: string, params: EvmSignMsgParams): Promise<Response<EvmSignature>>;
|
|
70
47
|
evmSignTypedData(connectId: string, deviceId: string, params: EvmSignTypedDataParams): Promise<Response<EvmSignature>>;
|
|
71
48
|
btcGetAddress(connectId: string, deviceId: string, params: BtcGetAddressParams): Promise<Response<BtcAddress>>;
|
|
72
|
-
btcGetAddresses(connectId: string, deviceId: string, params: BtcGetAddressParams[], onProgress?: ProgressCallback): Promise<Response<BtcAddress[]>>;
|
|
73
49
|
btcGetPublicKey(connectId: string, deviceId: string, params: BtcGetPublicKeyParams): Promise<Response<BtcPublicKey>>;
|
|
74
50
|
btcSignTransaction(connectId: string, deviceId: string, params: BtcSignTxParams): Promise<Response<BtcSignedTx>>;
|
|
75
51
|
btcSignPsbt(connectId: string, deviceId: string, params: BtcSignPsbtParams): Promise<Response<BtcSignedPsbt>>;
|
|
@@ -78,18 +54,16 @@ declare class LedgerAdapter implements IHardwareWallet {
|
|
|
78
54
|
masterFingerprint: string;
|
|
79
55
|
}>>;
|
|
80
56
|
solGetAddress(connectId: string, deviceId: string, params: SolGetAddressParams): Promise<Response<SolAddress>>;
|
|
81
|
-
solGetAddresses(connectId: string, deviceId: string, params: SolGetAddressParams[], onProgress?: ProgressCallback): Promise<Response<SolAddress[]>>;
|
|
82
57
|
solSignTransaction(connectId: string, deviceId: string, params: SolSignTxParams): Promise<Response<SolSignedTx>>;
|
|
83
58
|
solSignMessage(connectId: string, deviceId: string, params: SolSignMsgParams): Promise<Response<SolSignature>>;
|
|
84
59
|
tronGetAddress(connectId: string, deviceId: string, params: TronGetAddressParams): Promise<Response<TronAddress>>;
|
|
85
|
-
tronGetAddresses(connectId: string, deviceId: string, params: TronGetAddressParams[], onProgress?: ProgressCallback): Promise<Response<TronAddress[]>>;
|
|
86
60
|
tronSignTransaction(connectId: string, deviceId: string, params: TronSignTxParams): Promise<Response<TronSignedTx>>;
|
|
87
61
|
tronSignMessage(connectId: string, deviceId: string, params: TronSignMsgParams): Promise<Response<TronSignature>>;
|
|
88
62
|
on<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;
|
|
89
63
|
on(event: string, listener: DeviceEventListener): void;
|
|
90
64
|
off<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;
|
|
91
65
|
off(event: string, listener: DeviceEventListener): void;
|
|
92
|
-
cancel(connectId
|
|
66
|
+
cancel(connectId?: string): void;
|
|
93
67
|
getChainFingerprint(connectId: string, deviceId: string, chain: ChainForFingerprint): Promise<Response<string>>;
|
|
94
68
|
/**
|
|
95
69
|
* Verify fingerprint using an existing sessionId directly.
|
|
@@ -116,15 +90,23 @@ declare class LedgerAdapter implements IHardwareWallet {
|
|
|
116
90
|
*
|
|
117
91
|
* - If a session already exists for the given connectId, reuse it.
|
|
118
92
|
* - If ANY session exists (Ledger IDs are ephemeral), reuse it.
|
|
119
|
-
* - Otherwise: search → 1 device
|
|
93
|
+
* - Otherwise: search → exactly 1 USB device auto-connects; multiple or none throws.
|
|
120
94
|
*/
|
|
121
|
-
private static readonly MAX_DEVICE_RETRY;
|
|
122
95
|
private _connectingPromise;
|
|
123
96
|
private _waitForDeviceConnect;
|
|
97
|
+
/**
|
|
98
|
+
* Decide whether a BTC pubkey call needs `showOnDevice=true` because of
|
|
99
|
+
* the BTC App's account-index policy, asking the user once per session.
|
|
100
|
+
*
|
|
101
|
+
* Returns the params to pass through (with `showOnDevice` possibly
|
|
102
|
+
* promoted), or `null` if the user declined.
|
|
103
|
+
*/
|
|
104
|
+
private _gateBtcHighIndex;
|
|
105
|
+
private _waitForBtcHighIndexConfirm;
|
|
124
106
|
private ensureConnected;
|
|
125
107
|
private _doConnect;
|
|
126
108
|
private _connectFirstOrSelect;
|
|
127
|
-
private
|
|
109
|
+
private _connectDeviceOrThrow;
|
|
128
110
|
/**
|
|
129
111
|
* Call the connector with automatic session resolution and disconnect retry.
|
|
130
112
|
*
|
|
@@ -135,16 +117,31 @@ declare class LedgerAdapter implements IHardwareWallet {
|
|
|
135
117
|
*/
|
|
136
118
|
private connectorCall;
|
|
137
119
|
/**
|
|
138
|
-
* Race a promise against an abort signal.
|
|
139
|
-
* signal
|
|
140
|
-
* actually be cancelled on Ledger DMK, but the caller gets the abort immediately.
|
|
120
|
+
* Race a promise against an abort signal. On abort, rejects with
|
|
121
|
+
* signal.reason → instance _lastCancelReason → generic Error('Aborted').
|
|
141
122
|
*/
|
|
142
|
-
private
|
|
123
|
+
private _abortable;
|
|
143
124
|
/** Throw an AbortError if signal is already aborted. */
|
|
144
125
|
private static _throwIfAborted;
|
|
145
126
|
/** Actual work done under the job queue — connection, fingerprint, call, and recovery. */
|
|
146
127
|
private _runConnectorCall;
|
|
147
|
-
/**
|
|
128
|
+
/**
|
|
129
|
+
* Stuck-app recovery: pause for the device's UI transition, then retry once.
|
|
130
|
+
*
|
|
131
|
+
* Caller has already cleared the session + reset connector. We wait so Stax
|
|
132
|
+
* finishes its post-CloseApp animation, then go through ensureConnected +
|
|
133
|
+
* fingerprint check + call exactly once. Caller decides what to do on a
|
|
134
|
+
* second stuck-app hit.
|
|
135
|
+
*/
|
|
136
|
+
private _retryAfterStuckApp;
|
|
137
|
+
private _sleepAbortable;
|
|
138
|
+
/**
|
|
139
|
+
* Clear stale session, reconnect, and retry the call.
|
|
140
|
+
*
|
|
141
|
+
* Timeout recovery starts with a full connector reset. After an APDU
|
|
142
|
+
* timeout, DMK/transport state may still emit malformed responses; retrying
|
|
143
|
+
* on the same DMK can poison the next chain switch.
|
|
144
|
+
*/
|
|
148
145
|
private _retryWithFreshConnection;
|
|
149
146
|
/**
|
|
150
147
|
* Ensure OS-level device permission (Bluetooth / USB) before proceeding.
|
|
@@ -166,14 +163,115 @@ declare class LedgerAdapter implements IHardwareWallet {
|
|
|
166
163
|
private errorToFailure;
|
|
167
164
|
private deviceConnectHandler;
|
|
168
165
|
private deviceDisconnectHandler;
|
|
169
|
-
private
|
|
170
|
-
private uiEventHandler;
|
|
166
|
+
private uiEventForwarder;
|
|
171
167
|
private registerEventListeners;
|
|
172
168
|
private unregisterEventListeners;
|
|
173
|
-
private handleUiEvent;
|
|
174
169
|
private connectorDeviceToDeviceInfo;
|
|
175
|
-
|
|
176
|
-
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Re-export DMK types under local aliases for backward compatibility.
|
|
174
|
+
* These replace the previous duck-typed interfaces with the real SDK types.
|
|
175
|
+
*/
|
|
176
|
+
type DmkDiscoveredDevice = DiscoveredDevice;
|
|
177
|
+
/**
|
|
178
|
+
* DMK DeviceAction — the Observable-based return type of all DMK signer methods.
|
|
179
|
+
*
|
|
180
|
+
* This is a permissive alias for `ExecuteDeviceActionReturnType` that accepts
|
|
181
|
+
* any Error and IntermediateValue generics. Signer wrapper code only cares about
|
|
182
|
+
* the Output type and the observable/cancel shape.
|
|
183
|
+
*/
|
|
184
|
+
type DeviceAction<T> = ExecuteDeviceActionReturnType<T, any, any>;
|
|
185
|
+
/**
|
|
186
|
+
* DMK DeviceActionState — re-exported with permissive Error/IntermediateValue.
|
|
187
|
+
* The real type is a discriminated union on `status`.
|
|
188
|
+
*/
|
|
189
|
+
type DeviceActionState<T> = DeviceActionState$1<T, any, any>;
|
|
190
|
+
/** ETH address result — re-exported from DMK for backward compatibility. */
|
|
191
|
+
type SignerEvmAddress = Address;
|
|
192
|
+
/** ETH signature result — re-exported from DMK for backward compatibility. */
|
|
193
|
+
type SignerEvmSignature = Signature;
|
|
194
|
+
/** BTC address result (WalletAddress not exported from DMK top-level). */
|
|
195
|
+
interface SignerBtcAddress {
|
|
196
|
+
address: string;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Manages device discovery, connection, and session tracking.
|
|
201
|
+
* Wraps DMK's Observable APIs into simpler imperative calls.
|
|
202
|
+
*/
|
|
203
|
+
declare class LedgerDeviceManager {
|
|
204
|
+
private readonly _dmk;
|
|
205
|
+
private readonly _discovered;
|
|
206
|
+
private readonly _sessions;
|
|
207
|
+
private readonly _sessionToDevice;
|
|
208
|
+
private _listenSub;
|
|
209
|
+
constructor(dmk: DeviceManagementKit);
|
|
210
|
+
/**
|
|
211
|
+
* One-shot enumeration: subscribe to listenToAvailableDevices,
|
|
212
|
+
* take the first emission, unsubscribe, return DeviceDescriptors.
|
|
213
|
+
*/
|
|
214
|
+
enumerate(): Promise<DeviceDescriptor[]>;
|
|
215
|
+
/**
|
|
216
|
+
* Continuous listening: tracks device connect/disconnect via diffing.
|
|
217
|
+
*/
|
|
218
|
+
listen(onChange: (event: DeviceChangeEvent) => void): void;
|
|
219
|
+
stopListening(): void;
|
|
220
|
+
/**
|
|
221
|
+
* Resolve to the latest snapshot of advertising devices observed within
|
|
222
|
+
* `timeoutMs`. Rewrites `_discovered` so it tracks the live list.
|
|
223
|
+
*
|
|
224
|
+
* `listenToAvailableDevices` is a BehaviorSubject — it emits the cached
|
|
225
|
+
* list on subscribe and *only* re-emits when the list changes. A stable
|
|
226
|
+
* list of currently-advertising devices therefore produces only the
|
|
227
|
+
* subscription frame; treating that frame as "fossil to be discarded"
|
|
228
|
+
* caused devices to flicker in/out of the UI as searches alternated
|
|
229
|
+
* between "saw a change frame" and "saw only the cached frame".
|
|
230
|
+
*
|
|
231
|
+
* The window still gives a chance for the active scan to update the list
|
|
232
|
+
* (e.g. drop a peripheral that just stopped broadcasting), but if nothing
|
|
233
|
+
* changes we trust the snapshot — DMK silence on a stable list means
|
|
234
|
+
* "everything's still there".
|
|
235
|
+
*/
|
|
236
|
+
getLiveDevices(timeoutMs?: number): Promise<DmkDiscoveredDevice[]>;
|
|
237
|
+
/**
|
|
238
|
+
* Trigger browser device selection (WebHID requestDevice).
|
|
239
|
+
* Starts discovery for a short period, then stops.
|
|
240
|
+
*/
|
|
241
|
+
/**
|
|
242
|
+
* Start BLE discovery if not already running.
|
|
243
|
+
* Does NOT stop — DMK keeps scanning in the background so that
|
|
244
|
+
* listenToAvailableDevices() always has fresh data.
|
|
245
|
+
*/
|
|
246
|
+
private _discoverySub;
|
|
247
|
+
requestDevice(): Promise<void>;
|
|
248
|
+
/** Lookup a previously-discovered device's display name. */
|
|
249
|
+
getDeviceName(deviceId: string): string | undefined;
|
|
250
|
+
/** Lookup minimal model/signal info from a previously-discovered device. */
|
|
251
|
+
getDiscoveredDeviceInfo(deviceId: string): {
|
|
252
|
+
model?: string;
|
|
253
|
+
modelName?: string;
|
|
254
|
+
name?: string;
|
|
255
|
+
rssi?: number | null;
|
|
256
|
+
} | undefined;
|
|
257
|
+
hasDiscoveredDevice(deviceId: string): boolean;
|
|
258
|
+
/** Connect to a previously discovered device. Returns sessionId. */
|
|
259
|
+
connect(deviceId: string): Promise<string>;
|
|
260
|
+
/** Disconnect a session. */
|
|
261
|
+
disconnect(sessionId: string): Promise<void>;
|
|
262
|
+
getSessionId(deviceId: string): string | undefined;
|
|
263
|
+
getDeviceId(sessionId: string): string | undefined;
|
|
264
|
+
/** Get the underlying DMK instance (needed by SignerManager). */
|
|
265
|
+
getDmk(): DeviceManagementKit;
|
|
266
|
+
stopDiscovery(): void;
|
|
267
|
+
dispose(): void;
|
|
268
|
+
/**
|
|
269
|
+
* Tear down RxJS subscriptions and local state without closing the DMK.
|
|
270
|
+
* For light-reset paths that want to drop session state but keep the
|
|
271
|
+
* underlying transport alive for retry. Call this instead of orphaning
|
|
272
|
+
* the manager — bare null assignment leaks _listenSub / _discoverySub.
|
|
273
|
+
*/
|
|
274
|
+
disposeKeepingDmk(): void;
|
|
177
275
|
}
|
|
178
276
|
|
|
179
277
|
/**
|
|
@@ -201,7 +299,14 @@ interface LedgerConnectorBaseOptions {
|
|
|
201
299
|
* Subclasses only need to:
|
|
202
300
|
* 1. Supply a transport factory via the constructor.
|
|
203
301
|
* 2. Optionally override `_resolveConnectId()` for transport-specific
|
|
204
|
-
* device identity resolution
|
|
302
|
+
* device identity resolution.
|
|
303
|
+
*
|
|
304
|
+
* Invariant: one instance = one transport. `connectionType` is fixed at
|
|
305
|
+
* construction. To switch transport (e.g. desktop BLE ↔ WebHID), the host
|
|
306
|
+
* must build a new connector instance and replace the old one — don't add
|
|
307
|
+
* multiple transports to a single instance. Lifting this constraint would
|
|
308
|
+
* require routing `connectionType` from `descriptor.transport` per-device
|
|
309
|
+
* and updating every `this.connectionType` branch in this file.
|
|
205
310
|
*/
|
|
206
311
|
declare class LedgerConnectorBase implements IConnector {
|
|
207
312
|
private _deviceManager;
|
|
@@ -211,15 +316,8 @@ declare class LedgerConnectorBase implements IConnector {
|
|
|
211
316
|
private readonly _providedDmk;
|
|
212
317
|
private readonly _createTransport;
|
|
213
318
|
readonly connectionType: ConnectionType;
|
|
214
|
-
private _connectIdToPath;
|
|
215
|
-
private _pathToConnectId;
|
|
216
|
-
/** Register a connectId <-> path mapping from a device descriptor. */
|
|
217
|
-
private _registerDeviceId;
|
|
218
|
-
/** Get DMK path from external connectId. Falls back to connectId itself. */
|
|
219
|
-
private _getPathForConnectId;
|
|
220
|
-
/** Get external connectId from DMK path. Falls back to path itself. */
|
|
221
|
-
private _getConnectIdForPath;
|
|
222
319
|
private readonly _cancellers;
|
|
320
|
+
private readonly _sessionStateSubs;
|
|
223
321
|
/**
|
|
224
322
|
* Resolves a Ledger signer kit module by package name.
|
|
225
323
|
* Override via constructor to use CJS paths for Metro (React Native).
|
|
@@ -228,6 +326,10 @@ declare class LedgerConnectorBase implements IConnector {
|
|
|
228
326
|
protected _importLedgerKit: (pkg: string) => Promise<any>;
|
|
229
327
|
/** Context object passed to per-chain handler functions. */
|
|
230
328
|
private readonly _ctx;
|
|
329
|
+
/** When true, BLE direct-connect throws NotAdvertising if the pre-flight
|
|
330
|
+
* scan can't see the device — guard for GATT stacks that wedge on
|
|
331
|
+
* non-advertising peripherals (iOS). */
|
|
332
|
+
private readonly _requirePreFlightScan;
|
|
231
333
|
constructor(createTransport: TransportFactory, options?: {
|
|
232
334
|
connectionType?: ConnectionType;
|
|
233
335
|
dmk?: DeviceManagementKit;
|
|
@@ -237,17 +339,39 @@ declare class LedgerConnectorBase implements IConnector {
|
|
|
237
339
|
* For Metro (React Native): pass a resolver that uses CJS paths.
|
|
238
340
|
*/
|
|
239
341
|
importLedgerKit?: (pkg: string) => Promise<any>;
|
|
342
|
+
/** Default false. RN-iOS subclass should pass `true`. */
|
|
343
|
+
requirePreFlightScan?: boolean;
|
|
240
344
|
});
|
|
241
345
|
/**
|
|
242
346
|
* Resolve the connectId for a discovered device descriptor.
|
|
243
347
|
* Default: use the DMK path (ephemeral UUID).
|
|
244
|
-
* Override in subclasses
|
|
348
|
+
* Override in subclasses only when the public connectId differs from the transport path.
|
|
245
349
|
*/
|
|
246
350
|
protected _resolveConnectId(descriptor: DeviceDescriptor): string;
|
|
351
|
+
/**
|
|
352
|
+
* Authoritative discovery for this transport. Default = enumerate snapshot
|
|
353
|
+
* (USB/HID). BLE overrides to drive from a live scan window since DMK's
|
|
354
|
+
* enumerate() cache survives peripherals going offline.
|
|
355
|
+
*/
|
|
356
|
+
protected _discoverDescriptors(dm: LedgerDeviceManager): Promise<DeviceDescriptor[]>;
|
|
357
|
+
private _assertSingleUsbDescriptor;
|
|
247
358
|
searchDevices(): Promise<ConnectorDevice[]>;
|
|
248
359
|
connect(deviceId?: string): Promise<ConnectorSession>;
|
|
249
360
|
disconnect(sessionId: string): Promise<void>;
|
|
361
|
+
/**
|
|
362
|
+
* Subscribe to DMK's per-session state observable so that any autonomous
|
|
363
|
+
* disconnect (USB unplug, BLE drop, device sleep, transport reset) is
|
|
364
|
+
* surfaced as a `device-disconnect` event — without this, the upstream
|
|
365
|
+
* `LedgerAdapter._sessions` map would hold a dead session entry until
|
|
366
|
+
* the next call hit `DeviceSessionNotFound`.
|
|
367
|
+
*
|
|
368
|
+
* Subscribe failure is fatal — see the inline note at the subscribe call.
|
|
369
|
+
*/
|
|
370
|
+
private _watchSessionState;
|
|
371
|
+
private _unwatchSessionState;
|
|
372
|
+
private _handleAutonomousDisconnect;
|
|
250
373
|
call(sessionId: string, method: string, params: unknown): Promise<unknown>;
|
|
374
|
+
private _dispatch;
|
|
251
375
|
cancel(sessionId: string): Promise<void>;
|
|
252
376
|
uiResponse(_response: UiResponseEvent): void;
|
|
253
377
|
on<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void;
|
|
@@ -265,90 +389,53 @@ declare class LedgerConnectorBase implements IConnector {
|
|
|
265
389
|
private _invalidateSession;
|
|
266
390
|
/**
|
|
267
391
|
* Replace an old session with a new one after app switch.
|
|
268
|
-
*
|
|
269
|
-
* and emits device-connect so the adapter updates its _sessions Map.
|
|
392
|
+
* Emits device-connect so the adapter updates its _sessions Map.
|
|
270
393
|
*/
|
|
271
394
|
private _replaceSession;
|
|
272
395
|
/**
|
|
273
|
-
* Light reset: clear signer/session state but keep DMK
|
|
396
|
+
* Light reset: clear signer/session state but keep DMK alive.
|
|
274
397
|
* Used by connect() retry — we want to re-discover with the same transport.
|
|
398
|
+
*
|
|
399
|
+
* Note: drops the device manager but tears down its RxJS subs first via
|
|
400
|
+
* disposeKeepingDmk(). Bare null-assignment would leak _listenSub /
|
|
401
|
+
* _discoverySub and double-scan after the next _initManagers().
|
|
275
402
|
*/
|
|
276
403
|
private _resetSignersAndSessions;
|
|
277
404
|
private _resetAll;
|
|
278
405
|
protected _emit<K extends ConnectorEventType>(event: K, data: ConnectorEventMap[K]): void;
|
|
279
|
-
private _wrapError;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* Manages device discovery, connection, and session tracking.
|
|
284
|
-
* Wraps DMK's Observable APIs into simpler imperative calls.
|
|
285
|
-
*/
|
|
286
|
-
declare class LedgerDeviceManager {
|
|
287
|
-
private readonly _dmk;
|
|
288
|
-
private readonly _discovered;
|
|
289
|
-
private readonly _sessions;
|
|
290
|
-
private readonly _sessionToDevice;
|
|
291
|
-
private _listenSub;
|
|
292
|
-
constructor(dmk: DeviceManagementKit);
|
|
293
406
|
/**
|
|
294
|
-
*
|
|
295
|
-
*
|
|
407
|
+
* Return a per-call ctx with the chain's Ledger app name pre-bound to
|
|
408
|
+
* wrapError, so chain handlers don't need to repeat `{ defaultAppName: 'X' }`
|
|
409
|
+
* at every catch site. Falls through unchanged for unknown methods.
|
|
296
410
|
*/
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
* Continuous listening: tracks device connect/disconnect via diffing.
|
|
300
|
-
*/
|
|
301
|
-
listen(onChange: (event: DeviceChangeEvent) => void): void;
|
|
302
|
-
stopListening(): void;
|
|
303
|
-
/**
|
|
304
|
-
* Trigger browser device selection (WebHID requestDevice).
|
|
305
|
-
* Starts discovery for a short period, then stops.
|
|
306
|
-
*/
|
|
307
|
-
/**
|
|
308
|
-
* Start BLE discovery if not already running.
|
|
309
|
-
* Does NOT stop — DMK keeps scanning in the background so that
|
|
310
|
-
* listenToAvailableDevices() always has fresh data.
|
|
311
|
-
*/
|
|
312
|
-
private _discoverySub;
|
|
313
|
-
requestDevice(): Promise<void>;
|
|
314
|
-
/** Connect to a previously discovered device. Returns sessionId. */
|
|
315
|
-
connect(deviceId: string): Promise<string>;
|
|
316
|
-
/** Disconnect a session. */
|
|
317
|
-
disconnect(sessionId: string): Promise<void>;
|
|
318
|
-
getSessionId(deviceId: string): string | undefined;
|
|
319
|
-
getDeviceId(sessionId: string): string | undefined;
|
|
320
|
-
/** Get the underlying DMK instance (needed by SignerManager). */
|
|
321
|
-
getDmk(): DeviceManagementKit;
|
|
322
|
-
stopDiscovery(): void;
|
|
323
|
-
dispose(): void;
|
|
411
|
+
private _ctxForMethod;
|
|
412
|
+
private _wrapError;
|
|
324
413
|
}
|
|
325
414
|
|
|
415
|
+
/** Optional context attached to the rejection when a canceller fires. */
|
|
416
|
+
interface CancelReason {
|
|
417
|
+
code?: number;
|
|
418
|
+
tag?: string;
|
|
419
|
+
message?: string;
|
|
420
|
+
}
|
|
326
421
|
/**
|
|
327
|
-
*
|
|
328
|
-
*
|
|
329
|
-
*/
|
|
330
|
-
type DmkDiscoveredDevice = DiscoveredDevice;
|
|
331
|
-
/**
|
|
332
|
-
* DMK DeviceAction — the Observable-based return type of all DMK signer methods.
|
|
422
|
+
* Convert a DMK DeviceAction (Observable-based) into a Promise.
|
|
423
|
+
* Handles pending -> completed/error state transitions and interaction callbacks.
|
|
333
424
|
*
|
|
334
|
-
*
|
|
335
|
-
*
|
|
336
|
-
*
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
*
|
|
341
|
-
*
|
|
425
|
+
* Tracks the last DMK step observed (e.g. `signer.eth.steps.blindSignTransactionFallback`)
|
|
426
|
+
* and attaches it to the rejected error as a non-enumerable `_lastStep` property,
|
|
427
|
+
* so upstream error classifiers can distinguish failure contexts (e.g. Blind signing
|
|
428
|
+
* disabled vs. generic Invalid data).
|
|
429
|
+
*
|
|
430
|
+
* @param timeoutMs Idle watchdog ms. Re-armed on each emission, paused
|
|
431
|
+
* during interactive pending. 0 disables. Default 65s
|
|
432
|
+
* (covers DMK's 60s + margin; we're a backstop only).
|
|
433
|
+
* @param onRegisterCanceller Optional callback that receives a function which, when
|
|
434
|
+
* called, unsubscribes and cancels the underlying DeviceAction
|
|
435
|
+
* (releases DMK's IntentQueue slot). Caller is responsible
|
|
436
|
+
* for invoking the canceller on timeout/abort scenarios.
|
|
342
437
|
*/
|
|
343
|
-
|
|
344
|
-
/** ETH address result — re-exported from DMK for backward compatibility. */
|
|
345
|
-
type SignerEvmAddress = Address;
|
|
346
|
-
/** ETH signature result — re-exported from DMK for backward compatibility. */
|
|
347
|
-
type SignerEvmSignature = Signature;
|
|
348
|
-
/** BTC address result (WalletAddress not exported from DMK top-level). */
|
|
349
|
-
interface SignerBtcAddress {
|
|
350
|
-
address: string;
|
|
351
|
-
}
|
|
438
|
+
declare function deviceActionToPromise<T>(action: DeviceAction<T>, onInteraction?: (interaction: string) => void, timeoutMs?: number, onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void): Promise<T>;
|
|
352
439
|
|
|
353
440
|
/**
|
|
354
441
|
* Wraps Ledger's SDK signer (Observable-based DeviceActions) into
|
|
@@ -363,7 +450,7 @@ declare class SignerEth {
|
|
|
363
450
|
* for the underlying DeviceAction. Caller can invoke it to release DMK's
|
|
364
451
|
* IntentQueue slot and unsubscribe from the action's observable.
|
|
365
452
|
*/
|
|
366
|
-
onRegisterCanceller?: (cancel: () => void) => void;
|
|
453
|
+
onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void;
|
|
367
454
|
getAddress(derivationPath: string, options?: {
|
|
368
455
|
checkOnDevice?: boolean;
|
|
369
456
|
}): Promise<SignerEvmAddress>;
|
|
@@ -376,8 +463,14 @@ type SignerEthBuilderFn = (args: {
|
|
|
376
463
|
dmk: DeviceManagementKit;
|
|
377
464
|
sessionId: string;
|
|
378
465
|
}) => {
|
|
466
|
+
withContextModule?(contextModule: ContextModule): {
|
|
467
|
+
build(): SignerEth$1;
|
|
468
|
+
};
|
|
379
469
|
build(): SignerEth$1;
|
|
380
470
|
} | Promise<{
|
|
471
|
+
withContextModule?(contextModule: ContextModule): {
|
|
472
|
+
build(): SignerEth$1;
|
|
473
|
+
};
|
|
381
474
|
build(): SignerEth$1;
|
|
382
475
|
}>;
|
|
383
476
|
/**
|
|
@@ -393,6 +486,8 @@ declare class SignerManager {
|
|
|
393
486
|
invalidate(_sessionId: string): void;
|
|
394
487
|
clearAll(): void;
|
|
395
488
|
private static _defaultBuilder;
|
|
489
|
+
private static _createContextModule;
|
|
490
|
+
static wrapBlindSigningReportNonBlocking<T extends ContextModule>(contextModule: T): T;
|
|
396
491
|
}
|
|
397
492
|
|
|
398
493
|
type BtcWallet = Parameters<SignerBtc$1['getWalletAddress']>[0];
|
|
@@ -406,7 +501,7 @@ type BtcMessageOptions = Parameters<SignerBtc$1['signMessage']>[2];
|
|
|
406
501
|
declare class SignerBtc {
|
|
407
502
|
private readonly _sdk;
|
|
408
503
|
onInteraction?: (interaction: string) => void;
|
|
409
|
-
onRegisterCanceller?: (cancel: () => void) => void;
|
|
504
|
+
onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void;
|
|
410
505
|
constructor(_sdk: SignerBtc$1);
|
|
411
506
|
getWalletAddress(wallet: BtcWallet, addressIndex: number, options?: {
|
|
412
507
|
checkOnDevice?: boolean;
|
|
@@ -452,7 +547,7 @@ type SolMsgOptions = Parameters<SignerSolana['signMessage']>[2];
|
|
|
452
547
|
declare class SignerSol {
|
|
453
548
|
private readonly _sdk;
|
|
454
549
|
onInteraction?: (interaction: string) => void;
|
|
455
|
-
onRegisterCanceller?: (cancel: () => void) => void;
|
|
550
|
+
onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void;
|
|
456
551
|
constructor(_sdk: SignerSolana);
|
|
457
552
|
/**
|
|
458
553
|
* Get the Solana address (base58-encoded Ed25519 public key) at the given derivation path.
|
|
@@ -493,24 +588,6 @@ declare class DmkTransport extends Transport {
|
|
|
493
588
|
close(): Promise<void>;
|
|
494
589
|
}
|
|
495
590
|
|
|
496
|
-
/**
|
|
497
|
-
* Convert a DMK DeviceAction (Observable-based) into a Promise.
|
|
498
|
-
* Handles pending -> completed/error state transitions and interaction callbacks.
|
|
499
|
-
*
|
|
500
|
-
* Tracks the last DMK step observed (e.g. `signer.eth.steps.blindSignTransactionFallback`)
|
|
501
|
-
* and attaches it to the rejected error as a non-enumerable `_lastStep` property,
|
|
502
|
-
* so upstream error classifiers can distinguish failure contexts (e.g. Blind signing
|
|
503
|
-
* disabled vs. generic Invalid data).
|
|
504
|
-
*
|
|
505
|
-
* @param timeoutMs Timeout in ms. Resets each time the Observable emits (device is alive).
|
|
506
|
-
* Pass 0 to disable. Default: 30s.
|
|
507
|
-
* @param onRegisterCanceller Optional callback that receives a function which, when
|
|
508
|
-
* called, unsubscribes and cancels the underlying DeviceAction
|
|
509
|
-
* (releases DMK's IntentQueue slot). Caller is responsible
|
|
510
|
-
* for invoking the canceller on timeout/abort scenarios.
|
|
511
|
-
*/
|
|
512
|
-
declare function deviceActionToPromise<T>(action: DeviceAction<T>, onInteraction?: (interaction: string) => void, timeoutMs?: number, onRegisterCanceller?: (cancel: () => void) => void): Promise<T>;
|
|
513
|
-
|
|
514
591
|
interface AppManagerOptions {
|
|
515
592
|
waitMs?: number;
|
|
516
593
|
maxRetries?: number;
|
|
@@ -540,9 +617,16 @@ declare class AppManager {
|
|
|
540
617
|
* 5. Poll until the device confirms the target app is running.
|
|
541
618
|
*/
|
|
542
619
|
/**
|
|
543
|
-
* @param onConfirmOnDevice Called
|
|
544
|
-
*
|
|
545
|
-
*
|
|
620
|
+
* @param onConfirmOnDevice Called BEFORE OpenAppCommand is issued — the
|
|
621
|
+
* device is about to display "Open <app>" on screen and wait for the
|
|
622
|
+
* user's button press. UI consumers should show their "open app" prompt
|
|
623
|
+
* in response. NOT called when the target app is already open (no user
|
|
624
|
+
* interaction needed in that case).
|
|
625
|
+
*
|
|
626
|
+
* Important: OpenAppCommand is blocking. It does not resolve until the user
|
|
627
|
+
* has physically confirmed on the device, so anything that runs AFTER
|
|
628
|
+
* `await this._openApp(...)` lands AFTER the prompt is already gone.
|
|
629
|
+
* Hence the callback must fire BEFORE that await.
|
|
546
630
|
*/
|
|
547
631
|
ensureAppOpen(sessionId: string, targetAppName: string, onConfirmOnDevice?: () => void): Promise<void>;
|
|
548
632
|
private _getCurrentApp;
|
|
@@ -557,48 +641,59 @@ declare class AppManager {
|
|
|
557
641
|
private _wait;
|
|
558
642
|
}
|
|
559
643
|
|
|
560
|
-
/**
|
|
561
|
-
* Ledger-specific Failure: adds `appName` for "the currently-open app" — a
|
|
562
|
-
* Ledger hardware concept not shared with other vendors, so it lives here
|
|
563
|
-
* rather than in core's generic Failure.
|
|
564
|
-
*/
|
|
565
644
|
type LedgerFailure = Omit<Failure, 'payload'> & {
|
|
566
645
|
payload: Failure['payload'] & {
|
|
567
646
|
appName?: string;
|
|
647
|
+
_tag?: string;
|
|
568
648
|
};
|
|
569
649
|
};
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
declare function ledgerFailure(code: HardwareErrorCode, error: string, appName?: string): LedgerFailure;
|
|
575
|
-
/** Check if an error (or any error in its chain) represents a locked Ledger device. */
|
|
650
|
+
interface WrapErrorOptions {
|
|
651
|
+
/** Fallback when err has no `appName` (DMK signer errors don't carry it). */
|
|
652
|
+
defaultAppName?: string;
|
|
653
|
+
}
|
|
654
|
+
declare function ledgerFailure(code: HardwareErrorCode, error: string, appName?: string, tag?: string, params?: Record<string, unknown>): LedgerFailure;
|
|
576
655
|
declare function isDeviceLockedError(err: unknown): boolean;
|
|
577
656
|
/**
|
|
578
|
-
* Map a Ledger DMK error to a HardwareErrorCode and human-readable message
|
|
579
|
-
*
|
|
657
|
+
* Map a Ledger DMK error to a HardwareErrorCode and human-readable message.
|
|
658
|
+
* `opts.defaultAppName` fills `appName` when the raw error doesn't carry it
|
|
659
|
+
* (DMK signer errors don't).
|
|
580
660
|
*/
|
|
581
|
-
declare function mapLedgerError(err: unknown): {
|
|
661
|
+
declare function mapLedgerError(err: unknown, opts?: WrapErrorOptions): {
|
|
582
662
|
code: HardwareErrorCode;
|
|
583
663
|
message: string;
|
|
584
664
|
appName?: string;
|
|
585
665
|
};
|
|
586
666
|
|
|
587
667
|
/**
|
|
588
|
-
*
|
|
589
|
-
*
|
|
590
|
-
* Off by default. Toggle programmatically via `setDebugEnabled(true)`.
|
|
668
|
+
* SDK-global event bus. Per-runtime singleton — each process subscribes
|
|
669
|
+
* independently; cross-process hosts forward events over their own IPC.
|
|
591
670
|
*/
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
671
|
+
type SdkLogEvent = {
|
|
672
|
+
type: 'log';
|
|
673
|
+
level: 'debug' | 'error';
|
|
674
|
+
/** Pre-stringified payload. */
|
|
675
|
+
message: string;
|
|
676
|
+
};
|
|
677
|
+
/** Add new variants here; hosts dispatch on `event.type`. */
|
|
678
|
+
type SdkEvent = SdkLogEvent;
|
|
679
|
+
type SdkEventListener = (event: SdkEvent) => void;
|
|
680
|
+
declare function onSdkEvent(listener: SdkEventListener): () => void;
|
|
681
|
+
declare function offSdkEvent(listener: SdkEventListener): void;
|
|
682
|
+
|
|
683
|
+
declare function debugLog(...args: unknown[]): void;
|
|
596
684
|
|
|
597
685
|
/**
|
|
598
|
-
*
|
|
599
|
-
*
|
|
600
|
-
*
|
|
686
|
+
* Ledger DMK transport identifiers that represent BLE devices.
|
|
687
|
+
*
|
|
688
|
+
* Known today:
|
|
689
|
+
* - "BLE": generic/web BLE descriptors
|
|
690
|
+
* - "RN_BLE": @ledgerhq/device-transport-kit-react-native-ble
|
|
691
|
+
*
|
|
692
|
+
* Keep the suffix check here so future DMK BLE transports (for example
|
|
693
|
+
* "FOO_BLE") are handled in one place instead of scattering string checks.
|
|
601
694
|
*/
|
|
602
|
-
declare function
|
|
695
|
+
declare function isLedgerDmkBleTransport(transport?: string): boolean;
|
|
696
|
+
declare function isLedgerBleConnectionType(connectionType?: ConnectionType): boolean;
|
|
697
|
+
declare function isLedgerBleDescriptor(connectionType: ConnectionType, descriptor: DeviceDescriptor): boolean;
|
|
603
698
|
|
|
604
|
-
export { AppManager, type DeviceActionState, type DmkDiscoveredDevice, DmkTransport, LedgerAdapter, LedgerConnectorBase, type LedgerConnectorBaseOptions, LedgerDeviceManager, type LedgerFailure, SignerBtc, type SignerBtcAddress, SignerEth, type SignerEvmAddress, type SignerEvmSignature, SignerManager, SignerSol, type TransportFactory, deviceActionToPromise,
|
|
699
|
+
export { AppManager, type DeviceActionState, type DmkDiscoveredDevice, DmkTransport, LedgerAdapter, LedgerConnectorBase, type LedgerConnectorBaseOptions, LedgerDeviceManager, type LedgerFailure, type SdkEvent, type SdkEventListener, type SdkLogEvent, SignerBtc, type SignerBtcAddress, SignerEth, type SignerEvmAddress, type SignerEvmSignature, SignerManager, SignerSol, type TransportFactory, debugLog, deviceActionToPromise, isDeviceLockedError, isLedgerBleConnectionType, isLedgerBleDescriptor, isLedgerDmkBleTransport, ledgerFailure, mapLedgerError, offSdkEvent, onSdkEvent };
|