UNPKG

10.9 kBTypeScriptView Raw
1/// <reference types="node" />
2/// <reference types="node" />
3import EventEmitter from "events";
4import type { DeviceModel } from "@ledgerhq/devices";
5import { TransportError, StatusCodes, getAltStatusMessage, TransportStatusError } from "@ledgerhq/errors";
6import { LocalTracer, TraceContext, LogType } from "@ledgerhq/logs";
7export { TransportError, TransportStatusError, StatusCodes, getAltStatusMessage };
8/**
9 */
10export type Subscription = {
11 unsubscribe: () => void;
12};
13/**
14 */
15export type Device = any;
16export type DescriptorEventType = "add" | "remove";
17/**
18 * A "descriptor" is a parameter that is specific to the implementation, and can be an ID, file path, or URL.
19 * type: add or remove event
20 * descriptor: a parameter that can be passed to open(descriptor)
21 * deviceModel: device info on the model (is it a nano s, nano x, ...)
22 * device: transport specific device info
23 */
24export interface DescriptorEvent<Descriptor> {
25 type: DescriptorEventType;
26 descriptor: Descriptor;
27 deviceModel?: DeviceModel | null | undefined;
28 device?: Device;
29}
30/**
31 * Observer generic type, following the Observer pattern
32 */
33export type Observer<EventType, EventError = unknown> = Readonly<{
34 next: (event: EventType) => unknown;
35 error: (e: EventError) => unknown;
36 complete: () => unknown;
37}>;
38/**
39 * The Transport class defines a generic interface for communicating with a Ledger hardware wallet.
40 * There are different kind of transports based on the technology (channels like U2F, HID, Bluetooth, Webusb) and environment (Node, Web,...).
41 * It is an abstract class that needs to be implemented.
42 */
43export default class Transport {
44 exchangeTimeout: number;
45 unresponsiveTimeout: number;
46 deviceModel: DeviceModel | null | undefined;
47 tracer: LocalTracer;
48 constructor({ context, logType }?: {
49 context?: TraceContext;
50 logType?: LogType;
51 });
52 /**
53 * Check if the transport is supported on the current platform/browser.
54 * @returns {Promise<boolean>} A promise that resolves with a boolean indicating support.
55 */
56 static readonly isSupported: () => Promise<boolean>;
57 /**
58 * List all available descriptors for the transport.
59 * For a better granularity, checkout `listen()`.
60 *
61 * @returns {Promise<Array<any>>} A promise that resolves with an array of descriptors.
62 * @example
63 * TransportFoo.list().then(descriptors => ...)
64 */
65 static readonly list: () => Promise<Array<any>>;
66 /**
67 * Listen for device events for the transport. The method takes an observer of DescriptorEvent and returns a Subscription.
68 * A DescriptorEvent is an object containing a "descriptor" and a "type" field. The "type" field can be "add" or "remove", and the "descriptor" field can be passed to the "open" method.
69 * The "listen" method will first emit all currently connected devices and then will emit events as they occur, such as when a USB device is plugged in or a Bluetooth device becomes discoverable.
70 * @param {Observer<DescriptorEvent<any>>} observer - An object with "next", "error", and "complete" functions, following the observer pattern.
71 * @returns {Subscription} A Subscription object on which you can call ".unsubscribe()" to stop listening to descriptors.
72 * @example
73 const sub = TransportFoo.listen({
74 next: e => {
75 if (e.type==="add") {
76 sub.unsubscribe();
77 const transport = await TransportFoo.open(e.descriptor);
78 ...
79 }
80 },
81 error: error => {},
82 complete: () => {}
83 })
84 */
85 static readonly listen: (observer: Observer<DescriptorEvent<any>>) => Subscription;
86 /**
87 * Attempt to create a Transport instance with a specific descriptor.
88 * @param {any} descriptor - The descriptor to open the transport with.
89 * @param {number} timeout - An optional timeout for the transport connection.
90 * @param {TraceContext} context Optional tracing/log context
91 * @returns {Promise<Transport>} A promise that resolves with a Transport instance.
92 * @example
93 TransportFoo.open(descriptor).then(transport => ...)
94 */
95 static readonly open: (descriptor?: any, timeoutMs?: number, context?: TraceContext) => Promise<Transport>;
96 /**
97 * Send data to the device using a low level API.
98 * It's recommended to use the "send" method for a higher level API.
99 * @param {Buffer} apdu - The data to send.
100 * @param {Object} options - Contains optional options for the exchange function
101 * - abortTimeoutMs: stop the exchange after a given timeout. Another timeout exists
102 * to detect unresponsive device (see `unresponsiveTimeout`). This timeout aborts the exchange.
103 * @returns {Promise<Buffer>} A promise that resolves with the response data from the device.
104 */
105 exchange(_apdu: Buffer, { abortTimeoutMs: _abortTimeoutMs }?: {
106 abortTimeoutMs?: number;
107 }): Promise<Buffer>;
108 /**
109 * Send apdus in batch to the device using a low level API.
110 * The default implementation is to call exchange for each apdu.
111 * @param {Array<Buffer>} apdus - array of apdus to send.
112 * @param {Observer<Buffer>} observer - an observer that will receive the response of each apdu.
113 * @returns {Subscription} A Subscription object on which you can call ".unsubscribe()" to stop sending apdus.
114 */
115 exchangeBulk(apdus: Buffer[], observer: Observer<Buffer>): Subscription;
116 /**
117 * Set the "scramble key" for the next data exchanges with the device.
118 * Each app can have a different scramble key and it is set internally during instantiation.
119 * @param {string} key - The scramble key to set.
120 * deprecated This method is no longer needed for modern transports and should be migrated away from.
121 * no @ before deprecated as it breaks documentationjs on version 14.0.2
122 * https://github.com/documentationjs/documentation/issues/1596
123 */
124 setScrambleKey(_key: string): void;
125 /**
126 * Close the connection with the device.
127 *
128 * Note: for certain transports (hw-transport-node-hid-singleton for ex), once the promise resolved,
129 * the transport instance is actually still cached, and the device is disconnected only after a defined timeout.
130 * But for the consumer of the Transport, this does not matter and it can consider the transport to be closed.
131 *
132 * @returns {Promise<void>} A promise that resolves when the transport is closed.
133 */
134 close(): Promise<void>;
135 _events: EventEmitter<[never]>;
136 /**
137 * Listen for an event on the transport instance.
138 * Transport implementations may have specific events. Common events include:
139 * "disconnect" : triggered when the transport is disconnected.
140 * @param {string} eventName - The name of the event to listen for.
141 * @param {(...args: Array<any>) => any} cb - The callback function to be invoked when the event occurs.
142 */
143 on(eventName: string, cb: (...args: Array<any>) => any): void;
144 /**
145 * Stop listening to an event on an instance of transport.
146 */
147 off(eventName: string, cb: (...args: Array<any>) => any): void;
148 emit(event: string, ...args: any): void;
149 /**
150 * Enable or not logs of the binary exchange
151 */
152 setDebugMode(): void;
153 /**
154 * Set a timeout (in milliseconds) for the exchange call. Only some transport might implement it. (e.g. U2F)
155 */
156 setExchangeTimeout(exchangeTimeout: number): void;
157 /**
158 * Define the delay before emitting "unresponsive" on an exchange that does not respond
159 */
160 setExchangeUnresponsiveTimeout(unresponsiveTimeout: number): void;
161 /**
162 * Send data to the device using the higher level API.
163 *
164 * @param {number} cla - The instruction class for the command.
165 * @param {number} ins - The instruction code for the command.
166 * @param {number} p1 - The first parameter for the instruction.
167 * @param {number} p2 - The second parameter for the instruction.
168 * @param {Buffer} data - The data to be sent. Defaults to an empty buffer.
169 * @param {Array<number>} statusList - A list of acceptable status codes for the response. Defaults to [StatusCodes.OK].
170 * @param {Object} options - Contains optional options for the exchange function
171 * - abortTimeoutMs: stop the send after a given timeout. Another timeout exists
172 * to detect unresponsive device (see `unresponsiveTimeout`). This timeout aborts the exchange.
173 * @returns {Promise<Buffer>} A promise that resolves with the response data from the device.
174 */
175 send: (cla: number, ins: number, p1: number, p2: number, data?: Buffer, statusList?: Array<number>, { abortTimeoutMs }?: {
176 abortTimeoutMs?: number | undefined;
177 }) => Promise<Buffer>;
178 /**
179 * create() allows to open the first descriptor available or
180 * throw if there is none or if timeout is reached.
181 * This is a light helper, alternative to using listen() and open() (that you may need for any more advanced usecase)
182 * @example
183 TransportFoo.create().then(transport => ...)
184 */
185 static create(openTimeout?: number, listenTimeout?: number): Promise<Transport>;
186 exchangeBusyPromise: Promise<void> | null | undefined;
187 /**
188 * Wrapper to make an exchange "atomic" (blocking any other exchange)
189 *
190 * It also handles "unresponsiveness" by emitting "unresponsive" and "responsive" events.
191 *
192 * @param f The exchange job, using the transport to run
193 * @returns a Promise resolving with the output of the given job
194 */
195 exchangeAtomicImpl<Output>(f: () => Promise<Output>): Promise<Output>;
196 decorateAppAPIMethods(self: Record<string, any>, methods: Array<string>, scrambleKey: string): void;
197 _appAPIlock: string | null;
198 decorateAppAPIMethod<R, A extends any[]>(methodName: string, f: (...args: A) => Promise<R>, ctx: any, scrambleKey: string): (...args: A) => Promise<R>;
199 /**
200 * Sets the context used by the logging/tracing mechanism
201 *
202 * Useful when re-using (cached) the same Transport instance,
203 * but with a new tracing context.
204 *
205 * @param context A TraceContext, that can undefined to reset the context
206 */
207 setTraceContext(context?: TraceContext): void;
208 /**
209 * Updates the context used by the logging/tracing mechanism
210 *
211 * The update only overrides the key-value that are already defined in the current context.
212 *
213 * @param contextToAdd A TraceContext that will be added to the current context
214 */
215 updateTraceContext(contextToAdd: TraceContext): void;
216 /**
217 * Gets the tracing context of the transport instance
218 */
219 getTraceContext(): TraceContext | undefined;
220 static ErrorMessage_ListenTimeout: string;
221 static ErrorMessage_NoDeviceFound: string;
222}
223//# sourceMappingURL=Transport.d.ts.map
\No newline at end of file