@ledgerhq/hw-transport-http
Version:
Ledger Hardware Wallet communication layer over http
128 lines • 5.27 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var _a;
import Transport from "@ledgerhq/hw-transport";
import { TransportError } from "@ledgerhq/errors";
import { log } from "@ledgerhq/logs";
const WebSocket = global.WebSocket || require("ws");
/**
* WebSocket transport implementation
*/
class WebSocketTransport extends Transport {
static open(url) {
return __awaiter(this, void 0, void 0, function* () {
const exchangeMethods = yield new Promise((resolve, reject) => {
try {
const socket = new WebSocket(url);
const exchangeMethods = {
resolveExchange: (_b) => { },
rejectExchange: (_e) => { },
onDisconnect: () => { },
close: () => socket.close(),
send: msg => socket.send(msg),
};
socket.onopen = () => {
socket.send("open");
};
socket.onerror = e => {
exchangeMethods.onDisconnect();
reject(e);
};
socket.onclose = () => {
exchangeMethods.onDisconnect();
reject(new TransportError("OpenFailed", "OpenFailed"));
};
socket.onmessage = e => {
if (typeof e.data !== "string")
return;
const data = JSON.parse(e.data);
switch (data.type) {
case "opened":
return resolve(exchangeMethods);
case "error":
reject(new Error(data.error));
return exchangeMethods.rejectExchange(new TransportError(data.error, "WSError"));
case "response":
return exchangeMethods.resolveExchange(Buffer.from(data.data, "hex"));
}
};
}
catch (e) {
reject(e);
}
});
return new _a(exchangeMethods);
});
}
constructor(hook) {
super();
this.hook = hook;
hook.onDisconnect = () => {
this.emit("disconnect");
this.hook.rejectExchange(new TransportError("WebSocket disconnected", "WSDisconnect"));
};
}
exchange(apdu) {
return __awaiter(this, void 0, void 0, function* () {
const hex = apdu.toString("hex");
log("apdu", "=> " + hex);
const res = yield new Promise((resolve, reject) => {
this.hook.rejectExchange = (e) => reject(e);
this.hook.resolveExchange = (b) => resolve(b);
this.hook.send(hex);
});
log("apdu", "<= " + res.toString("hex"));
return res;
});
}
setScrambleKey() { }
close() {
return __awaiter(this, void 0, void 0, function* () {
this.hook.close();
return new Promise(success => {
setTimeout(() => {
success(undefined);
}, 200);
});
});
}
}
_a = WebSocketTransport;
WebSocketTransport.isSupported = () => Promise.resolve(typeof WebSocket === "function");
// this transport is not discoverable
WebSocketTransport.list = () => Promise.resolve([]);
WebSocketTransport.listen = (_observer) => ({
unsubscribe: () => { },
});
WebSocketTransport.check = (url_1, ...args_1) => __awaiter(void 0, [url_1, ...args_1], void 0, function* (url, timeout = 5000) {
return new Promise((resolve, reject) => {
const socket = new WebSocket(url);
let success = false;
setTimeout(() => {
socket.close();
}, timeout);
socket.onopen = () => {
success = true;
socket.close();
};
socket.onclose = () => {
if (success)
resolve(undefined);
else {
reject(new TransportError("failed to access WebSocketTransport(" + url + ")", "WebSocketTransportNotAccessible"));
}
};
socket.onerror = () => {
reject(new TransportError("failed to access WebSocketTransport(" + url + "): error", "WebSocketTransportNotAccessible"));
};
});
});
export default WebSocketTransport;
//# sourceMappingURL=WebSocketTransport.js.map