Socket
Socket
Sign inDemoInstall

@ledgerhq/hw-transport-webusb

Package Overview
Dependencies
Maintainers
20
Versions
288
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ledgerhq/hw-transport-webusb - npm Package Compare versions

Comparing version 6.27.13 to 6.27.14-next.0

9

CHANGELOG.md
# @ledgerhq/hw-transport-webusb
## 6.27.14-next.0
### Patch Changes
- Updated dependencies [[`87d2349fd8`](https://github.com/LedgerHQ/ledger-live/commit/87d2349fd835e5deb39d1ee8dfcf3539f4195472)]:
- @ledgerhq/errors@6.12.5-next.0
- @ledgerhq/devices@8.0.2-next.0
- @ledgerhq/hw-transport@6.28.3-next.0
## 6.27.13

@@ -4,0 +13,0 @@

412

lib-es/TransportWebUSB.js

@@ -1,16 +0,1 @@

var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {

@@ -25,29 +10,2 @@ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }

};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
import Transport from "@ledgerhq/hw-transport";

@@ -59,4 +17,4 @@ import hidFraming from "@ledgerhq/devices/hid-framing";

import { getLedgerDevices, getFirstLedgerDevice, requestLedgerDevice, isSupported, } from "./webusb";
var configurationValue = 1;
var endpointNumber = 3;
const configurationValue = 1;
const endpointNumber = 3;
/**

@@ -69,19 +27,17 @@ * WebUSB Transport implementation

*/
var TransportWebUSB = /** @class */ (function (_super) {
__extends(TransportWebUSB, _super);
function TransportWebUSB(device, interfaceNumber) {
var _this = _super.call(this) || this;
_this.channel = Math.floor(Math.random() * 0xffff);
_this.packetSize = 64;
_this._disconnectEmitted = false;
_this._emitDisconnect = function (e) {
if (_this._disconnectEmitted)
export default class TransportWebUSB extends Transport {
constructor(device, interfaceNumber) {
super();
this.channel = Math.floor(Math.random() * 0xffff);
this.packetSize = 64;
this._disconnectEmitted = false;
this._emitDisconnect = (e) => {
if (this._disconnectEmitted)
return;
_this._disconnectEmitted = true;
_this.emit("disconnect", e);
this._disconnectEmitted = true;
this.emit("disconnect", e);
};
_this.device = device;
_this.interfaceNumber = interfaceNumber;
_this.deviceModel = identifyUSBProductId(device.productId);
return _this;
this.device = device;
this.interfaceNumber = interfaceNumber;
this.deviceModel = identifyUSBProductId(device.productId);
}

@@ -91,113 +47,65 @@ /**

*/
TransportWebUSB.request = function () {
return __awaiter(this, void 0, void 0, function () {
var device;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, requestLedgerDevice()];
case 1:
device = _a.sent();
return [2 /*return*/, TransportWebUSB.open(device)];
}
});
static request() {
return __awaiter(this, void 0, void 0, function* () {
const device = yield requestLedgerDevice();
return TransportWebUSB.open(device);
});
};
}
/**
* Similar to create() except it will never display the device permission (it returns a Promise<?Transport>, null if it fails to find a device).
*/
TransportWebUSB.openConnected = function () {
return __awaiter(this, void 0, void 0, function () {
var devices;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, getLedgerDevices()];
case 1:
devices = _a.sent();
if (devices.length === 0)
return [2 /*return*/, null];
return [2 /*return*/, TransportWebUSB.open(devices[0])];
}
});
static openConnected() {
return __awaiter(this, void 0, void 0, function* () {
const devices = yield getLedgerDevices();
if (devices.length === 0)
return null;
return TransportWebUSB.open(devices[0]);
});
};
}
/**
* Create a Ledger transport with a USBDevice
*/
TransportWebUSB.open = function (device) {
return __awaiter(this, void 0, void 0, function () {
var iface, interfaceNumber, e_1, transport, onDisconnect;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, device.open()];
case 1:
_a.sent();
if (!(device.configuration === null)) return [3 /*break*/, 3];
return [4 /*yield*/, device.selectConfiguration(configurationValue)];
case 2:
_a.sent();
_a.label = 3;
case 3: return [4 /*yield*/, gracefullyResetDevice(device)];
case 4:
_a.sent();
iface = device.configurations[0].interfaces.find(function (_a) {
var alternates = _a.alternates;
return alternates.some(function (a) { return a.interfaceClass === 255; });
});
if (!iface) {
throw new TransportInterfaceNotAvailable("No WebUSB interface found for your Ledger device. Please upgrade firmware or contact techsupport.");
}
interfaceNumber = iface.interfaceNumber;
_a.label = 5;
case 5:
_a.trys.push([5, 7, , 9]);
return [4 /*yield*/, device.claimInterface(interfaceNumber)];
case 6:
_a.sent();
return [3 /*break*/, 9];
case 7:
e_1 = _a.sent();
return [4 /*yield*/, device.close()];
case 8:
_a.sent();
throw new TransportInterfaceNotAvailable(e_1.message);
case 9:
transport = new TransportWebUSB(device, interfaceNumber);
onDisconnect = function (e) {
if (device === e.device) {
// $FlowFixMe
navigator.usb.removeEventListener("disconnect", onDisconnect);
transport._emitDisconnect(new DisconnectedDevice());
}
};
// $FlowFixMe
navigator.usb.addEventListener("disconnect", onDisconnect);
return [2 /*return*/, transport];
static open(device) {
return __awaiter(this, void 0, void 0, function* () {
yield device.open();
if (device.configuration === null) {
yield device.selectConfiguration(configurationValue);
}
yield gracefullyResetDevice(device);
const iface = device.configurations[0].interfaces.find(({ alternates }) => alternates.some((a) => a.interfaceClass === 255));
if (!iface) {
throw new TransportInterfaceNotAvailable("No WebUSB interface found for your Ledger device. Please upgrade firmware or contact techsupport.");
}
const interfaceNumber = iface.interfaceNumber;
try {
yield device.claimInterface(interfaceNumber);
}
catch (e) {
yield device.close();
throw new TransportInterfaceNotAvailable(e.message);
}
const transport = new TransportWebUSB(device, interfaceNumber);
const onDisconnect = (e) => {
if (device === e.device) {
// $FlowFixMe
navigator.usb.removeEventListener("disconnect", onDisconnect);
transport._emitDisconnect(new DisconnectedDevice());
}
});
};
// $FlowFixMe
navigator.usb.addEventListener("disconnect", onDisconnect);
return transport;
});
};
}
/**
* Release the transport device
*/
TransportWebUSB.prototype.close = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.exchangeBusyPromise];
case 1:
_a.sent();
return [4 /*yield*/, this.device.releaseInterface(this.interfaceNumber)];
case 2:
_a.sent();
return [4 /*yield*/, gracefullyResetDevice(this.device)];
case 3:
_a.sent();
return [4 /*yield*/, this.device.close()];
case 4:
_a.sent();
return [2 /*return*/];
}
});
close() {
return __awaiter(this, void 0, void 0, function* () {
yield this.exchangeBusyPromise;
yield this.device.releaseInterface(this.interfaceNumber);
yield gracefullyResetDevice(this.device);
yield this.device.close();
});
};
}
/**

@@ -208,122 +116,90 @@ * Exchange with the device using APDU protocol.

*/
TransportWebUSB.prototype.exchange = function (apdu) {
return __awaiter(this, void 0, void 0, function () {
var b;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.exchangeAtomicImpl(function () { return __awaiter(_this, void 0, void 0, function () {
var _a, channel, packetSize, framing, blocks, i, result, acc, r, buffer;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_a = this, channel = _a.channel, packetSize = _a.packetSize;
log("apdu", "=> " + apdu.toString("hex"));
framing = hidFraming(channel, packetSize);
blocks = framing.makeBlocks(apdu);
i = 0;
_b.label = 1;
case 1:
if (!(i < blocks.length)) return [3 /*break*/, 4];
return [4 /*yield*/, this.device.transferOut(endpointNumber, blocks[i])];
case 2:
_b.sent();
_b.label = 3;
case 3:
i++;
return [3 /*break*/, 1];
case 4:
if (!!(result = framing.getReducedResult(acc))) return [3 /*break*/, 6];
return [4 /*yield*/, this.device.transferIn(endpointNumber, packetSize)];
case 5:
r = _b.sent();
buffer = Buffer.from(r.data.buffer);
acc = framing.reduceResponse(acc, buffer);
return [3 /*break*/, 4];
case 6:
log("apdu", "<= " + result.toString("hex"));
return [2 /*return*/, result];
}
});
}); })["catch"](function (e) {
if (e && e.message && e.message.includes("disconnected")) {
_this._emitDisconnect(e);
throw new DisconnectedDeviceDuringOperation(e.message);
}
throw e;
})];
case 1:
b = _a.sent();
return [2 /*return*/, b];
exchange(apdu) {
return __awaiter(this, void 0, void 0, function* () {
const b = yield this.exchangeAtomicImpl(() => __awaiter(this, void 0, void 0, function* () {
const { channel, packetSize } = this;
log("apdu", "=> " + apdu.toString("hex"));
const framing = hidFraming(channel, packetSize);
// Write...
const blocks = framing.makeBlocks(apdu);
for (let i = 0; i < blocks.length; i++) {
yield this.device.transferOut(endpointNumber, blocks[i]);
}
// Read...
let result;
let acc;
while (!(result = framing.getReducedResult(acc))) {
const r = yield this.device.transferIn(endpointNumber, packetSize);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const buffer = Buffer.from(r.data.buffer);
acc = framing.reduceResponse(acc, buffer);
}
log("apdu", "<= " + result.toString("hex"));
return result;
})).catch((e) => {
if (e && e.message && e.message.includes("disconnected")) {
this._emitDisconnect(e);
throw new DisconnectedDeviceDuringOperation(e.message);
}
throw e;
});
return b;
});
};
TransportWebUSB.prototype.setScrambleKey = function () { };
/**
* Check if WebUSB transport is supported.
*/
TransportWebUSB.isSupported = isSupported;
/**
* List the WebUSB devices that was previously authorized by the user.
*/
TransportWebUSB.list = getLedgerDevices;
/**
* Actively listen to WebUSB devices and emit ONE device
* that was either accepted before, if not it will trigger the native permission UI.
*
* Important: it must be called in the context of a UI click!
*/
TransportWebUSB.listen = function (observer) {
var unsubscribed = false;
getFirstLedgerDevice().then(function (device) {
if (!unsubscribed) {
var deviceModel = identifyUSBProductId(device.productId);
observer.next({
type: "add",
descriptor: device,
deviceModel: deviceModel
});
observer.complete();
}
}, function (error) {
if (window.DOMException &&
error instanceof window.DOMException &&
error.code === 18) {
observer.error(new TransportWebUSBGestureRequired(error.message));
}
else {
observer.error(new TransportOpenUserCancelled(error.message));
}
});
function unsubscribe() {
unsubscribed = true;
}
setScrambleKey() { }
}
/**
* Check if WebUSB transport is supported.
*/
TransportWebUSB.isSupported = isSupported;
/**
* List the WebUSB devices that was previously authorized by the user.
*/
TransportWebUSB.list = getLedgerDevices;
/**
* Actively listen to WebUSB devices and emit ONE device
* that was either accepted before, if not it will trigger the native permission UI.
*
* Important: it must be called in the context of a UI click!
*/
TransportWebUSB.listen = (observer) => {
let unsubscribed = false;
getFirstLedgerDevice().then((device) => {
if (!unsubscribed) {
const deviceModel = identifyUSBProductId(device.productId);
observer.next({
type: "add",
descriptor: device,
deviceModel,
});
observer.complete();
}
return {
unsubscribe: unsubscribe
};
}, (error) => {
if (window.DOMException &&
error instanceof window.DOMException &&
error.code === 18) {
observer.error(new TransportWebUSBGestureRequired(error.message));
}
else {
observer.error(new TransportOpenUserCancelled(error.message));
}
});
function unsubscribe() {
unsubscribed = true;
}
return {
unsubscribe,
};
return TransportWebUSB;
}(Transport));
export default TransportWebUSB;
};
function gracefullyResetDevice(device) {
return __awaiter(this, void 0, void 0, function () {
var err_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, device.reset()];
case 1:
_a.sent();
return [3 /*break*/, 3];
case 2:
err_1 = _a.sent();
console.warn(err_1);
return [3 /*break*/, 3];
case 3: return [2 /*return*/];
}
});
return __awaiter(this, void 0, void 0, function* () {
try {
yield device.reset();
}
catch (err) {
console.warn(err);
}
});
}
//# sourceMappingURL=TransportWebUSB.js.map

@@ -10,83 +10,33 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {

};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
import { ledgerUSBVendorId } from "@ledgerhq/devices";
var ledgerDevices = [
const ledgerDevices = [
{
vendorId: ledgerUSBVendorId
vendorId: ledgerUSBVendorId,
},
];
export function requestLedgerDevice() {
return __awaiter(this, void 0, void 0, function () {
var device;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, navigator.usb.requestDevice({
filters: ledgerDevices
})];
case 1:
device = _a.sent();
return [2 /*return*/, device];
}
return __awaiter(this, void 0, void 0, function* () {
const device = yield navigator.usb.requestDevice({
filters: ledgerDevices,
});
return device;
});
}
export function getLedgerDevices() {
return __awaiter(this, void 0, void 0, function () {
var devices;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, navigator.usb.getDevices()];
case 1:
devices = _a.sent();
return [2 /*return*/, devices.filter(function (d) { return d.vendorId === ledgerUSBVendorId; })];
}
});
return __awaiter(this, void 0, void 0, function* () {
const devices = yield navigator.usb.getDevices();
return devices.filter((d) => d.vendorId === ledgerUSBVendorId);
});
}
export function getFirstLedgerDevice() {
return __awaiter(this, void 0, void 0, function () {
var existingDevices;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, getLedgerDevices()];
case 1:
existingDevices = _a.sent();
if (existingDevices.length > 0)
return [2 /*return*/, existingDevices[0]];
return [2 /*return*/, requestLedgerDevice()];
}
});
return __awaiter(this, void 0, void 0, function* () {
const existingDevices = yield getLedgerDevices();
if (existingDevices.length > 0)
return existingDevices[0];
return requestLedgerDevice();
});
}
export var isSupported = function () {
return Promise.resolve(!!navigator &&
!!navigator.usb &&
typeof navigator.usb.getDevices === "function");
};
export const isSupported = () => Promise.resolve(!!navigator &&
!!navigator.usb &&
typeof navigator.usb.getDevices === "function");
//# sourceMappingURL=webusb.js.map
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {

@@ -26,41 +11,14 @@ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }

};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
exports.__esModule = true;
var hw_transport_1 = __importDefault(require("@ledgerhq/hw-transport"));
var hid_framing_1 = __importDefault(require("@ledgerhq/devices/hid-framing"));
var devices_1 = require("@ledgerhq/devices");
var logs_1 = require("@ledgerhq/logs");
var errors_1 = require("@ledgerhq/errors");
var webusb_1 = require("./webusb");
var configurationValue = 1;
var endpointNumber = 3;
Object.defineProperty(exports, "__esModule", { value: true });
const hw_transport_1 = __importDefault(require("@ledgerhq/hw-transport"));
const hid_framing_1 = __importDefault(require("@ledgerhq/devices/hid-framing"));
const devices_1 = require("@ledgerhq/devices");
const logs_1 = require("@ledgerhq/logs");
const errors_1 = require("@ledgerhq/errors");
const webusb_1 = require("./webusb");
const configurationValue = 1;
const endpointNumber = 3;
/**

@@ -73,19 +31,17 @@ * WebUSB Transport implementation

*/
var TransportWebUSB = /** @class */ (function (_super) {
__extends(TransportWebUSB, _super);
function TransportWebUSB(device, interfaceNumber) {
var _this = _super.call(this) || this;
_this.channel = Math.floor(Math.random() * 0xffff);
_this.packetSize = 64;
_this._disconnectEmitted = false;
_this._emitDisconnect = function (e) {
if (_this._disconnectEmitted)
class TransportWebUSB extends hw_transport_1.default {
constructor(device, interfaceNumber) {
super();
this.channel = Math.floor(Math.random() * 0xffff);
this.packetSize = 64;
this._disconnectEmitted = false;
this._emitDisconnect = (e) => {
if (this._disconnectEmitted)
return;
_this._disconnectEmitted = true;
_this.emit("disconnect", e);
this._disconnectEmitted = true;
this.emit("disconnect", e);
};
_this.device = device;
_this.interfaceNumber = interfaceNumber;
_this.deviceModel = (0, devices_1.identifyUSBProductId)(device.productId);
return _this;
this.device = device;
this.interfaceNumber = interfaceNumber;
this.deviceModel = (0, devices_1.identifyUSBProductId)(device.productId);
}

@@ -95,113 +51,65 @@ /**

*/
TransportWebUSB.request = function () {
return __awaiter(this, void 0, void 0, function () {
var device;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, (0, webusb_1.requestLedgerDevice)()];
case 1:
device = _a.sent();
return [2 /*return*/, TransportWebUSB.open(device)];
}
});
static request() {
return __awaiter(this, void 0, void 0, function* () {
const device = yield (0, webusb_1.requestLedgerDevice)();
return TransportWebUSB.open(device);
});
};
}
/**
* Similar to create() except it will never display the device permission (it returns a Promise<?Transport>, null if it fails to find a device).
*/
TransportWebUSB.openConnected = function () {
return __awaiter(this, void 0, void 0, function () {
var devices;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, (0, webusb_1.getLedgerDevices)()];
case 1:
devices = _a.sent();
if (devices.length === 0)
return [2 /*return*/, null];
return [2 /*return*/, TransportWebUSB.open(devices[0])];
}
});
static openConnected() {
return __awaiter(this, void 0, void 0, function* () {
const devices = yield (0, webusb_1.getLedgerDevices)();
if (devices.length === 0)
return null;
return TransportWebUSB.open(devices[0]);
});
};
}
/**
* Create a Ledger transport with a USBDevice
*/
TransportWebUSB.open = function (device) {
return __awaiter(this, void 0, void 0, function () {
var iface, interfaceNumber, e_1, transport, onDisconnect;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, device.open()];
case 1:
_a.sent();
if (!(device.configuration === null)) return [3 /*break*/, 3];
return [4 /*yield*/, device.selectConfiguration(configurationValue)];
case 2:
_a.sent();
_a.label = 3;
case 3: return [4 /*yield*/, gracefullyResetDevice(device)];
case 4:
_a.sent();
iface = device.configurations[0].interfaces.find(function (_a) {
var alternates = _a.alternates;
return alternates.some(function (a) { return a.interfaceClass === 255; });
});
if (!iface) {
throw new errors_1.TransportInterfaceNotAvailable("No WebUSB interface found for your Ledger device. Please upgrade firmware or contact techsupport.");
}
interfaceNumber = iface.interfaceNumber;
_a.label = 5;
case 5:
_a.trys.push([5, 7, , 9]);
return [4 /*yield*/, device.claimInterface(interfaceNumber)];
case 6:
_a.sent();
return [3 /*break*/, 9];
case 7:
e_1 = _a.sent();
return [4 /*yield*/, device.close()];
case 8:
_a.sent();
throw new errors_1.TransportInterfaceNotAvailable(e_1.message);
case 9:
transport = new TransportWebUSB(device, interfaceNumber);
onDisconnect = function (e) {
if (device === e.device) {
// $FlowFixMe
navigator.usb.removeEventListener("disconnect", onDisconnect);
transport._emitDisconnect(new errors_1.DisconnectedDevice());
}
};
// $FlowFixMe
navigator.usb.addEventListener("disconnect", onDisconnect);
return [2 /*return*/, transport];
static open(device) {
return __awaiter(this, void 0, void 0, function* () {
yield device.open();
if (device.configuration === null) {
yield device.selectConfiguration(configurationValue);
}
yield gracefullyResetDevice(device);
const iface = device.configurations[0].interfaces.find(({ alternates }) => alternates.some((a) => a.interfaceClass === 255));
if (!iface) {
throw new errors_1.TransportInterfaceNotAvailable("No WebUSB interface found for your Ledger device. Please upgrade firmware or contact techsupport.");
}
const interfaceNumber = iface.interfaceNumber;
try {
yield device.claimInterface(interfaceNumber);
}
catch (e) {
yield device.close();
throw new errors_1.TransportInterfaceNotAvailable(e.message);
}
const transport = new TransportWebUSB(device, interfaceNumber);
const onDisconnect = (e) => {
if (device === e.device) {
// $FlowFixMe
navigator.usb.removeEventListener("disconnect", onDisconnect);
transport._emitDisconnect(new errors_1.DisconnectedDevice());
}
});
};
// $FlowFixMe
navigator.usb.addEventListener("disconnect", onDisconnect);
return transport;
});
};
}
/**
* Release the transport device
*/
TransportWebUSB.prototype.close = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.exchangeBusyPromise];
case 1:
_a.sent();
return [4 /*yield*/, this.device.releaseInterface(this.interfaceNumber)];
case 2:
_a.sent();
return [4 /*yield*/, gracefullyResetDevice(this.device)];
case 3:
_a.sent();
return [4 /*yield*/, this.device.close()];
case 4:
_a.sent();
return [2 /*return*/];
}
});
close() {
return __awaiter(this, void 0, void 0, function* () {
yield this.exchangeBusyPromise;
yield this.device.releaseInterface(this.interfaceNumber);
yield gracefullyResetDevice(this.device);
yield this.device.close();
});
};
}
/**

@@ -212,122 +120,91 @@ * Exchange with the device using APDU protocol.

*/
TransportWebUSB.prototype.exchange = function (apdu) {
return __awaiter(this, void 0, void 0, function () {
var b;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.exchangeAtomicImpl(function () { return __awaiter(_this, void 0, void 0, function () {
var _a, channel, packetSize, framing, blocks, i, result, acc, r, buffer;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_a = this, channel = _a.channel, packetSize = _a.packetSize;
(0, logs_1.log)("apdu", "=> " + apdu.toString("hex"));
framing = (0, hid_framing_1["default"])(channel, packetSize);
blocks = framing.makeBlocks(apdu);
i = 0;
_b.label = 1;
case 1:
if (!(i < blocks.length)) return [3 /*break*/, 4];
return [4 /*yield*/, this.device.transferOut(endpointNumber, blocks[i])];
case 2:
_b.sent();
_b.label = 3;
case 3:
i++;
return [3 /*break*/, 1];
case 4:
if (!!(result = framing.getReducedResult(acc))) return [3 /*break*/, 6];
return [4 /*yield*/, this.device.transferIn(endpointNumber, packetSize)];
case 5:
r = _b.sent();
buffer = Buffer.from(r.data.buffer);
acc = framing.reduceResponse(acc, buffer);
return [3 /*break*/, 4];
case 6:
(0, logs_1.log)("apdu", "<= " + result.toString("hex"));
return [2 /*return*/, result];
}
});
}); })["catch"](function (e) {
if (e && e.message && e.message.includes("disconnected")) {
_this._emitDisconnect(e);
throw new errors_1.DisconnectedDeviceDuringOperation(e.message);
}
throw e;
})];
case 1:
b = _a.sent();
return [2 /*return*/, b];
exchange(apdu) {
return __awaiter(this, void 0, void 0, function* () {
const b = yield this.exchangeAtomicImpl(() => __awaiter(this, void 0, void 0, function* () {
const { channel, packetSize } = this;
(0, logs_1.log)("apdu", "=> " + apdu.toString("hex"));
const framing = (0, hid_framing_1.default)(channel, packetSize);
// Write...
const blocks = framing.makeBlocks(apdu);
for (let i = 0; i < blocks.length; i++) {
yield this.device.transferOut(endpointNumber, blocks[i]);
}
// Read...
let result;
let acc;
while (!(result = framing.getReducedResult(acc))) {
const r = yield this.device.transferIn(endpointNumber, packetSize);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const buffer = Buffer.from(r.data.buffer);
acc = framing.reduceResponse(acc, buffer);
}
(0, logs_1.log)("apdu", "<= " + result.toString("hex"));
return result;
})).catch((e) => {
if (e && e.message && e.message.includes("disconnected")) {
this._emitDisconnect(e);
throw new errors_1.DisconnectedDeviceDuringOperation(e.message);
}
throw e;
});
return b;
});
};
TransportWebUSB.prototype.setScrambleKey = function () { };
/**
* Check if WebUSB transport is supported.
*/
TransportWebUSB.isSupported = webusb_1.isSupported;
/**
* List the WebUSB devices that was previously authorized by the user.
*/
TransportWebUSB.list = webusb_1.getLedgerDevices;
/**
* Actively listen to WebUSB devices and emit ONE device
* that was either accepted before, if not it will trigger the native permission UI.
*
* Important: it must be called in the context of a UI click!
*/
TransportWebUSB.listen = function (observer) {
var unsubscribed = false;
(0, webusb_1.getFirstLedgerDevice)().then(function (device) {
if (!unsubscribed) {
var deviceModel = (0, devices_1.identifyUSBProductId)(device.productId);
observer.next({
type: "add",
descriptor: device,
deviceModel: deviceModel
});
observer.complete();
}
}, function (error) {
if (window.DOMException &&
error instanceof window.DOMException &&
error.code === 18) {
observer.error(new errors_1.TransportWebUSBGestureRequired(error.message));
}
else {
observer.error(new errors_1.TransportOpenUserCancelled(error.message));
}
});
function unsubscribe() {
unsubscribed = true;
}
setScrambleKey() { }
}
exports.default = TransportWebUSB;
/**
* Check if WebUSB transport is supported.
*/
TransportWebUSB.isSupported = webusb_1.isSupported;
/**
* List the WebUSB devices that was previously authorized by the user.
*/
TransportWebUSB.list = webusb_1.getLedgerDevices;
/**
* Actively listen to WebUSB devices and emit ONE device
* that was either accepted before, if not it will trigger the native permission UI.
*
* Important: it must be called in the context of a UI click!
*/
TransportWebUSB.listen = (observer) => {
let unsubscribed = false;
(0, webusb_1.getFirstLedgerDevice)().then((device) => {
if (!unsubscribed) {
const deviceModel = (0, devices_1.identifyUSBProductId)(device.productId);
observer.next({
type: "add",
descriptor: device,
deviceModel,
});
observer.complete();
}
return {
unsubscribe: unsubscribe
};
}, (error) => {
if (window.DOMException &&
error instanceof window.DOMException &&
error.code === 18) {
observer.error(new errors_1.TransportWebUSBGestureRequired(error.message));
}
else {
observer.error(new errors_1.TransportOpenUserCancelled(error.message));
}
});
function unsubscribe() {
unsubscribed = true;
}
return {
unsubscribe,
};
return TransportWebUSB;
}(hw_transport_1["default"]));
exports["default"] = TransportWebUSB;
};
function gracefullyResetDevice(device) {
return __awaiter(this, void 0, void 0, function () {
var err_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, device.reset()];
case 1:
_a.sent();
return [3 /*break*/, 3];
case 2:
err_1 = _a.sent();
console.warn(err_1);
return [3 /*break*/, 3];
case 3: return [2 /*return*/];
}
});
return __awaiter(this, void 0, void 0, function* () {
try {
yield device.reset();
}
catch (err) {
console.warn(err);
}
});
}
//# sourceMappingURL=TransportWebUSB.js.map

@@ -11,50 +11,16 @@ "use strict";

};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", { value: true });
exports.isSupported = exports.getFirstLedgerDevice = exports.getLedgerDevices = exports.requestLedgerDevice = void 0;
var devices_1 = require("@ledgerhq/devices");
var ledgerDevices = [
const devices_1 = require("@ledgerhq/devices");
const ledgerDevices = [
{
vendorId: devices_1.ledgerUSBVendorId
vendorId: devices_1.ledgerUSBVendorId,
},
];
function requestLedgerDevice() {
return __awaiter(this, void 0, void 0, function () {
var device;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, navigator.usb.requestDevice({
filters: ledgerDevices
})];
case 1:
device = _a.sent();
return [2 /*return*/, device];
}
return __awaiter(this, void 0, void 0, function* () {
const device = yield navigator.usb.requestDevice({
filters: ledgerDevices,
});
return device;
});

@@ -64,12 +30,5 @@ }

function getLedgerDevices() {
return __awaiter(this, void 0, void 0, function () {
var devices;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, navigator.usb.getDevices()];
case 1:
devices = _a.sent();
return [2 /*return*/, devices.filter(function (d) { return d.vendorId === devices_1.ledgerUSBVendorId; })];
}
});
return __awaiter(this, void 0, void 0, function* () {
const devices = yield navigator.usb.getDevices();
return devices.filter((d) => d.vendorId === devices_1.ledgerUSBVendorId);
});

@@ -79,23 +38,14 @@ }

function getFirstLedgerDevice() {
return __awaiter(this, void 0, void 0, function () {
var existingDevices;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, getLedgerDevices()];
case 1:
existingDevices = _a.sent();
if (existingDevices.length > 0)
return [2 /*return*/, existingDevices[0]];
return [2 /*return*/, requestLedgerDevice()];
}
});
return __awaiter(this, void 0, void 0, function* () {
const existingDevices = yield getLedgerDevices();
if (existingDevices.length > 0)
return existingDevices[0];
return requestLedgerDevice();
});
}
exports.getFirstLedgerDevice = getFirstLedgerDevice;
var isSupported = function () {
return Promise.resolve(!!navigator &&
!!navigator.usb &&
typeof navigator.usb.getDevices === "function");
};
const isSupported = () => Promise.resolve(!!navigator &&
!!navigator.usb &&
typeof navigator.usb.getDevices === "function");
exports.isSupported = isSupported;
//# sourceMappingURL=webusb.js.map
{
"name": "@ledgerhq/hw-transport-webusb",
"version": "6.27.13",
"version": "6.27.14-next.0",
"description": "Ledger Hardware Wallet WebUSB implementation of the communication layer",

@@ -29,5 +29,5 @@ "keywords": [

"dependencies": {
"@ledgerhq/devices": "^8.0.1",
"@ledgerhq/errors": "^6.12.4",
"@ledgerhq/hw-transport": "^6.28.2",
"@ledgerhq/devices": "^8.0.2-next.0",
"@ledgerhq/errors": "^6.12.5-next.0",
"@ledgerhq/hw-transport": "^6.28.3-next.0",
"@ledgerhq/logs": "^6.10.1"

@@ -41,7 +41,6 @@ },

"jest": "^28.1.1",
"rimraf": "^4.1.2",
"rimraf": "^4.4.1",
"source-map-support": "^0.5.21",
"ts-jest": "^28.0.5",
"ts-node": "^10.4.0",
"typescript": "^4"
"ts-node": "^10.4.0"
},

@@ -48,0 +47,0 @@ "gitHead": "dd0dea64b58e5a9125c8a422dcffd29e5ef6abec",

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc