@trezor/connect 9.5.0-beta.1 → 9.5.1-beta.1
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.
- package/CHANGELOG.md +66 -62
- package/README.md +1 -1
- package/lib/api/bitcoin/BitcoinFees.d.ts +25 -0
- package/lib/api/bitcoin/{Fees.js → BitcoinFees.js} +8 -29
- package/lib/api/bitcoin/TransactionComposer.d.ts +2 -2
- package/lib/api/bitcoin/TransactionComposer.js +5 -5
- package/lib/api/bitcoin/index.d.ts +1 -1
- package/lib/api/bitcoin/index.js +1 -1
- package/lib/api/blockchainEstimateFee.js +15 -4
- package/lib/api/{bitcoin/Fees.d.ts → common/MiscFees.d.ts} +10 -11
- package/lib/api/common/MiscFees.js +46 -0
- package/lib/api/common/paramsValidator.js +1 -1
- package/lib/api/ethereum/EthereumFees.d.ts +24 -0
- package/lib/api/ethereum/EthereumFees.js +71 -0
- package/lib/api/ethereum/api/ethereumSignTypedData.d.ts +6 -0
- package/lib/api/ethereum/ethereumDefinitions.js +1 -3
- package/lib/api/getCoinInfo.d.ts +18 -0
- package/lib/api/solana/api/solanaComposeTransaction.d.ts +1 -2
- package/lib/api/solana/api/solanaComposeTransaction.js +2 -5
- package/lib/api/unlockPath.d.ts +1 -1
- package/lib/backend/Blockchain.d.ts +1 -0
- package/lib/core/AbstractMethod.js +1 -1
- package/lib/data/coinInfo.d.ts +66 -0
- package/lib/data/connectSettings.js +6 -1
- package/lib/data/defaultFeeLevels.js +1 -1
- package/lib/data/version.d.ts +1 -1
- package/lib/data/version.js +1 -1
- package/lib/device/Device.d.ts +3 -5
- package/lib/device/Device.js +25 -20
- package/lib/device/DeviceList.d.ts +6 -13
- package/lib/device/DeviceList.js +44 -174
- package/lib/device/TransportList.d.ts +9 -0
- package/lib/device/TransportList.js +50 -0
- package/lib/device/TransportManager.d.ts +34 -0
- package/lib/device/TransportManager.js +149 -0
- package/lib/device/checkFirmwareRevision.js +9 -5
- package/lib/types/api/solana/index.d.ts +1 -2
- package/lib/types/api/solana/index.js +1 -2
- package/lib/types/coinInfo.d.ts +36 -0
- package/lib/types/device.d.ts +6 -0
- package/lib/types/fees.d.ts +13 -0
- package/lib/types/fees.js +13 -1
- package/lib/types/settings.d.ts +3 -1
- package/lib/types/utils.d.ts +0 -1
- package/lib/types/utils.js +0 -3
- package/lib/utils/assets-browser.d.ts +4 -0
- package/lib/utils/assets-browser.js +11 -2
- package/package.json +16 -16
package/lib/device/DeviceList.js
CHANGED
|
@@ -6,9 +6,9 @@ const utils_1 = require("@trezor/utils");
|
|
|
6
6
|
const constants_1 = require("../constants");
|
|
7
7
|
const events_1 = require("../events");
|
|
8
8
|
const Device_1 = require("./Device");
|
|
9
|
-
const transportInfo_1 = require("../data/transportInfo");
|
|
10
9
|
const types_1 = require("../types");
|
|
11
|
-
const
|
|
10
|
+
const TransportList_1 = require("./TransportList");
|
|
11
|
+
const TransportManager_1 = require("./TransportManager");
|
|
12
12
|
const debug_1 = require("../utils/debug");
|
|
13
13
|
const createAuthPenaltyManager = (priority) => {
|
|
14
14
|
const penalizedDevices = {};
|
|
@@ -67,100 +67,42 @@ const assertDeviceListConnected = deviceList => {
|
|
|
67
67
|
};
|
|
68
68
|
exports.assertDeviceListConnected = assertDeviceListConnected;
|
|
69
69
|
class DeviceList extends utils_1.TypedEmitter {
|
|
70
|
-
|
|
70
|
+
transportManagers = {};
|
|
71
71
|
transports = [];
|
|
72
72
|
devices = createDeviceCollection();
|
|
73
73
|
deviceCounter = Date.now();
|
|
74
74
|
handshakeLock;
|
|
75
75
|
authPenaltyManager;
|
|
76
|
-
|
|
76
|
+
updateTransports;
|
|
77
|
+
getConnectedTransports() {
|
|
78
|
+
return Object.values(this.transportManagers)
|
|
79
|
+
.map(manager => manager.get())
|
|
80
|
+
.filter(utils_1.isNotUndefined);
|
|
81
|
+
}
|
|
77
82
|
isConnected() {
|
|
78
|
-
return !!
|
|
83
|
+
return !!this.getConnectedTransports().length;
|
|
79
84
|
}
|
|
80
85
|
pendingConnection() {
|
|
81
|
-
const pending = Object.values(this.
|
|
82
|
-
.map(
|
|
86
|
+
const pending = Object.values(this.transportManagers)
|
|
87
|
+
.map(manager => manager.pending())
|
|
83
88
|
.filter(utils_1.isNotUndefined);
|
|
84
89
|
if (pending.length)
|
|
85
90
|
return Promise.all(pending).then(() => { });
|
|
86
91
|
}
|
|
87
92
|
getActiveTransports() {
|
|
88
|
-
return
|
|
89
|
-
}
|
|
90
|
-
locks = {};
|
|
91
|
-
async transportLock(apiType, abortMessage, action) {
|
|
92
|
-
const lock = this.locks[apiType] ?? (this.locks[apiType] = { sequence: 0 });
|
|
93
|
-
lock.abortMessage = abortMessage;
|
|
94
|
-
const sequence = ++lock.sequence;
|
|
95
|
-
while (lock.promise) {
|
|
96
|
-
lock.abort?.abort(new Error(abortMessage));
|
|
97
|
-
await lock.promise.catch(() => { });
|
|
98
|
-
}
|
|
99
|
-
if (sequence !== lock.sequence)
|
|
100
|
-
return Promise.reject(new Error(lock.abortMessage));
|
|
101
|
-
lock.abort = new AbortController();
|
|
102
|
-
lock.promise = action(lock.abort.signal).finally(() => {
|
|
103
|
-
delete lock.abort;
|
|
104
|
-
delete lock.promise;
|
|
105
|
-
});
|
|
106
|
-
return lock.promise;
|
|
93
|
+
return this.getConnectedTransports().map(getTransportInfo);
|
|
107
94
|
}
|
|
108
|
-
scheduledUpgradeChecks = {};
|
|
109
95
|
constructor({ messages, priority, debug, _sessionsBackgroundUrl, manifest, }) {
|
|
110
96
|
super();
|
|
111
97
|
const transportLogger = (0, debug_1.initLog)('@trezor/transport', debug);
|
|
112
98
|
this.handshakeLock = (0, utils_1.getSynchronize)();
|
|
113
99
|
this.authPenaltyManager = createAuthPenaltyManager(priority);
|
|
114
|
-
this.
|
|
100
|
+
this.updateTransports = (0, TransportList_1.createTransportList)({
|
|
115
101
|
messages,
|
|
116
102
|
logger: transportLogger,
|
|
117
103
|
sessionsBackgroundUrl: _sessionsBackgroundUrl,
|
|
118
104
|
id: manifest?.appUrl || 'unknown app',
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
tryGetTransport(name) {
|
|
122
|
-
return this.transports.find(t => t.name === name);
|
|
123
|
-
}
|
|
124
|
-
getOrCreateTransport(transportType) {
|
|
125
|
-
const { transportCommonArgs } = this;
|
|
126
|
-
if (typeof transportType === 'string') {
|
|
127
|
-
const existing = this.tryGetTransport(transportType);
|
|
128
|
-
if (existing)
|
|
129
|
-
return existing;
|
|
130
|
-
switch (transportType) {
|
|
131
|
-
case 'WebUsbTransport':
|
|
132
|
-
return new transport_1.WebUsbTransport(transportCommonArgs);
|
|
133
|
-
case 'NodeUsbTransport':
|
|
134
|
-
return new transport_1.NodeUsbTransport(transportCommonArgs);
|
|
135
|
-
case 'BridgeTransport':
|
|
136
|
-
return new transport_1.BridgeTransport({
|
|
137
|
-
latestVersion: (0, transportInfo_1.getBridgeInfo)().version.join('.'),
|
|
138
|
-
...transportCommonArgs,
|
|
139
|
-
});
|
|
140
|
-
case 'UdpTransport':
|
|
141
|
-
return new transport_1.UdpTransport(transportCommonArgs);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
else if (typeof transportType === 'function' && 'prototype' in transportType) {
|
|
145
|
-
const transportInstance = new transportType(transportCommonArgs);
|
|
146
|
-
if ((0, transport_1.isTransportInstance)(transportInstance)) {
|
|
147
|
-
return this.tryGetTransport(transportInstance.name) ?? transportInstance;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
else if ((0, transport_1.isTransportInstance)(transportType)) {
|
|
151
|
-
if (this.tryGetTransport(transportType.name)) {
|
|
152
|
-
return transportType;
|
|
153
|
-
}
|
|
154
|
-
if (!transportType.getMessage()) {
|
|
155
|
-
transportType.updateMessages(transportCommonArgs.messages);
|
|
156
|
-
}
|
|
157
|
-
return transportType;
|
|
158
|
-
}
|
|
159
|
-
throw constants_1.ERRORS.TypedError('Runtime', `DeviceList.init: transports[] of unexpected type: ${transportType}`);
|
|
160
|
-
}
|
|
161
|
-
createTransports(transports) {
|
|
162
|
-
const transportTypes = transports?.length ? transports : ['BridgeTransport'];
|
|
163
|
-
return transportTypes.map(this.getOrCreateTransport.bind(this));
|
|
105
|
+
});
|
|
164
106
|
}
|
|
165
107
|
onDeviceConnected(descriptor, transport) {
|
|
166
108
|
const id = (this.deviceCounter++).toString(16).slice(-8);
|
|
@@ -190,103 +132,41 @@ class DeviceList extends utils_1.TypedEmitter {
|
|
|
190
132
|
const device = this.devices.get(descriptor.path, transport);
|
|
191
133
|
device?.usedElsewhere();
|
|
192
134
|
}
|
|
193
|
-
|
|
194
|
-
|
|
135
|
+
getOrCreateTransportManager(apiType) {
|
|
136
|
+
if (!this.transportManagers[apiType]) {
|
|
137
|
+
const manager = new TransportManager_1.TransportManager({
|
|
138
|
+
startTransport: this.startTransport.bind(this),
|
|
139
|
+
stopTransport: this.stopTransport.bind(this),
|
|
140
|
+
});
|
|
141
|
+
manager.on(transport_1.TRANSPORT.START, transport => this.emit(transport_1.TRANSPORT.START, getTransportInfo(transport)));
|
|
142
|
+
manager.on(transport_1.TRANSPORT.ERROR, error => this.emit(transport_1.TRANSPORT.ERROR, { apiType, error }));
|
|
143
|
+
this.transportManagers[apiType] = manager;
|
|
144
|
+
}
|
|
145
|
+
return this.transportManagers[apiType];
|
|
146
|
+
}
|
|
147
|
+
async init({ transports, transportReconnect, pendingTransportEvent } = {}) {
|
|
148
|
+
this.transports = this.updateTransports(this.transports, transports);
|
|
195
149
|
const promises = this.transports
|
|
196
150
|
.map(t => t.apiType)
|
|
197
|
-
.concat((0,
|
|
198
|
-
.concat((0, utils_2.typedObjectKeys)(this.locks))
|
|
151
|
+
.concat((0, utils_1.typedObjectKeys)(this.transportManagers))
|
|
199
152
|
.filter(utils_1.arrayDistinct)
|
|
200
|
-
.map(apiType => this.
|
|
153
|
+
.map(apiType => this.getOrCreateTransportManager(apiType).init({
|
|
154
|
+
transports: this.transports.filter(t => t.apiType === apiType),
|
|
155
|
+
transportReconnect,
|
|
156
|
+
pendingTransportEvent,
|
|
157
|
+
}));
|
|
201
158
|
await Promise.all(promises);
|
|
202
159
|
}
|
|
203
|
-
async
|
|
160
|
+
async startTransport(transport, pendingTransportEvent, signal) {
|
|
204
161
|
try {
|
|
205
|
-
|
|
206
|
-
const transport = transports.length
|
|
207
|
-
? await this.selectTransport(transports, abortSignal)
|
|
208
|
-
: undefined;
|
|
209
|
-
const oldTransport = this.transport[apiType];
|
|
210
|
-
if (oldTransport !== transport) {
|
|
211
|
-
if (oldTransport) {
|
|
212
|
-
delete this.transport[apiType];
|
|
213
|
-
await this.stopTransport(oldTransport);
|
|
214
|
-
if (!transport) {
|
|
215
|
-
this.emit(transport_1.TRANSPORT.ERROR, { apiType, error: 'Transport disabled' });
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
if (transport) {
|
|
219
|
-
try {
|
|
220
|
-
await this.initializeTransport(transport, initParams, abortSignal);
|
|
221
|
-
}
|
|
222
|
-
catch (error) {
|
|
223
|
-
await this.stopTransport(transport);
|
|
224
|
-
throw error;
|
|
225
|
-
}
|
|
226
|
-
transport.on(transport_1.TRANSPORT.ERROR, error => {
|
|
227
|
-
this.emit(transport_1.TRANSPORT.ERROR, { apiType, error });
|
|
228
|
-
this.transportLock(apiType, 'Transport error', async (signal) => {
|
|
229
|
-
delete this.transport[apiType];
|
|
230
|
-
await this.stopTransport(transport);
|
|
231
|
-
if (initParams.transportReconnect) {
|
|
232
|
-
await this.createReconnectDelay(signal);
|
|
233
|
-
await this.createInitPromise(apiType, initParams, signal);
|
|
234
|
-
}
|
|
235
|
-
}).catch(() => { });
|
|
236
|
-
});
|
|
237
|
-
this.transport[apiType] = transport;
|
|
238
|
-
this.emit(transport_1.TRANSPORT.START, getTransportInfo(transport));
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
if (transport && transport !== transports[0]) {
|
|
242
|
-
this.scheduleUpgradeCheck(apiType, initParams);
|
|
243
|
-
}
|
|
162
|
+
await this.initializeTransport(transport, pendingTransportEvent, signal);
|
|
244
163
|
}
|
|
245
|
-
catch (
|
|
246
|
-
this.
|
|
247
|
-
|
|
248
|
-
this.transportLock(apiType, 'Reconnecting', async (signal) => {
|
|
249
|
-
await this.createReconnectDelay(signal);
|
|
250
|
-
await this.createInitPromise(apiType, initParams, signal);
|
|
251
|
-
}).catch(() => { });
|
|
252
|
-
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
await this.stopTransport(transport);
|
|
166
|
+
throw err;
|
|
253
167
|
}
|
|
254
168
|
}
|
|
255
|
-
|
|
256
|
-
return (0, utils_1.resolveAfter)(1000, signal);
|
|
257
|
-
}
|
|
258
|
-
scheduleUpgradeCheck(apiType, initParams) {
|
|
259
|
-
clearTimeout(this.scheduledUpgradeChecks[apiType]);
|
|
260
|
-
this.scheduledUpgradeChecks[apiType] = setTimeout(async () => {
|
|
261
|
-
const transport = this.transport[apiType];
|
|
262
|
-
const transports = this.transports.filter(t => t.apiType === apiType);
|
|
263
|
-
if (!transport || transport === transports[0])
|
|
264
|
-
return;
|
|
265
|
-
for (const t of transports) {
|
|
266
|
-
if (t === transport)
|
|
267
|
-
break;
|
|
268
|
-
if (await t.ping()) {
|
|
269
|
-
this.transportLock(apiType, 'Upgrading', signal => this.createInitPromise(apiType, initParams, signal)).catch(() => { });
|
|
270
|
-
return;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
this.scheduleUpgradeCheck(apiType, initParams);
|
|
274
|
-
}, 1000);
|
|
275
|
-
}
|
|
276
|
-
async selectTransport([transport, ...rest], signal) {
|
|
277
|
-
if (signal.aborted)
|
|
278
|
-
throw new Error(signal.reason);
|
|
279
|
-
if (transport === this.transport[transport.apiType])
|
|
280
|
-
return transport;
|
|
281
|
-
const result = await transport.init({ signal });
|
|
282
|
-
if (result.success)
|
|
283
|
-
return transport;
|
|
284
|
-
else if (rest.length)
|
|
285
|
-
return this.selectTransport(rest, signal);
|
|
286
|
-
else
|
|
287
|
-
throw new Error(result.error);
|
|
288
|
-
}
|
|
289
|
-
async initializeTransport(transport, initParams, signal) {
|
|
169
|
+
async initializeTransport(transport, pendingTransportEvent, signal) {
|
|
290
170
|
transport.on(transport_1.TRANSPORT.DEVICE_CONNECTED, d => this.onDeviceConnected(d, transport));
|
|
291
171
|
transport.on(transport_1.TRANSPORT.DEVICE_DISCONNECTED, d => this.onDeviceDisconnected(d, transport));
|
|
292
172
|
transport.on(transport_1.TRANSPORT.DEVICE_SESSION_CHANGED, d => this.onDeviceSessionChanged(d, transport));
|
|
@@ -296,7 +176,7 @@ class DeviceList extends utils_1.TypedEmitter {
|
|
|
296
176
|
throw new Error(enumerateResult.error);
|
|
297
177
|
}
|
|
298
178
|
const descriptors = enumerateResult.payload;
|
|
299
|
-
const waitForDevicesPromise =
|
|
179
|
+
const waitForDevicesPromise = pendingTransportEvent && descriptors.length
|
|
300
180
|
? this.waitForDevices(transport, descriptors, signal)
|
|
301
181
|
: Promise.resolve();
|
|
302
182
|
transport.handleDescriptorsChange(descriptors);
|
|
@@ -348,20 +228,10 @@ class DeviceList extends utils_1.TypedEmitter {
|
|
|
348
228
|
}
|
|
349
229
|
async dispose() {
|
|
350
230
|
this.removeAllListeners();
|
|
351
|
-
const promises = (
|
|
352
|
-
.concat((0, utils_2.typedObjectKeys)(this.locks))
|
|
353
|
-
.filter(utils_1.arrayDistinct)
|
|
354
|
-
.map(apiType => this.transportLock(apiType, 'Disposing', async () => {
|
|
355
|
-
const transport = this.transport[apiType];
|
|
356
|
-
if (transport) {
|
|
357
|
-
delete this.transport[apiType];
|
|
358
|
-
await this.stopTransport(transport);
|
|
359
|
-
}
|
|
360
|
-
}));
|
|
231
|
+
const promises = Object.values(this.transportManagers).map(manager => manager.dispose());
|
|
361
232
|
await Promise.all(promises);
|
|
362
233
|
}
|
|
363
234
|
async stopTransport(transport) {
|
|
364
|
-
clearTimeout(this.scheduledUpgradeChecks[transport.apiType]);
|
|
365
235
|
const devices = this.devices.clear(transport);
|
|
366
236
|
devices.forEach(device => {
|
|
367
237
|
this.emit(events_1.DEVICE.DISCONNECT, device);
|
|
@@ -373,7 +243,7 @@ class DeviceList extends utils_1.TypedEmitter {
|
|
|
373
243
|
transport?.stop();
|
|
374
244
|
}
|
|
375
245
|
async enumerate() {
|
|
376
|
-
const promises =
|
|
246
|
+
const promises = this.getConnectedTransports().map(async (transport) => {
|
|
377
247
|
const res = await transport.enumerate();
|
|
378
248
|
if (!res.success) {
|
|
379
249
|
return;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { BridgeTransport, NodeUsbTransport, Transport, UdpTransport } from '@trezor/transport';
|
|
2
|
+
import type { AbstractTransportParams } from '@trezor/transport/lib/transports/abstract';
|
|
3
|
+
import { ConnectSettingsTransport } from '../types';
|
|
4
|
+
type Params = AbstractTransportParams & {
|
|
5
|
+
sessionsBackgroundUrl?: string | null;
|
|
6
|
+
};
|
|
7
|
+
export declare const createTransportList: (params: Params) => (existing: Transport[], transports?: ConnectSettingsTransport[]) => (Transport | NodeUsbTransport | BridgeTransport | UdpTransport)[];
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=TransportList.d.ts.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createTransportList = void 0;
|
|
4
|
+
const transport_1 = require("@trezor/transport");
|
|
5
|
+
const constants_1 = require("../constants");
|
|
6
|
+
const transportInfo_1 = require("../data/transportInfo");
|
|
7
|
+
const tryGetTransport = (transports, name) => transports.find(t => t.name === name);
|
|
8
|
+
const getOrCreateTransport = (transports, transportType, params) => {
|
|
9
|
+
if (typeof transportType === 'string') {
|
|
10
|
+
const existing = tryGetTransport(transports, transportType);
|
|
11
|
+
if (existing)
|
|
12
|
+
return existing;
|
|
13
|
+
switch (transportType) {
|
|
14
|
+
case 'WebUsbTransport':
|
|
15
|
+
return new transport_1.WebUsbTransport(params);
|
|
16
|
+
case 'NodeUsbTransport':
|
|
17
|
+
return new transport_1.NodeUsbTransport(params);
|
|
18
|
+
case 'BridgeTransport':
|
|
19
|
+
return new transport_1.BridgeTransport({
|
|
20
|
+
latestVersion: (0, transportInfo_1.getBridgeInfo)().version.join('.'),
|
|
21
|
+
...params,
|
|
22
|
+
});
|
|
23
|
+
case 'UdpTransport':
|
|
24
|
+
return new transport_1.UdpTransport(params);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
else if (typeof transportType === 'function' && 'prototype' in transportType) {
|
|
28
|
+
const transportInstance = new transportType(params);
|
|
29
|
+
if ((0, transport_1.isTransportInstance)(transportInstance)) {
|
|
30
|
+
return tryGetTransport(transports, transportInstance.name) ?? transportInstance;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else if ((0, transport_1.isTransportInstance)(transportType)) {
|
|
34
|
+
if (tryGetTransport(transports, transportType.name)) {
|
|
35
|
+
return transportType;
|
|
36
|
+
}
|
|
37
|
+
if (!transportType.getMessage()) {
|
|
38
|
+
transportType.updateMessages(params.messages);
|
|
39
|
+
}
|
|
40
|
+
return transportType;
|
|
41
|
+
}
|
|
42
|
+
throw constants_1.ERRORS.TypedError('Runtime', `DeviceList.init: transports[] of unexpected type: ${transportType}`);
|
|
43
|
+
};
|
|
44
|
+
const createTransports = (existing, transports = [], params) => {
|
|
45
|
+
const transportTypes = transports?.length ? transports : ['BridgeTransport'];
|
|
46
|
+
return transportTypes.map(type => getOrCreateTransport(existing, type, params));
|
|
47
|
+
};
|
|
48
|
+
const createTransportList = (params) => (existing, transports) => createTransports(existing, transports, params);
|
|
49
|
+
exports.createTransportList = createTransportList;
|
|
50
|
+
//# sourceMappingURL=TransportList.js.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { TRANSPORT, Transport } from '@trezor/transport';
|
|
2
|
+
import { TypedEmitter } from '@trezor/utils';
|
|
3
|
+
type TransportManagerEvents = {
|
|
4
|
+
[TRANSPORT.START]: Transport;
|
|
5
|
+
[TRANSPORT.ERROR]: string;
|
|
6
|
+
};
|
|
7
|
+
type TransportManagerParams = {
|
|
8
|
+
startTransport: (transport: Transport, pendingTransportEvent: boolean, signal: AbortSignal) => Promise<void>;
|
|
9
|
+
stopTransport: (transport: Transport) => Promise<void>;
|
|
10
|
+
};
|
|
11
|
+
type InitParams = {
|
|
12
|
+
transports: Transport[];
|
|
13
|
+
transportReconnect?: boolean;
|
|
14
|
+
pendingTransportEvent?: boolean;
|
|
15
|
+
};
|
|
16
|
+
export declare class TransportManager extends TypedEmitter<TransportManagerEvents> {
|
|
17
|
+
private lock;
|
|
18
|
+
private transports;
|
|
19
|
+
private activeTransport?;
|
|
20
|
+
private transportReconnect;
|
|
21
|
+
private upgradeTimeout?;
|
|
22
|
+
private readonly startTransport;
|
|
23
|
+
private readonly stopTransport;
|
|
24
|
+
constructor({ startTransport, stopTransport }: TransportManagerParams);
|
|
25
|
+
pending(): Promise<void> | undefined;
|
|
26
|
+
get(): Transport | undefined;
|
|
27
|
+
init({ transports, transportReconnect, pendingTransportEvent }: InitParams): Promise<void>;
|
|
28
|
+
dispose(): Promise<void>;
|
|
29
|
+
private selectTransport;
|
|
30
|
+
private scheduleUpgradeCheck;
|
|
31
|
+
private createInitPromise;
|
|
32
|
+
}
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=TransportManager.d.ts.map
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TransportManager = void 0;
|
|
4
|
+
const transport_1 = require("@trezor/transport");
|
|
5
|
+
const utils_1 = require("@trezor/utils");
|
|
6
|
+
const createOverrideLock = () => {
|
|
7
|
+
let promise;
|
|
8
|
+
let sequence = 0;
|
|
9
|
+
let abort;
|
|
10
|
+
let message;
|
|
11
|
+
const override = async (abortMessage, action) => {
|
|
12
|
+
message = abortMessage;
|
|
13
|
+
const seq = ++sequence;
|
|
14
|
+
while (promise) {
|
|
15
|
+
abort?.abort(new Error(abortMessage));
|
|
16
|
+
await promise.catch(() => { });
|
|
17
|
+
}
|
|
18
|
+
if (seq !== sequence)
|
|
19
|
+
return Promise.reject(new Error(message));
|
|
20
|
+
abort = new AbortController();
|
|
21
|
+
promise = action(abort.signal).finally(() => {
|
|
22
|
+
abort = undefined;
|
|
23
|
+
promise = undefined;
|
|
24
|
+
});
|
|
25
|
+
return promise;
|
|
26
|
+
};
|
|
27
|
+
const getPending = () => promise;
|
|
28
|
+
return { override, getPending };
|
|
29
|
+
};
|
|
30
|
+
class TransportManager extends utils_1.TypedEmitter {
|
|
31
|
+
lock = createOverrideLock();
|
|
32
|
+
transports = [];
|
|
33
|
+
activeTransport;
|
|
34
|
+
transportReconnect = false;
|
|
35
|
+
upgradeTimeout;
|
|
36
|
+
startTransport;
|
|
37
|
+
stopTransport;
|
|
38
|
+
constructor({ startTransport, stopTransport }) {
|
|
39
|
+
super();
|
|
40
|
+
this.startTransport = startTransport;
|
|
41
|
+
this.stopTransport = stopTransport;
|
|
42
|
+
}
|
|
43
|
+
pending() {
|
|
44
|
+
return this.lock.getPending();
|
|
45
|
+
}
|
|
46
|
+
get() {
|
|
47
|
+
return this.activeTransport;
|
|
48
|
+
}
|
|
49
|
+
init({ transports, transportReconnect = false, pendingTransportEvent = false }) {
|
|
50
|
+
this.transports = transports;
|
|
51
|
+
this.transportReconnect = transportReconnect;
|
|
52
|
+
return this.lock.override('New init', signal => this.createInitPromise(pendingTransportEvent, signal));
|
|
53
|
+
}
|
|
54
|
+
dispose() {
|
|
55
|
+
this.removeAllListeners();
|
|
56
|
+
return this.lock.override('Disposing', async () => {
|
|
57
|
+
const { activeTransport } = this;
|
|
58
|
+
if (activeTransport) {
|
|
59
|
+
clearTimeout(this.upgradeTimeout);
|
|
60
|
+
delete this.activeTransport;
|
|
61
|
+
await this.stopTransport(activeTransport);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
async selectTransport([transport, ...rest], signal) {
|
|
66
|
+
if (signal.aborted)
|
|
67
|
+
throw new Error(signal.reason);
|
|
68
|
+
if (transport === this.activeTransport)
|
|
69
|
+
return transport;
|
|
70
|
+
const result = await transport.init({ signal });
|
|
71
|
+
if (result.success)
|
|
72
|
+
return transport;
|
|
73
|
+
else if (rest.length)
|
|
74
|
+
return this.selectTransport(rest, signal);
|
|
75
|
+
else
|
|
76
|
+
throw new Error(result.error);
|
|
77
|
+
}
|
|
78
|
+
scheduleUpgradeCheck(pendingTransportEvent) {
|
|
79
|
+
clearTimeout(this.upgradeTimeout);
|
|
80
|
+
this.upgradeTimeout = setTimeout(async () => {
|
|
81
|
+
if (!this.activeTransport || this.activeTransport === this.transports[0])
|
|
82
|
+
return;
|
|
83
|
+
for (const t of this.transports) {
|
|
84
|
+
if (t === this.activeTransport)
|
|
85
|
+
break;
|
|
86
|
+
if (await t.ping()) {
|
|
87
|
+
this.lock
|
|
88
|
+
.override('Upgrading', signal => this.createInitPromise(pendingTransportEvent, signal))
|
|
89
|
+
.catch(() => { });
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
this.scheduleUpgradeCheck(pendingTransportEvent);
|
|
94
|
+
}, 1000);
|
|
95
|
+
}
|
|
96
|
+
async createInitPromise(pendingTransportEvent, abortSignal) {
|
|
97
|
+
try {
|
|
98
|
+
const { transports, activeTransport } = this;
|
|
99
|
+
const transport = transports.length
|
|
100
|
+
? await this.selectTransport(transports, abortSignal)
|
|
101
|
+
: undefined;
|
|
102
|
+
if (activeTransport !== transport) {
|
|
103
|
+
if (activeTransport) {
|
|
104
|
+
clearTimeout(this.upgradeTimeout);
|
|
105
|
+
delete this.activeTransport;
|
|
106
|
+
await this.stopTransport(activeTransport);
|
|
107
|
+
}
|
|
108
|
+
if (transport) {
|
|
109
|
+
await this.startTransport(transport, pendingTransportEvent, abortSignal);
|
|
110
|
+
transport.on(transport_1.TRANSPORT.ERROR, error => {
|
|
111
|
+
this.emit(transport_1.TRANSPORT.ERROR, error);
|
|
112
|
+
clearTimeout(this.upgradeTimeout);
|
|
113
|
+
this.lock
|
|
114
|
+
.override('Transport error', async (signal) => {
|
|
115
|
+
delete this.activeTransport;
|
|
116
|
+
await this.stopTransport(transport);
|
|
117
|
+
if (this.transportReconnect) {
|
|
118
|
+
await (0, utils_1.resolveAfter)(1000, signal);
|
|
119
|
+
await this.createInitPromise(pendingTransportEvent, signal);
|
|
120
|
+
}
|
|
121
|
+
})
|
|
122
|
+
.catch(() => { });
|
|
123
|
+
});
|
|
124
|
+
this.activeTransport = transport;
|
|
125
|
+
this.emit(transport_1.TRANSPORT.START, transport);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
this.emit(transport_1.TRANSPORT.ERROR, 'Transport disabled');
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (transport && transport !== transports[0]) {
|
|
132
|
+
this.scheduleUpgradeCheck(pendingTransportEvent);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
this.emit(transport_1.TRANSPORT.ERROR, error?.message);
|
|
137
|
+
if (this.transportReconnect && !abortSignal.aborted) {
|
|
138
|
+
this.lock
|
|
139
|
+
.override('Reconnecting', async (signal) => {
|
|
140
|
+
await (0, utils_1.resolveAfter)(1000, signal);
|
|
141
|
+
await this.createInitPromise(pendingTransportEvent, signal);
|
|
142
|
+
})
|
|
143
|
+
.catch(() => { });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
exports.TransportManager = TransportManager;
|
|
149
|
+
//# sourceMappingURL=TransportManager.js.map
|
|
@@ -4,12 +4,14 @@ exports.checkFirmwareRevision = void 0;
|
|
|
4
4
|
const versionUtils_1 = require("@trezor/utils/lib/versionUtils");
|
|
5
5
|
const downloadReleasesMetadata_1 = require("../data/downloadReleasesMetadata");
|
|
6
6
|
const calculateRevisionForDevice_1 = require("./calculateRevisionForDevice");
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
7
|
+
const assets_browser_1 = require("../utils/assets-browser");
|
|
8
|
+
const isNotFoundError = (e) => e instanceof assets_browser_1.HttpRequestError && e.response.status === 404;
|
|
9
|
+
const isNodeJSOfflineError = (e) => ['FetchError', 'AbortError'].includes(e.name);
|
|
10
|
+
const isReactNativeOfflineError = (e) => e.name === 'TypeError' && e.message.includes('Network request failed');
|
|
11
|
+
const isOfflineError = (e) => {
|
|
10
12
|
if (!(e instanceof Error))
|
|
11
13
|
return false;
|
|
12
|
-
return
|
|
14
|
+
return isNodeJSOfflineError(e) || isReactNativeOfflineError(e);
|
|
13
15
|
};
|
|
14
16
|
const getOnlineReleaseMetadata = async ({ firmwareVersion, internalModel, }) => {
|
|
15
17
|
const onlineReleases = await (0, downloadReleasesMetadata_1.downloadReleasesMetadata)({ internal_model: internalModel });
|
|
@@ -49,7 +51,9 @@ const checkFirmwareRevision = async ({ firmwareVersion, internalModel, deviceRev
|
|
|
49
51
|
return { success: true };
|
|
50
52
|
}
|
|
51
53
|
catch (e) {
|
|
52
|
-
|
|
54
|
+
if (isNotFoundError(e))
|
|
55
|
+
return failFirmwareRevisionCheck('firmware-version-unknown');
|
|
56
|
+
return isOfflineError(e)
|
|
53
57
|
? failFirmwareRevisionCheck('cannot-perform-check-offline')
|
|
54
58
|
: failFirmwareRevisionCheck('other-error');
|
|
55
59
|
}
|
|
@@ -71,8 +71,7 @@ export type SolanaComposedTransaction = Static<typeof SolanaComposedTransaction>
|
|
|
71
71
|
export declare const SolanaComposedTransaction: import("@trezor/schema-utils").TObject<{
|
|
72
72
|
serializedTx: import("@trezor/schema-utils").TString;
|
|
73
73
|
additionalInfo: import("@trezor/schema-utils").TObject<{
|
|
74
|
-
|
|
75
|
-
newTokenAccountProgramName: import("@trezor/schema-utils").TOptional<import("@trezor/schema-utils").TUnion<[import("@trezor/schema-utils").TLiteral<"spl-token">, import("@trezor/schema-utils").TLiteral<"spl-token-2022">]>>;
|
|
74
|
+
newAccountProgramName: import("@trezor/schema-utils").TOptional<import("@trezor/schema-utils").TUnion<[import("@trezor/schema-utils").TLiteral<"spl-token">, import("@trezor/schema-utils").TLiteral<"spl-token-2022">]>>;
|
|
76
75
|
tokenAccountInfo: import("@trezor/schema-utils").TOptional<import("@trezor/schema-utils").TObject<{
|
|
77
76
|
baseAddress: import("@trezor/schema-utils").TString;
|
|
78
77
|
tokenProgram: import("@trezor/schema-utils").TString;
|
|
@@ -51,8 +51,7 @@ exports.SolanaComposeTransaction = schema_utils_1.Type.Object({
|
|
|
51
51
|
exports.SolanaComposedTransaction = schema_utils_1.Type.Object({
|
|
52
52
|
serializedTx: schema_utils_1.Type.String(),
|
|
53
53
|
additionalInfo: schema_utils_1.Type.Object({
|
|
54
|
-
|
|
55
|
-
newTokenAccountProgramName: schema_utils_1.Type.Optional(exports.SolanaProgramName),
|
|
54
|
+
newAccountProgramName: schema_utils_1.Type.Optional(exports.SolanaProgramName),
|
|
56
55
|
tokenAccountInfo: schema_utils_1.Type.Optional(exports.SolanaTxTokenAccountInfo),
|
|
57
56
|
}),
|
|
58
57
|
});
|