@ledgerhq/live-cli 24.11.0 → 24.11.1-nightly.0

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.
Files changed (152) hide show
  1. package/lib/cli.js +33 -63
  2. package/lib/cli.js.map +1 -1
  3. package/lib/commands/blockchain/bot.js +7 -7
  4. package/lib/commands/blockchain/bot.js.map +1 -1
  5. package/lib/commands/blockchain/botPortfolio.js +22 -26
  6. package/lib/commands/blockchain/botPortfolio.js.map +1 -1
  7. package/lib/commands/blockchain/botTransfer.js +219 -392
  8. package/lib/commands/blockchain/botTransfer.js.map +1 -1
  9. package/lib/commands/blockchain/broadcast.js +11 -42
  10. package/lib/commands/blockchain/broadcast.js.map +1 -1
  11. package/lib/commands/blockchain/confirmOp.js +12 -52
  12. package/lib/commands/blockchain/confirmOp.js.map +1 -1
  13. package/lib/commands/blockchain/derivation.js +31 -33
  14. package/lib/commands/blockchain/derivation.js.map +1 -1
  15. package/lib/commands/blockchain/estimateMaxSpendable.js +27 -56
  16. package/lib/commands/blockchain/estimateMaxSpendable.js.map +1 -1
  17. package/lib/commands/blockchain/generateTestScanAccounts.js +29 -37
  18. package/lib/commands/blockchain/generateTestScanAccounts.js.map +1 -1
  19. package/lib/commands/blockchain/generateTestTransaction.js +70 -96
  20. package/lib/commands/blockchain/generateTestTransaction.js.map +1 -1
  21. package/lib/commands/blockchain/getAddress.js +20 -24
  22. package/lib/commands/blockchain/getAddress.js.map +1 -1
  23. package/lib/commands/blockchain/getTransactionStatus.js +31 -69
  24. package/lib/commands/blockchain/getTransactionStatus.js.map +1 -1
  25. package/lib/commands/blockchain/receive.js +14 -42
  26. package/lib/commands/blockchain/receive.js.map +1 -1
  27. package/lib/commands/blockchain/satstack.js +30 -33
  28. package/lib/commands/blockchain/satstack.js.map +1 -1
  29. package/lib/commands/blockchain/satstackStatus.js +4 -5
  30. package/lib/commands/blockchain/satstackStatus.js.map +1 -1
  31. package/lib/commands/blockchain/scanDescriptors.js +8 -14
  32. package/lib/commands/blockchain/scanDescriptors.js.map +1 -1
  33. package/lib/commands/blockchain/send.js +61 -90
  34. package/lib/commands/blockchain/send.js.map +1 -1
  35. package/lib/commands/blockchain/signMessage.d.ts +1 -1
  36. package/lib/commands/blockchain/signMessage.js +15 -40
  37. package/lib/commands/blockchain/signMessage.js.map +1 -1
  38. package/lib/commands/blockchain/sync.js +27 -120
  39. package/lib/commands/blockchain/sync.js.map +1 -1
  40. package/lib/commands/blockchain/testDetectOpCollision.js +15 -48
  41. package/lib/commands/blockchain/testDetectOpCollision.js.map +1 -1
  42. package/lib/commands/blockchain/testGetTrustedInputFromTxHash.js +37 -86
  43. package/lib/commands/blockchain/testGetTrustedInputFromTxHash.js.map +1 -1
  44. package/lib/commands/device/app.js +42 -76
  45. package/lib/commands/device/app.js.map +1 -1
  46. package/lib/commands/device/appUninstallAll.d.ts +1 -1
  47. package/lib/commands/device/appUninstallAll.js +22 -29
  48. package/lib/commands/device/appUninstallAll.js.map +1 -1
  49. package/lib/commands/device/appsCheckAllAppVersions.js +208 -361
  50. package/lib/commands/device/appsCheckAllAppVersions.js.map +1 -1
  51. package/lib/commands/device/appsInstallAll.js +15 -24
  52. package/lib/commands/device/appsInstallAll.js.map +1 -1
  53. package/lib/commands/device/appsUpdateTestAll.js +69 -80
  54. package/lib/commands/device/appsUpdateTestAll.js.map +1 -1
  55. package/lib/commands/device/cleanSpeculos.js +4 -4
  56. package/lib/commands/device/cleanSpeculos.js.map +1 -1
  57. package/lib/commands/device/customLockScreenFetch.js +37 -84
  58. package/lib/commands/device/customLockScreenFetch.js.map +1 -1
  59. package/lib/commands/device/customLockScreenFetchAndRestore.js +46 -110
  60. package/lib/commands/device/customLockScreenFetchAndRestore.js.map +1 -1
  61. package/lib/commands/device/customLockScreenFetchHash.js +5 -7
  62. package/lib/commands/device/customLockScreenFetchHash.js.map +1 -1
  63. package/lib/commands/device/customLockScreenLoad.js +25 -72
  64. package/lib/commands/device/customLockScreenLoad.js.map +1 -1
  65. package/lib/commands/device/customLockScreenRemove.js +5 -7
  66. package/lib/commands/device/customLockScreenRemove.js.map +1 -1
  67. package/lib/commands/device/devDeviceAppsScenario.js +33 -65
  68. package/lib/commands/device/devDeviceAppsScenario.js.map +1 -1
  69. package/lib/commands/device/deviceAppVersion.js +5 -8
  70. package/lib/commands/device/deviceAppVersion.js.map +1 -1
  71. package/lib/commands/device/deviceInfo.js +5 -8
  72. package/lib/commands/device/deviceInfo.js.map +1 -1
  73. package/lib/commands/device/deviceSDKFirmwareUpdate.js +22 -68
  74. package/lib/commands/device/deviceSDKFirmwareUpdate.js.map +1 -1
  75. package/lib/commands/device/deviceSDKGetBatteryStatuses.js +7 -8
  76. package/lib/commands/device/deviceSDKGetBatteryStatuses.js.map +1 -1
  77. package/lib/commands/device/deviceSDKGetDeviceInfo.js +6 -7
  78. package/lib/commands/device/deviceSDKGetDeviceInfo.js.map +1 -1
  79. package/lib/commands/device/deviceSDKToggleOnboardingEarlyCheck.js +8 -9
  80. package/lib/commands/device/deviceSDKToggleOnboardingEarlyCheck.js.map +1 -1
  81. package/lib/commands/device/deviceVersion.js +5 -8
  82. package/lib/commands/device/deviceVersion.js.map +1 -1
  83. package/lib/commands/device/discoverDevices.js +15 -50
  84. package/lib/commands/device/discoverDevices.js.map +1 -1
  85. package/lib/commands/device/firmwareRepair.js +3 -6
  86. package/lib/commands/device/firmwareRepair.js.map +1 -1
  87. package/lib/commands/device/firmwareUpdate.js +63 -123
  88. package/lib/commands/device/firmwareUpdate.js.map +1 -1
  89. package/lib/commands/device/genuineCheck.js +7 -12
  90. package/lib/commands/device/genuineCheck.js.map +1 -1
  91. package/lib/commands/device/getBatteryStatus.js +5 -9
  92. package/lib/commands/device/getBatteryStatus.js.map +1 -1
  93. package/lib/commands/device/getDeviceRunningMode.js +7 -10
  94. package/lib/commands/device/getDeviceRunningMode.js.map +1 -1
  95. package/lib/commands/device/i18n.js +27 -79
  96. package/lib/commands/device/i18n.js.map +1 -1
  97. package/lib/commands/device/listApps.d.ts +1 -1
  98. package/lib/commands/device/listApps.js +7 -12
  99. package/lib/commands/device/listApps.js.map +1 -1
  100. package/lib/commands/device/managerListApps.js +21 -28
  101. package/lib/commands/device/managerListApps.js.map +1 -1
  102. package/lib/commands/device/proxy.js +242 -350
  103. package/lib/commands/device/proxy.js.map +1 -1
  104. package/lib/commands/device/reinstallConfigurationConsent.js +36 -126
  105. package/lib/commands/device/reinstallConfigurationConsent.js.map +1 -1
  106. package/lib/commands/device/repl.js +5 -10
  107. package/lib/commands/device/repl.js.map +1 -1
  108. package/lib/commands/device/speculosList.js +12 -58
  109. package/lib/commands/device/speculosList.js.map +1 -1
  110. package/lib/commands/live/balanceHistory.js +44 -79
  111. package/lib/commands/live/balanceHistory.js.map +1 -1
  112. package/lib/commands/live/countervalues.js +111 -207
  113. package/lib/commands/live/countervalues.js.map +1 -1
  114. package/lib/commands/live/envs.js +4 -6
  115. package/lib/commands/live/envs.js.map +1 -1
  116. package/lib/commands/live/exportAccounts.js +30 -56
  117. package/lib/commands/live/exportAccounts.js.map +1 -1
  118. package/lib/commands/live/ledgerKeyRingProtocol.d.ts +1 -1
  119. package/lib/commands/live/ledgerKeyRingProtocol.js +63 -103
  120. package/lib/commands/live/ledgerKeyRingProtocol.js.map +1 -1
  121. package/lib/commands/live/ledgerSync.js +20 -60
  122. package/lib/commands/live/ledgerSync.js.map +1 -1
  123. package/lib/commands/live/liveData.js +34 -60
  124. package/lib/commands/live/liveData.js.map +1 -1
  125. package/lib/commands/live/portfolio.js +68 -98
  126. package/lib/commands/live/portfolio.js.map +1 -1
  127. package/lib/commands/live/synchronousOnboarding.js +6 -9
  128. package/lib/commands/live/synchronousOnboarding.js.map +1 -1
  129. package/lib/commands/live/user.js +4 -4
  130. package/lib/commands/live/user.js.map +1 -1
  131. package/lib/commands/live/version.js +2 -4
  132. package/lib/commands/live/version.js.map +1 -1
  133. package/lib/commands/ptx/swap.js +194 -282
  134. package/lib/commands/ptx/swap.js.map +1 -1
  135. package/lib/commands-index.d.ts +9 -9
  136. package/lib/commands-index.js +64 -64
  137. package/lib/commands-index.js.map +1 -1
  138. package/lib/live-common-setup-base.js +26 -48
  139. package/lib/live-common-setup-base.js.map +1 -1
  140. package/lib/live-common-setup.js +66 -123
  141. package/lib/live-common-setup.js.map +1 -1
  142. package/lib/qr.js +6 -10
  143. package/lib/qr.js.map +1 -1
  144. package/lib/scan.js +84 -92
  145. package/lib/scan.js.map +1 -1
  146. package/lib/signedOperation.js +6 -6
  147. package/lib/signedOperation.js.map +1 -1
  148. package/lib/stream.js +57 -68
  149. package/lib/stream.js.map +1 -1
  150. package/lib/transaction.js +60 -142
  151. package/lib/transaction.js.map +1 -1
  152. package/package.json +2 -2
@@ -1,83 +1,22 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
- function verb(n) { return function (v) { return step([n, v]); }; }
15
- function step(op) {
16
- if (f) throw new TypeError("Generator is already executing.");
17
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
- 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;
19
- if (y = 0, t) op = [op[0] & 2, t.value];
20
- switch (op[0]) {
21
- case 0: case 1: t = op; break;
22
- case 4: _.label++; return { value: op[1], done: false };
23
- case 5: _.label++; y = op[1]; op = [0]; continue;
24
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
- default:
26
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
- if (t[2]) _.ops.pop();
31
- _.trys.pop(); continue;
32
- }
33
- op = body.call(thisArg, _);
34
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
- }
37
- };
38
- var __read = (this && this.__read) || function (o, n) {
39
- var m = typeof Symbol === "function" && o[Symbol.iterator];
40
- if (!m) return o;
41
- var i = m.call(o), r, ar = [], e;
42
- try {
43
- while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
44
- }
45
- catch (error) { e = { error: error }; }
46
- finally {
47
- try {
48
- if (r && !r.done && (m = i["return"])) m.call(i);
49
- }
50
- finally { if (e) throw e.error; }
51
- }
52
- return ar;
53
- };
54
- var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
55
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
56
- if (ar || !(i in from)) {
57
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
58
- ar[i] = from[i];
59
- }
60
- }
61
- return to.concat(ar || Array.prototype.slice.call(from));
62
- };
63
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
64
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
65
4
  };
66
5
  Object.defineProperty(exports, "__esModule", { value: true });
67
6
  /* eslint-disable global-require */
68
- var hw_transport_mocker_1 = require("@ledgerhq/hw-transport-mocker");
69
- var logs_1 = require("@ledgerhq/logs");
70
- var index_1 = require("@ledgerhq/live-common/hw/index");
71
- var fs_1 = __importDefault(require("fs"));
72
- var http_1 = __importDefault(require("http"));
73
- var express_1 = __importDefault(require("express"));
74
- var cors_1 = __importDefault(require("cors"));
75
- var ws_1 = __importDefault(require("ws"));
76
- var body_parser_1 = __importDefault(require("body-parser"));
77
- var os_1 = __importDefault(require("os"));
78
- var rxjs_1 = require("rxjs");
79
- var scan_1 = require("../../scan");
80
- var args = [
7
+ const hw_transport_mocker_1 = require("@ledgerhq/hw-transport-mocker");
8
+ const logs_1 = require("@ledgerhq/logs");
9
+ const index_1 = require("@ledgerhq/live-common/hw/index");
10
+ const fs_1 = __importDefault(require("fs"));
11
+ const http_1 = __importDefault(require("http"));
12
+ const express_1 = __importDefault(require("express"));
13
+ const cors_1 = __importDefault(require("cors"));
14
+ const ws_1 = __importDefault(require("ws"));
15
+ const body_parser_1 = __importDefault(require("body-parser"));
16
+ const os_1 = __importDefault(require("os"));
17
+ const rxjs_1 = require("rxjs");
18
+ const scan_1 = require("../../scan");
19
+ const args = [
81
20
  scan_1.deviceOpt,
82
21
  {
83
22
  name: "file",
@@ -115,300 +54,253 @@ var args = [
115
54
  desc: "see the description of --file",
116
55
  },
117
56
  ];
118
- var job = function (_a) {
119
- var device = _a.device, file = _a.file, record = _a.record, port = _a.port, silent = _a.silent, verbose = _a.verbose, noAutoSkip = _a["disable-auto-skip"];
120
- return new rxjs_1.Observable(function (o) {
121
- var unsub = (0, logs_1.listen)(function (l) {
122
- if (verbose) {
123
- o.next(l.type + ": " + l.message);
57
+ const job = ({ device, file, record, port, silent, verbose, "disable-auto-skip": noAutoSkip, }) => new rxjs_1.Observable(o => {
58
+ const unsub = (0, logs_1.listen)(l => {
59
+ if (verbose) {
60
+ o.next(l.type + ": " + l.message);
61
+ }
62
+ else if (!silent && l.type === "proxy") {
63
+ o.next(l.message);
64
+ }
65
+ });
66
+ let Transport;
67
+ let saveToFile = null;
68
+ let recordStore;
69
+ const getTransportLike = () => {
70
+ return {
71
+ open: () => (0, index_1.open)(device || ""),
72
+ create: () => (0, index_1.open)(device || ""),
73
+ };
74
+ };
75
+ // --file <file>
76
+ // There are two ways to use the mock, either you record or you replay
77
+ // record: using --record means that it's a decoration in node-hid that will just save to a file
78
+ // replay: without --record, it's going to re-use a recorded file and mock a transport instead of using an actual device
79
+ if (file) {
80
+ if (record) {
81
+ (0, logs_1.log)("proxy", `the APDUs will be recorded in ${file}`);
82
+ saveToFile = file;
83
+ recordStore = new hw_transport_mocker_1.RecordStore([]);
84
+ // FIXME: ok this is the funky part with `DecoratedTransport`, ignoring for now cuz it's bullshit typings
85
+ // Has to be tackled during refacto
86
+ // @ts-expect-error getTransportLike should return a Partial<Transport> and createTransportRecorder should accept it
87
+ Transport = (0, hw_transport_mocker_1.createTransportRecorder)(getTransportLike(), recordStore);
88
+ }
89
+ else {
90
+ recordStore = hw_transport_mocker_1.RecordStore.fromString(fs_1.default.readFileSync(file, "utf8"), {
91
+ autoSkipUnknownApdu: !noAutoSkip,
92
+ });
93
+ if (recordStore.isEmpty()) {
94
+ process.exit(0);
124
95
  }
125
- else if (!silent && l.type === "proxy") {
126
- o.next(l.message);
96
+ (0, logs_1.log)("proxy", `${recordStore.queue.length} mocked APDUs will be replayed from ${file}`);
97
+ Transport = {
98
+ open: () => (0, hw_transport_mocker_1.openTransportReplayer)(recordStore),
99
+ create: () => (0, hw_transport_mocker_1.openTransportReplayer)(recordStore),
100
+ };
101
+ }
102
+ }
103
+ else {
104
+ Transport = getTransportLike();
105
+ }
106
+ const ifaces = os_1.default.networkInterfaces();
107
+ const ips = Object.keys(ifaces)
108
+ .reduce((acc, ifname) => acc.concat(ifaces[ifname].map(iface => {
109
+ if (iface.family !== "IPv4" || iface.internal !== false) {
110
+ // skip over internal (i.e. 127.0.0.1) and non-ipv4 addresses
111
+ return;
112
+ }
113
+ return iface.address;
114
+ })), [])
115
+ .filter(a => a);
116
+ const PORT = port || "8435";
117
+ const app = (0, express_1.default)();
118
+ const server = http_1.default.createServer(app);
119
+ const wss = new ws_1.default.Server({
120
+ server,
121
+ });
122
+ app.use((0, cors_1.default)());
123
+ app.get("/", (req, res) => {
124
+ res.sendStatus(200);
125
+ });
126
+ if (recordStore) {
127
+ app.post("/end", (req, res) => {
128
+ try {
129
+ if (!saveToFile) {
130
+ recordStore.ensureQueueEmpty();
131
+ }
132
+ res.sendStatus(200);
133
+ process.exit(0);
134
+ }
135
+ catch (e) {
136
+ res.sendStatus(400);
137
+ console.error(e.message);
138
+ process.exit(1);
127
139
  }
128
140
  });
129
- var Transport;
130
- var saveToFile = null;
131
- var recordStore;
132
- var getTransportLike = function () {
133
- return {
134
- open: function () { return (0, index_1.open)(device || ""); },
135
- create: function () { return (0, index_1.open)(device || ""); },
136
- };
137
- };
138
- // --file <file>
139
- // There are two ways to use the mock, either you record or you replay
140
- // record: using --record means that it's a decoration in node-hid that will just save to a file
141
- // replay: without --record, it's going to re-use a recorded file and mock a transport instead of using an actual device
142
- if (file) {
143
- if (record) {
144
- (0, logs_1.log)("proxy", "the APDUs will be recorded in ".concat(file));
145
- saveToFile = file;
146
- recordStore = new hw_transport_mocker_1.RecordStore([]);
147
- // FIXME: ok this is the funky part with `DecoratedTransport`, ignoring for now cuz it's bullshit typings
148
- // Has to be tackled during refacto
149
- // @ts-expect-error getTransportLike should return a Partial<Transport> and createTransportRecorder should accept it
150
- Transport = (0, hw_transport_mocker_1.createTransportRecorder)(getTransportLike(), recordStore);
141
+ }
142
+ let pending = false;
143
+ app.post("/", body_parser_1.default.json(), async (req, res) => {
144
+ if (!req.body)
145
+ return res.sendStatus(400);
146
+ let data = null;
147
+ let error = null;
148
+ if (pending) {
149
+ return res.status(400).json({
150
+ error: "an exchange query was already pending",
151
+ });
152
+ }
153
+ pending = true;
154
+ try {
155
+ const transport = await Transport.open();
156
+ try {
157
+ data = await transport.exchange(Buffer.from(req.body.apduHex, "hex"));
151
158
  }
152
- else {
153
- recordStore = hw_transport_mocker_1.RecordStore.fromString(fs_1.default.readFileSync(file, "utf8"), {
154
- autoSkipUnknownApdu: !noAutoSkip,
155
- });
156
- if (recordStore.isEmpty()) {
157
- process.exit(0);
159
+ finally {
160
+ transport.close();
161
+ if (saveToFile) {
162
+ fs_1.default.writeFileSync(saveToFile, recordStore.toString());
163
+ }
164
+ else if (recordStore) {
165
+ if (recordStore.isEmpty()) {
166
+ process.exit(0);
167
+ }
158
168
  }
159
- (0, logs_1.log)("proxy", "".concat(recordStore.queue.length, " mocked APDUs will be replayed from ").concat(file));
160
- Transport = {
161
- open: function () { return (0, hw_transport_mocker_1.openTransportReplayer)(recordStore); },
162
- create: function () { return (0, hw_transport_mocker_1.openTransportReplayer)(recordStore); },
163
- };
164
169
  }
165
170
  }
171
+ catch (e) {
172
+ error = e;
173
+ }
174
+ pending = false;
175
+ const result = {
176
+ data,
177
+ error,
178
+ };
179
+ if (data) {
180
+ // @ts-expect-error 3 args only, we give 5
181
+ (0, logs_1.log)("proxy", "HTTP:", req.body.apduHex, "=>", data.toString("hex"));
182
+ }
166
183
  else {
167
- Transport = getTransportLike();
184
+ // @ts-expect-error 3 args only, we give 5
185
+ (0, logs_1.log)("proxy", "HTTP:", req.body.apduHex, "=>", error);
186
+ }
187
+ res.json(result);
188
+ if (error && error.name === "RecordStoreWrongAPDU") {
189
+ console.error(error.message);
190
+ process.exit(1);
168
191
  }
169
- var ifaces = os_1.default.networkInterfaces();
170
- var ips = Object.keys(ifaces)
171
- .reduce(function (acc, ifname) {
172
- return acc.concat(ifaces[ifname].map(function (iface) {
173
- if (iface.family !== "IPv4" || iface.internal !== false) {
174
- // skip over internal (i.e. 127.0.0.1) and non-ipv4 addresses
192
+ });
193
+ let wsIndex = 0;
194
+ let wsBusyIndex = 0;
195
+ wss.on("connection", (ws) => {
196
+ const index = ++wsIndex;
197
+ try {
198
+ let transport;
199
+ let transportP;
200
+ let destroyed = false;
201
+ const onClose = async () => {
202
+ if (destroyed)
175
203
  return;
204
+ destroyed = true;
205
+ if (wsBusyIndex === index) {
206
+ (0, logs_1.log)("proxy", `WS(${index}): close`);
207
+ await transportP.then((t) => t.close(), () => { });
208
+ wsBusyIndex = 0;
176
209
  }
177
- return iface.address;
178
- }));
179
- }, [])
180
- .filter(function (a) { return a; });
181
- var PORT = port || "8435";
182
- var app = (0, express_1.default)();
183
- var server = http_1.default.createServer(app);
184
- var wss = new ws_1.default.Server({
185
- server: server,
186
- });
187
- app.use((0, cors_1.default)());
188
- app.get("/", function (req, res) {
189
- res.sendStatus(200);
190
- });
191
- if (recordStore) {
192
- app.post("/end", function (req, res) {
193
- try {
194
- if (!saveToFile) {
195
- recordStore.ensureQueueEmpty();
210
+ if (saveToFile) {
211
+ fs_1.default.writeFileSync(saveToFile, recordStore.toString());
212
+ }
213
+ else if (recordStore) {
214
+ if (recordStore.isEmpty()) {
215
+ process.exit(0);
216
+ }
217
+ }
218
+ };
219
+ ws.on("close", onClose);
220
+ ws.on("message", async (data, isBinary) => {
221
+ if (destroyed)
222
+ return;
223
+ const apduHex = isBinary ? data : data.toString();
224
+ if (apduHex === "open") {
225
+ if (wsBusyIndex) {
226
+ ws.send(JSON.stringify({
227
+ error: "WebSocket is busy (previous session not closed)",
228
+ }));
229
+ ws.close();
230
+ destroyed = true;
231
+ return;
196
232
  }
197
- res.sendStatus(200);
198
- process.exit(0);
233
+ transportP = Transport.open();
234
+ wsBusyIndex = index;
235
+ (0, logs_1.log)("proxy", `WS(${index}): opening...`);
236
+ try {
237
+ transport = await transportP;
238
+ transport.on("disconnect", () => ws.close());
239
+ (0, logs_1.log)("proxy", `WS(${index}): opened!`);
240
+ ws.send(JSON.stringify({
241
+ type: "opened",
242
+ }));
243
+ }
244
+ catch (e) {
245
+ (0, logs_1.log)("proxy", `WS(${index}): open failed! ${e}`);
246
+ ws.send(JSON.stringify({
247
+ error: e.message,
248
+ }));
249
+ ws.close();
250
+ }
251
+ return;
252
+ }
253
+ if (wsBusyIndex !== index) {
254
+ console.warn("ignoring message because busy transport");
255
+ return;
256
+ }
257
+ if (!transport) {
258
+ console.warn("received message before device was opened");
259
+ return;
260
+ }
261
+ try {
262
+ const res = await transport.exchange(Buffer.from(apduHex, "hex"));
263
+ (0, logs_1.log)("proxy", `WS(${index}): ${apduHex} => ${res.toString("hex")}`);
264
+ if (destroyed)
265
+ return;
266
+ ws.send(JSON.stringify({
267
+ type: "response",
268
+ data: res.toString("hex"),
269
+ }));
199
270
  }
200
271
  catch (e) {
201
- res.sendStatus(400);
202
- console.error(e.message);
203
- process.exit(1);
272
+ (0, logs_1.log)("proxy", `WS(${index}): ${apduHex} =>`, e);
273
+ if (destroyed)
274
+ return;
275
+ ws.send(JSON.stringify({
276
+ type: "error",
277
+ error: e.message,
278
+ }));
279
+ if (e.name === "RecordStoreWrongAPDU") {
280
+ console.error(e.message);
281
+ process.exit(1);
282
+ }
204
283
  }
205
284
  });
206
285
  }
207
- var pending = false;
208
- app.post("/", body_parser_1.default.json(), function (req, res) { return __awaiter(void 0, void 0, void 0, function () {
209
- var data, error, transport, e_1, result;
210
- return __generator(this, function (_a) {
211
- switch (_a.label) {
212
- case 0:
213
- if (!req.body)
214
- return [2 /*return*/, res.sendStatus(400)];
215
- data = null;
216
- error = null;
217
- if (pending) {
218
- return [2 /*return*/, res.status(400).json({
219
- error: "an exchange query was already pending",
220
- })];
221
- }
222
- pending = true;
223
- _a.label = 1;
224
- case 1:
225
- _a.trys.push([1, 7, , 8]);
226
- return [4 /*yield*/, Transport.open()];
227
- case 2:
228
- transport = _a.sent();
229
- _a.label = 3;
230
- case 3:
231
- _a.trys.push([3, , 5, 6]);
232
- return [4 /*yield*/, transport.exchange(Buffer.from(req.body.apduHex, "hex"))];
233
- case 4:
234
- data = _a.sent();
235
- return [3 /*break*/, 6];
236
- case 5:
237
- transport.close();
238
- if (saveToFile) {
239
- fs_1.default.writeFileSync(saveToFile, recordStore.toString());
240
- }
241
- else if (recordStore) {
242
- if (recordStore.isEmpty()) {
243
- process.exit(0);
244
- }
245
- }
246
- return [7 /*endfinally*/];
247
- case 6: return [3 /*break*/, 8];
248
- case 7:
249
- e_1 = _a.sent();
250
- error = e_1;
251
- return [3 /*break*/, 8];
252
- case 8:
253
- pending = false;
254
- result = {
255
- data: data,
256
- error: error,
257
- };
258
- if (data) {
259
- // @ts-expect-error 3 args only, we give 5
260
- (0, logs_1.log)("proxy", "HTTP:", req.body.apduHex, "=>", data.toString("hex"));
261
- }
262
- else {
263
- // @ts-expect-error 3 args only, we give 5
264
- (0, logs_1.log)("proxy", "HTTP:", req.body.apduHex, "=>", error);
265
- }
266
- res.json(result);
267
- if (error && error.name === "RecordStoreWrongAPDU") {
268
- console.error(error.message);
269
- process.exit(1);
270
- }
271
- return [2 /*return*/];
272
- }
273
- });
274
- }); });
275
- var wsIndex = 0;
276
- var wsBusyIndex = 0;
277
- wss.on("connection", function (ws) {
278
- var index = ++wsIndex;
279
- try {
280
- var transport_1;
281
- var transportP_1;
282
- var destroyed_1 = false;
283
- var onClose = function () { return __awaiter(void 0, void 0, void 0, function () {
284
- return __generator(this, function (_a) {
285
- switch (_a.label) {
286
- case 0:
287
- if (destroyed_1)
288
- return [2 /*return*/];
289
- destroyed_1 = true;
290
- if (!(wsBusyIndex === index)) return [3 /*break*/, 2];
291
- (0, logs_1.log)("proxy", "WS(".concat(index, "): close"));
292
- return [4 /*yield*/, transportP_1.then(function (t) { return t.close(); }, function () { })];
293
- case 1:
294
- _a.sent();
295
- wsBusyIndex = 0;
296
- _a.label = 2;
297
- case 2:
298
- if (saveToFile) {
299
- fs_1.default.writeFileSync(saveToFile, recordStore.toString());
300
- }
301
- else if (recordStore) {
302
- if (recordStore.isEmpty()) {
303
- process.exit(0);
304
- }
305
- }
306
- return [2 /*return*/];
307
- }
308
- });
309
- }); };
310
- ws.on("close", onClose);
311
- ws.on("message", function (data, isBinary) { return __awaiter(void 0, void 0, void 0, function () {
312
- var apduHex, e_2, res, e_3;
313
- return __generator(this, function (_a) {
314
- switch (_a.label) {
315
- case 0:
316
- if (destroyed_1)
317
- return [2 /*return*/];
318
- apduHex = isBinary ? data : data.toString();
319
- if (!(apduHex === "open")) return [3 /*break*/, 5];
320
- if (wsBusyIndex) {
321
- ws.send(JSON.stringify({
322
- error: "WebSocket is busy (previous session not closed)",
323
- }));
324
- ws.close();
325
- destroyed_1 = true;
326
- return [2 /*return*/];
327
- }
328
- transportP_1 = Transport.open();
329
- wsBusyIndex = index;
330
- (0, logs_1.log)("proxy", "WS(".concat(index, "): opening..."));
331
- _a.label = 1;
332
- case 1:
333
- _a.trys.push([1, 3, , 4]);
334
- return [4 /*yield*/, transportP_1];
335
- case 2:
336
- transport_1 = _a.sent();
337
- transport_1.on("disconnect", function () { return ws.close(); });
338
- (0, logs_1.log)("proxy", "WS(".concat(index, "): opened!"));
339
- ws.send(JSON.stringify({
340
- type: "opened",
341
- }));
342
- return [3 /*break*/, 4];
343
- case 3:
344
- e_2 = _a.sent();
345
- (0, logs_1.log)("proxy", "WS(".concat(index, "): open failed! ").concat(e_2));
346
- ws.send(JSON.stringify({
347
- error: e_2.message,
348
- }));
349
- ws.close();
350
- return [3 /*break*/, 4];
351
- case 4: return [2 /*return*/];
352
- case 5:
353
- if (wsBusyIndex !== index) {
354
- console.warn("ignoring message because busy transport");
355
- return [2 /*return*/];
356
- }
357
- if (!transport_1) {
358
- console.warn("received message before device was opened");
359
- return [2 /*return*/];
360
- }
361
- _a.label = 6;
362
- case 6:
363
- _a.trys.push([6, 8, , 9]);
364
- return [4 /*yield*/, transport_1.exchange(Buffer.from(apduHex, "hex"))];
365
- case 7:
366
- res = _a.sent();
367
- (0, logs_1.log)("proxy", "WS(".concat(index, "): ").concat(apduHex, " => ").concat(res.toString("hex")));
368
- if (destroyed_1)
369
- return [2 /*return*/];
370
- ws.send(JSON.stringify({
371
- type: "response",
372
- data: res.toString("hex"),
373
- }));
374
- return [3 /*break*/, 9];
375
- case 8:
376
- e_3 = _a.sent();
377
- (0, logs_1.log)("proxy", "WS(".concat(index, "): ").concat(apduHex, " =>"), e_3);
378
- if (destroyed_1)
379
- return [2 /*return*/];
380
- ws.send(JSON.stringify({
381
- type: "error",
382
- error: e_3.message,
383
- }));
384
- if (e_3.name === "RecordStoreWrongAPDU") {
385
- console.error(e_3.message);
386
- process.exit(1);
387
- }
388
- return [3 /*break*/, 9];
389
- case 9: return [2 /*return*/];
390
- }
391
- });
392
- }); });
393
- }
394
- catch (e) {
395
- ws.close();
396
- }
397
- });
398
- __spreadArray(["localhost"], __read(ips), false).map(function (ip) { return "ws://".concat(ip, ":").concat(PORT); })
399
- .forEach(function (ip) {
400
- (0, logs_1.log)("proxy", "DEVICE_PROXY_URL=" + ip);
401
- });
402
- server.listen(PORT, function () {
403
- (0, logs_1.log)("proxy", "\nNano S proxy started on ".concat(ips[0], "\n"));
404
- });
405
- return function () {
406
- unsub();
407
- };
286
+ catch (e) {
287
+ ws.close();
288
+ }
408
289
  });
409
- };
290
+ ["localhost", ...ips]
291
+ .map(ip => `ws://${ip}:${PORT}`)
292
+ .forEach(ip => {
293
+ (0, logs_1.log)("proxy", "DEVICE_PROXY_URL=" + ip);
294
+ });
295
+ server.listen(PORT, () => {
296
+ (0, logs_1.log)("proxy", `\nNano S proxy started on ${ips[0]}\n`);
297
+ });
298
+ return () => {
299
+ unsub();
300
+ };
301
+ });
410
302
  exports.default = {
411
- args: args,
412
- job: job,
303
+ args,
304
+ job,
413
305
  };
414
306
  //# sourceMappingURL=proxy.js.map