UNPKG

8.25 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";
6export { TransportError, TransportStatusError, StatusCodes, getAltStatusMessage, };
7/**
8 */
9export type Subscription = {
10 unsubscribe: () => void;
11};
12/**
13 */
14export type Device = any;
15export type DescriptorEventType = "add" | "remove";
16/**
17 * A "descriptor" is a parameter that is specific to the implementation, and can be an ID, file path, or URL.
18 * type: add or remove event
19 * descriptor: a parameter that can be passed to open(descriptor)
20 * deviceModel: device info on the model (is it a nano s, nano x, ...)
21 * device: transport specific device info
22 */
23export interface DescriptorEvent<Descriptor> {
24 type: DescriptorEventType;
25 descriptor: Descriptor;
26 deviceModel?: DeviceModel | null | undefined;
27 device?: Device;
28}
29/**
30 * Observer generic type, following the Observer pattern
31 */
32export type Observer<EventType, EventError = unknown> = Readonly<{
33 next: (event: EventType) => unknown;
34 error: (e: EventError) => unknown;
35 complete: () => unknown;
36}>;
37/**
38 * The Transport class defines a generic interface for communicating with a Ledger hardware wallet.
39 * There are different kind of transports based on the technology (channels like U2F, HID, Bluetooth, Webusb) and environment (Node, Web,...).
40 * It is an abstract class that needs to be implemented.
41 */
42export default class Transport {
43 exchangeTimeout: number;
44 unresponsiveTimeout: number;
45 deviceModel: DeviceModel | null | undefined;
46 /**
47 * Check if the transport is supported on the current platform/browser.
48 * @returns {Promise<boolean>} A promise that resolves with a boolean indicating support.
49 */
50 static readonly isSupported: () => Promise<boolean>;
51 /**
52 * List all available descriptors for the transport.
53 * For a better granularity, checkout `listen()`.
54 *
55 * @returns {Promise<Array<any>>} A promise that resolves with an array of descriptors.
56 * @example
57 * TransportFoo.list().then(descriptors => ...)
58 */
59 static readonly list: () => Promise<Array<any>>;
60 /**
61 * Listen for device events for the transport. The method takes an observer of DescriptorEvent and returns a Subscription.
62 * 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.
63 * 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.
64 * @param {Observer<DescriptorEvent<any>>} observer - An object with "next", "error", and "complete" functions, following the observer pattern.
65 * @returns {Subscription} A Subscription object on which you can call ".unsubscribe()" to stop listening to descriptors.
66 * @example
67 const sub = TransportFoo.listen({
68 next: e => {
69 if (e.type==="add") {
70 sub.unsubscribe();
71 const transport = await TransportFoo.open(e.descriptor);
72 ...
73 }
74 },
75 error: error => {},
76 complete: () => {}
77 })
78 */
79 static readonly listen: (observer: Observer<DescriptorEvent<any>>) => Subscription;
80 /**
81 * Attempt to create a Transport instance with a specific descriptor.
82 * @param {any} descriptor - The descriptor to open the transport with.
83 * @param {number} timeout - An optional timeout for the transport connection.
84 * @returns {Promise<Transport>} A promise that resolves with a Transport instance.
85 * @example
86 TransportFoo.open(descriptor).then(transport => ...)
87 */
88 static readonly open: (descriptor?: any, timeout?: number) => Promise<Transport>;
89 /**
90 * Send data to the device using a low level API.
91 * It's recommended to use the "send" method for a higher level API.
92 * @param {Buffer} apdu - The data to send.
93 * @returns {Promise<Buffer>} A promise that resolves with the response data from the device.
94 */
95 exchange(_apdu: Buffer): Promise<Buffer>;
96 /**
97 * Send apdus in batch to the device using a low level API.
98 * The default implementation is to call exchange for each apdu.
99 * @param {Array<Buffer>} apdus - array of apdus to send.
100 * @param {Observer<Buffer>} observer - an observer that will receive the response of each apdu.
101 * @returns {Subscription} A Subscription object on which you can call ".unsubscribe()" to stop sending apdus.
102 */
103 exchangeBulk(apdus: Buffer[], observer: Observer<Buffer>): Subscription;
104 /**
105 * Set the "scramble key" for the next data exchanges with the device.
106 * Each app can have a different scramble key and it is set internally during instantiation.
107 * @param {string} key - The scramble key to set.
108 * @deprecated This method is no longer needed for modern transports and should be migrated away from.
109 */
110 setScrambleKey(_key: string): void;
111 /**
112 * Close the connection with the device.
113 * @returns {Promise<void>} A promise that resolves when the transport is closed.
114 */
115 close(): Promise<void>;
116 _events: EventEmitter;
117 /**
118 * Listen for an event on the transport instance.
119 * Transport implementations may have specific events. Common events include:
120 * "disconnect" : triggered when the transport is disconnected.
121 * @param {string} eventName - The name of the event to listen for.
122 * @param {(...args: Array<any>) => any} cb - The callback function to be invoked when the event occurs.
123 */
124 on(eventName: string, cb: (...args: Array<any>) => any): void;
125 /**
126 * Stop listening to an event on an instance of transport.
127 */
128 off(eventName: string, cb: (...args: Array<any>) => any): void;
129 emit(event: string, ...args: any): void;
130 /**
131 * Enable or not logs of the binary exchange
132 */
133 setDebugMode(): void;
134 /**
135 * Set a timeout (in milliseconds) for the exchange call. Only some transport might implement it. (e.g. U2F)
136 */
137 setExchangeTimeout(exchangeTimeout: number): void;
138 /**
139 * Define the delay before emitting "unresponsive" on an exchange that does not respond
140 */
141 setExchangeUnresponsiveTimeout(unresponsiveTimeout: number): void;
142 /**
143 * Send data to the device using the higher level API.
144 * @param {number} cla - The instruction class for the command.
145 * @param {number} ins - The instruction code for the command.
146 * @param {number} p1 - The first parameter for the instruction.
147 * @param {number} p2 - The second parameter for the instruction.
148 * @param {Buffer} data - The data to be sent. Defaults to an empty buffer.
149 * @param {Array<number>} statusList - A list of acceptable status codes for the response. Defaults to [StatusCodes.OK].
150 * @returns {Promise<Buffer>} A promise that resolves with the response data from the device.
151 */
152 send: (cla: number, ins: number, p1: number, p2: number, data?: Buffer, statusList?: Array<number>) => Promise<Buffer>;
153 /**
154 * create() allows to open the first descriptor available or
155 * throw if there is none or if timeout is reached.
156 * This is a light helper, alternative to using listen() and open() (that you may need for any more advanced usecase)
157 * @example
158 TransportFoo.create().then(transport => ...)
159 */
160 static create(openTimeout?: number, listenTimeout?: number): Promise<Transport>;
161 exchangeBusyPromise: Promise<void> | null | undefined;
162 exchangeAtomicImpl: (f: () => Promise<Buffer | void>) => Promise<Buffer | void>;
163 decorateAppAPIMethods(self: Record<string, any>, methods: Array<string>, scrambleKey: string): void;
164 _appAPIlock: string | null;
165 decorateAppAPIMethod<R, A extends any[]>(methodName: string, f: (...args: A) => Promise<R>, ctx: any, scrambleKey: string): (...args: A) => Promise<R>;
166 static ErrorMessage_ListenTimeout: string;
167 static ErrorMessage_NoDeviceFound: string;
168}
169//# sourceMappingURL=Transport.d.ts.map
\No newline at end of file