@trezor/connect 9.1.1 → 9.1.2
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 +13 -3
- package/README.md +2 -2
- package/lib/api/backupDevice.d.ts +1 -1
- package/lib/api/binanceGetAddress.d.ts +1 -0
- package/lib/api/binanceGetAddress.js +4 -4
- package/lib/api/binanceGetPublicKey.d.ts +1 -0
- package/lib/api/binanceGetPublicKey.js +3 -1
- package/lib/api/binanceSignTransaction.d.ts +2 -1
- package/lib/api/binanceSignTransaction.js +3 -1
- package/lib/api/bitcoin/Fees.d.ts +2 -2
- package/lib/api/bitcoin/Fees.js +32 -90
- package/lib/api/bitcoin/TransactionComposer.d.ts +1 -2
- package/lib/api/bitcoin/TransactionComposer.js +3 -2
- package/lib/api/bitcoin/refTx.d.ts +10 -2
- package/lib/api/bitcoin/refTx.js +46 -19
- package/lib/api/blockchainDisconnect.d.ts +1 -0
- package/lib/api/blockchainDisconnect.js +3 -1
- package/lib/api/blockchainEstimateFee.js +1 -1
- package/lib/api/blockchainSetCustomBackend.d.ts +1 -0
- package/lib/api/blockchainSetCustomBackend.js +3 -1
- package/lib/api/cancelCoinjoinAuthorization.d.ts +1 -0
- package/lib/api/cancelCoinjoinAuthorization.js +3 -1
- package/lib/api/cardanoGetAddress.d.ts +1 -0
- package/lib/api/cardanoGetAddress.js +4 -4
- package/lib/api/cardanoGetNativeScriptHash.d.ts +1 -0
- package/lib/api/cardanoGetNativeScriptHash.js +3 -1
- package/lib/api/cardanoGetPublicKey.d.ts +1 -0
- package/lib/api/cardanoGetPublicKey.js +3 -1
- package/lib/api/cardanoSignTransaction.d.ts +1 -0
- package/lib/api/cardanoSignTransaction.js +3 -1
- package/lib/api/checkFirmwareAuthenticity.js +2 -1
- package/lib/api/cipherKeyValue.d.ts +1 -0
- package/lib/api/cipherKeyValue.js +3 -1
- package/lib/api/composeTransaction.d.ts +3 -0
- package/lib/api/composeTransaction.js +9 -7
- package/lib/api/eosGetPublicKey.d.ts +1 -0
- package/lib/api/eosGetPublicKey.js +3 -1
- package/lib/api/eosSignTransaction.d.ts +1 -0
- package/lib/api/eosSignTransaction.js +3 -1
- package/lib/api/ethereum/ethereumDefinitions.d.ts +28 -6
- package/lib/api/ethereum/ethereumDefinitions.js +60 -1
- package/lib/api/ethereum/ethereumSignTx.d.ts +1 -1
- package/lib/api/ethereumGetAddress.d.ts +2 -0
- package/lib/api/ethereumGetAddress.js +28 -26
- package/lib/api/ethereumGetPublicKey.d.ts +1 -0
- package/lib/api/ethereumGetPublicKey.js +8 -10
- package/lib/api/ethereumSignMessage.d.ts +10 -1
- package/lib/api/ethereumSignMessage.js +14 -13
- package/lib/api/ethereumSignTransaction.d.ts +6 -0
- package/lib/api/ethereumSignTransaction.js +18 -5
- package/lib/api/ethereumSignTypedData.d.ts +6 -0
- package/lib/api/ethereumSignTypedData.js +15 -13
- package/lib/api/ethereumVerifyMessage.d.ts +1 -0
- package/lib/api/ethereumVerifyMessage.js +3 -1
- package/lib/api/getAccountInfo.d.ts +1 -0
- package/lib/api/getAccountInfo.js +3 -1
- package/lib/api/getAddress.d.ts +1 -0
- package/lib/api/getAddress.js +8 -10
- package/lib/api/getFeatures.d.ts +1 -1
- package/lib/api/getOwnershipId.d.ts +1 -0
- package/lib/api/getOwnershipId.js +3 -1
- package/lib/api/getOwnershipProof.d.ts +1 -0
- package/lib/api/getOwnershipProof.js +3 -1
- package/lib/api/getPublicKey.d.ts +1 -0
- package/lib/api/getPublicKey.js +3 -1
- package/lib/api/nemGetAddress.d.ts +1 -0
- package/lib/api/nemGetAddress.js +4 -4
- package/lib/api/nemSignTransaction.d.ts +1 -0
- package/lib/api/nemSignTransaction.js +3 -1
- package/lib/api/rebootToBootloader.d.ts +2 -1
- package/lib/api/rebootToBootloader.js +3 -1
- package/lib/api/requestLogin.d.ts +1 -0
- package/lib/api/requestLogin.js +3 -1
- package/lib/api/resetDevice.d.ts +1 -0
- package/lib/api/resetDevice.js +3 -1
- package/lib/api/rippleGetAddress.d.ts +1 -0
- package/lib/api/rippleGetAddress.js +4 -4
- package/lib/api/rippleSignTransaction.d.ts +1 -0
- package/lib/api/rippleSignTransaction.js +3 -1
- package/lib/api/showDeviceTutorial.d.ts +1 -0
- package/lib/api/showDeviceTutorial.js +3 -1
- package/lib/api/signMessage.d.ts +1 -0
- package/lib/api/signMessage.js +5 -1
- package/lib/api/signTransaction.d.ts +1 -0
- package/lib/api/signTransaction.js +16 -4
- package/lib/api/stellarGetAddress.d.ts +1 -0
- package/lib/api/stellarGetAddress.js +4 -4
- package/lib/api/stellarSignTransaction.d.ts +1 -0
- package/lib/api/stellarSignTransaction.js +3 -1
- package/lib/api/tezosGetAddress.d.ts +1 -0
- package/lib/api/tezosGetAddress.js +4 -4
- package/lib/api/tezosGetPublicKey.d.ts +1 -0
- package/lib/api/tezosGetPublicKey.js +3 -1
- package/lib/api/tezosSignTransaction.d.ts +1 -0
- package/lib/api/tezosSignTransaction.js +3 -1
- package/lib/api/verifyMessage.d.ts +1 -0
- package/lib/api/verifyMessage.js +7 -2
- package/lib/api/wipeDevice.d.ts +2 -1
- package/lib/api/wipeDevice.js +3 -1
- package/lib/backend/Blockchain.d.ts +1 -3
- package/lib/backend/Blockchain.js +10 -6
- package/lib/constants/index.d.ts +1 -1
- package/lib/constants/index.js +1 -1
- package/lib/core/AbstractMethod.d.ts +3 -1
- package/lib/core/AbstractMethod.js +3 -1
- package/lib/core/index.js +9 -1
- package/lib/data/DataManager.js +4 -1
- package/lib/data/analyticsInfo.js +1 -1
- package/lib/data/coinInfo.d.ts +9 -0
- package/lib/data/coinInfo.js +10 -41
- package/lib/data/config.js +5 -1
- package/lib/data/defaultFeeLevels.d.ts +17 -0
- package/lib/data/defaultFeeLevels.js +84 -0
- package/lib/data/version.d.ts +1 -1
- package/lib/data/version.js +1 -1
- package/lib/device/Device.d.ts +2 -2
- package/lib/device/Device.js +9 -7
- package/lib/device/DeviceCommands.js +6 -1
- package/lib/events/popup.d.ts +8 -1
- package/lib/events/popup.js +1 -0
- package/lib/events/ui-request.d.ts +2 -2
- package/lib/types/account.d.ts +1 -20
- package/lib/types/api/bitcoin/index.d.ts +2 -0
- package/lib/types/api/blockchainEstimateFee.d.ts +2 -5
- package/lib/types/coinInfo.d.ts +5 -17
- package/lib/types/device.d.ts +5 -2
- package/lib/types/device.js +7 -2
- package/lib/types/fees.d.ts +26 -0
- package/lib/types/fees.js +3 -0
- package/lib/types/index.d.ts +2 -1
- package/lib/types/index.js +1 -0
- package/lib/utils/assetUtils.js +3 -1
- package/lib/utils/urlUtils.d.ts +10 -3
- package/lib/utils/urlUtils.js +5 -9
- package/package.json +10 -8
|
@@ -41,12 +41,12 @@ class TezosGetAddress extends AbstractMethod_1.AbstractMethod {
|
|
|
41
41
|
this.params[0].show_display;
|
|
42
42
|
this.confirmed = useEventListener;
|
|
43
43
|
this.useUi = !useEventListener;
|
|
44
|
+
}
|
|
45
|
+
get info() {
|
|
44
46
|
if (this.params.length === 1) {
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
this.info = 'Export multiple Tezos addresses';
|
|
47
|
+
return `Export Tezos address for account #${(0, pathUtils_1.fromHardened)(this.params[0].address_n[2]) + 1}`;
|
|
49
48
|
}
|
|
49
|
+
return 'Export multiple Tezos addresses';
|
|
50
50
|
}
|
|
51
51
|
getButtonRequestData(code) {
|
|
52
52
|
if (code === 'ButtonRequest_Address') {
|
|
@@ -4,6 +4,7 @@ export default class TezosGetPublicKey extends AbstractMethod<'tezosGetPublicKey
|
|
|
4
4
|
hasBundle?: boolean;
|
|
5
5
|
confirmed?: boolean;
|
|
6
6
|
init(): void;
|
|
7
|
+
get info(): string;
|
|
7
8
|
confirmation(): Promise<boolean>;
|
|
8
9
|
run(): Promise<import("..").PublicKey | import("..").PublicKey[]>;
|
|
9
10
|
}
|
|
@@ -9,7 +9,6 @@ class TezosGetPublicKey extends AbstractMethod_1.AbstractMethod {
|
|
|
9
9
|
init() {
|
|
10
10
|
this.requiredPermissions = ['read'];
|
|
11
11
|
this.firmwareRange = (0, paramsValidator_1.getFirmwareRange)(this.name, (0, coinInfo_1.getMiscNetwork)('Tezos'), this.firmwareRange);
|
|
12
|
-
this.info = 'Export Tezos public key';
|
|
13
12
|
this.hasBundle = !!this.payload.bundle;
|
|
14
13
|
const payload = !this.payload.bundle
|
|
15
14
|
? { ...this.payload, bundle: [this.payload] }
|
|
@@ -27,6 +26,9 @@ class TezosGetPublicKey extends AbstractMethod_1.AbstractMethod {
|
|
|
27
26
|
};
|
|
28
27
|
});
|
|
29
28
|
}
|
|
29
|
+
get info() {
|
|
30
|
+
return 'Export Tezos public key';
|
|
31
|
+
}
|
|
30
32
|
async confirmation() {
|
|
31
33
|
if (this.confirmed)
|
|
32
34
|
return true;
|
|
@@ -2,6 +2,7 @@ import { AbstractMethod } from '../core/AbstractMethod';
|
|
|
2
2
|
import type { PROTO } from '../constants';
|
|
3
3
|
export default class TezosSignTransaction extends AbstractMethod<'tezosSignTransaction', PROTO.TezosSignTx> {
|
|
4
4
|
init(): void;
|
|
5
|
+
get info(): string;
|
|
5
6
|
run(): Promise<PROTO.TezosSignedTx>;
|
|
6
7
|
}
|
|
7
8
|
//# sourceMappingURL=tezosSignTransaction.d.ts.map
|
|
@@ -10,7 +10,6 @@ class TezosSignTransaction extends AbstractMethod_1.AbstractMethod {
|
|
|
10
10
|
init() {
|
|
11
11
|
this.requiredPermissions = ['read', 'write'];
|
|
12
12
|
this.firmwareRange = (0, paramsValidator_1.getFirmwareRange)(this.name, (0, coinInfo_1.getMiscNetwork)('Tezos'), this.firmwareRange);
|
|
13
|
-
this.info = 'Sign Tezos transaction';
|
|
14
13
|
const { payload } = this;
|
|
15
14
|
(0, paramsValidator_1.validateParams)(payload, [
|
|
16
15
|
{ name: 'path', required: true },
|
|
@@ -20,6 +19,9 @@ class TezosSignTransaction extends AbstractMethod_1.AbstractMethod {
|
|
|
20
19
|
const path = (0, pathUtils_1.validatePath)(payload.path, 3);
|
|
21
20
|
this.params = helper.createTx(path, payload.branch, payload.operation);
|
|
22
21
|
}
|
|
22
|
+
get info() {
|
|
23
|
+
return 'Sign Tezos transaction';
|
|
24
|
+
}
|
|
23
25
|
async run() {
|
|
24
26
|
const cmd = this.device.getCommands();
|
|
25
27
|
const response = await cmd.typedCall('TezosSignTx', 'TezosSignedTx', this.params);
|
|
@@ -2,6 +2,7 @@ import { AbstractMethod } from '../core/AbstractMethod';
|
|
|
2
2
|
import { PROTO } from '../constants';
|
|
3
3
|
export default class VerifyMessage extends AbstractMethod<'verifyMessage', PROTO.VerifyMessage> {
|
|
4
4
|
init(): void;
|
|
5
|
+
get info(): string;
|
|
5
6
|
run(): Promise<PROTO.Success>;
|
|
6
7
|
}
|
|
7
8
|
//# sourceMappingURL=verifyMessage.d.ts.map
|
package/lib/api/verifyMessage.js
CHANGED
|
@@ -9,7 +9,6 @@ const constants_1 = require("../constants");
|
|
|
9
9
|
class VerifyMessage extends AbstractMethod_1.AbstractMethod {
|
|
10
10
|
init() {
|
|
11
11
|
this.requiredPermissions = ['read', 'write'];
|
|
12
|
-
this.info = 'Verify message';
|
|
13
12
|
const { payload } = this;
|
|
14
13
|
(0, paramsValidator_1.validateParams)(payload, [
|
|
15
14
|
{ name: 'address', type: 'string', required: true },
|
|
@@ -24,7 +23,6 @@ class VerifyMessage extends AbstractMethod_1.AbstractMethod {
|
|
|
24
23
|
}
|
|
25
24
|
else {
|
|
26
25
|
this.firmwareRange = (0, paramsValidator_1.getFirmwareRange)(this.name, coinInfo, this.firmwareRange);
|
|
27
|
-
this.info = (0, pathUtils_1.getLabel)('Verify #NETWORK message', coinInfo);
|
|
28
26
|
}
|
|
29
27
|
const messageHex = payload.hex
|
|
30
28
|
? (0, formatUtils_1.messageToHex)(payload.message)
|
|
@@ -37,6 +35,13 @@ class VerifyMessage extends AbstractMethod_1.AbstractMethod {
|
|
|
37
35
|
coin_name: coinInfo.name,
|
|
38
36
|
};
|
|
39
37
|
}
|
|
38
|
+
get info() {
|
|
39
|
+
const coinInfo = (0, coinInfo_1.getBitcoinNetwork)(this.payload.coin);
|
|
40
|
+
if (!coinInfo) {
|
|
41
|
+
return 'Verify message';
|
|
42
|
+
}
|
|
43
|
+
return (0, pathUtils_1.getLabel)('Verify #NETWORK message', coinInfo);
|
|
44
|
+
}
|
|
40
45
|
async run() {
|
|
41
46
|
const cmd = this.device.getCommands();
|
|
42
47
|
const response = await cmd.typedCall('VerifyMessage', 'Success', this.params);
|
package/lib/api/wipeDevice.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export default class WipeDevice extends AbstractMethod<'wipeDevice'> {
|
|
|
3
3
|
confirmed?: boolean;
|
|
4
4
|
init(): void;
|
|
5
5
|
confirmation(): Promise<boolean>;
|
|
6
|
-
|
|
6
|
+
get info(): string;
|
|
7
|
+
run(): Promise<import("packages/protobuf/lib/messages").Success>;
|
|
7
8
|
}
|
|
8
9
|
//# sourceMappingURL=wipeDevice.d.ts.map
|
package/lib/api/wipeDevice.js
CHANGED
|
@@ -9,7 +9,6 @@ class WipeDevice extends AbstractMethod_1.AbstractMethod {
|
|
|
9
9
|
this.useDeviceState = false;
|
|
10
10
|
this.requiredPermissions = ['management'];
|
|
11
11
|
this.firmwareRange = (0, paramsValidator_1.getFirmwareRange)(this.name, null, this.firmwareRange);
|
|
12
|
-
this.info = 'Wipe device';
|
|
13
12
|
}
|
|
14
13
|
async confirmation() {
|
|
15
14
|
if (this.confirmed)
|
|
@@ -28,6 +27,9 @@ class WipeDevice extends AbstractMethod_1.AbstractMethod {
|
|
|
28
27
|
this.confirmed = uiResp.payload;
|
|
29
28
|
return this.confirmed;
|
|
30
29
|
}
|
|
30
|
+
get info() {
|
|
31
|
+
return 'Wipe device';
|
|
32
|
+
}
|
|
31
33
|
async run() {
|
|
32
34
|
const cmd = this.device.getCommands();
|
|
33
35
|
if (this.device.isBootloader()) {
|
|
@@ -44,9 +44,7 @@ export declare class Blockchain {
|
|
|
44
44
|
getNetworkInfo(): Promise<ServerInfo>;
|
|
45
45
|
getAccountInfo(request: BlockchainLinkParams<'getAccountInfo'>): Promise<import("@trezor/blockchain-link").AccountInfo>;
|
|
46
46
|
getAccountUtxo(descriptor: string): Promise<import("@trezor/blockchain-link").Utxo[]>;
|
|
47
|
-
estimateFee(request: {
|
|
48
|
-
blocks?: number[];
|
|
49
|
-
}): Promise<{
|
|
47
|
+
estimateFee(request: Parameters<typeof this.link.estimateFee>[0]): Promise<{
|
|
50
48
|
feePerUnit: string;
|
|
51
49
|
feePerTx?: string | undefined;
|
|
52
50
|
feeLimit?: string | undefined;
|
|
@@ -108,17 +108,21 @@ class Blockchain {
|
|
|
108
108
|
}
|
|
109
109
|
async estimateFee(request) {
|
|
110
110
|
const { blocks } = request;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const outdated = now - this.feeTimestamp > 20 * 60 * 1000;
|
|
114
|
-
const unknownBlocks =
|
|
115
|
-
|
|
111
|
+
const useCache = !request.specific && Array.isArray(blocks) && blocks.length > 0;
|
|
112
|
+
if (useCache) {
|
|
113
|
+
const outdated = Date.now() - this.feeTimestamp > 20 * 60 * 1000;
|
|
114
|
+
const unknownBlocks = outdated
|
|
115
|
+
? blocks
|
|
116
|
+
: blocks.filter(block => !this.feeForBlock[block]);
|
|
117
|
+
if (unknownBlocks.length < 1) {
|
|
118
|
+
return blocks.map(block => this.feeForBlock[block]);
|
|
116
119
|
}
|
|
120
|
+
this.feeForBlock = [];
|
|
117
121
|
const fees = await this.link.estimateFee(request);
|
|
118
122
|
blocks.forEach((block, index) => {
|
|
119
123
|
this.feeForBlock[block] = fees[index];
|
|
120
124
|
});
|
|
121
|
-
this.feeTimestamp = now;
|
|
125
|
+
this.feeTimestamp = Date.now();
|
|
122
126
|
return fees;
|
|
123
127
|
}
|
|
124
128
|
return this.link.estimateFee(request);
|
package/lib/constants/index.d.ts
CHANGED
|
@@ -2,5 +2,5 @@ export * as ERRORS from './errors';
|
|
|
2
2
|
export * as NETWORK from './network';
|
|
3
3
|
export * as CARDANO from './cardano';
|
|
4
4
|
export * as NEM from './nem';
|
|
5
|
-
export * as PROTO from '@trezor/
|
|
5
|
+
export * as PROTO from '@trezor/protobuf/lib/messages';
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/constants/index.js
CHANGED
|
@@ -6,5 +6,5 @@ exports.ERRORS = tslib_1.__importStar(require("./errors"));
|
|
|
6
6
|
exports.NETWORK = tslib_1.__importStar(require("./network"));
|
|
7
7
|
exports.CARDANO = tslib_1.__importStar(require("./cardano"));
|
|
8
8
|
exports.NEM = tslib_1.__importStar(require("./nem"));
|
|
9
|
-
exports.PROTO = tslib_1.__importStar(require("@trezor/
|
|
9
|
+
exports.PROTO = tslib_1.__importStar(require("@trezor/protobuf/lib/messages"));
|
|
10
10
|
//# sourceMappingURL=index.js.map
|
|
@@ -23,7 +23,7 @@ export declare abstract class AbstractMethod<Name extends CallMethodPayload['met
|
|
|
23
23
|
overridden: boolean;
|
|
24
24
|
name: Name;
|
|
25
25
|
payload: Payload<Name>;
|
|
26
|
-
info: string;
|
|
26
|
+
get info(): string;
|
|
27
27
|
useUi: boolean;
|
|
28
28
|
useDevice: boolean;
|
|
29
29
|
useDeviceState: boolean;
|
|
@@ -43,6 +43,8 @@ export declare abstract class AbstractMethod<Name extends CallMethodPayload['met
|
|
|
43
43
|
getPopupPromise: () => Deferred<void>;
|
|
44
44
|
createUiPromise: <T extends UiPromiseResponse['type']>(promiseId: T, device?: Device) => UiPromise<T>;
|
|
45
45
|
removeUiPromise: (promise: Deferred<any>) => void;
|
|
46
|
+
initAsync?(): Promise<void>;
|
|
47
|
+
initAsyncPromise?: Promise<void>;
|
|
46
48
|
constructor(message: {
|
|
47
49
|
id?: number;
|
|
48
50
|
payload: Payload<Name>;
|
|
@@ -8,9 +8,11 @@ const events_1 = require("../events");
|
|
|
8
8
|
const versionUtils_1 = require("../utils/versionUtils");
|
|
9
9
|
const urlUtils_1 = require("../utils/urlUtils");
|
|
10
10
|
class AbstractMethod {
|
|
11
|
+
get info() {
|
|
12
|
+
return '';
|
|
13
|
+
}
|
|
11
14
|
constructor(message) {
|
|
12
15
|
var _a, _b;
|
|
13
|
-
this.info = '';
|
|
14
16
|
const { payload } = message;
|
|
15
17
|
this.name = payload.method;
|
|
16
18
|
this.payload = payload;
|
package/lib/core/index.js
CHANGED
|
@@ -166,13 +166,17 @@ const onCall = async (message) => {
|
|
|
166
166
|
method.getPopupPromise = getPopupPromise;
|
|
167
167
|
method.createUiPromise = createUiPromise;
|
|
168
168
|
method.init();
|
|
169
|
+
_callMethods.push(method);
|
|
170
|
+
if (method.initAsync) {
|
|
171
|
+
method.initAsyncPromise = method.initAsync();
|
|
172
|
+
await method.initAsyncPromise;
|
|
173
|
+
}
|
|
169
174
|
}
|
|
170
175
|
catch (error) {
|
|
171
176
|
postMessage((0, events_2.createPopupMessage)(events_2.POPUP.CANCEL_POPUP_REQUEST));
|
|
172
177
|
postMessage((0, events_2.createResponseMessage)(responseID, false, { error }));
|
|
173
178
|
return Promise.resolve();
|
|
174
179
|
}
|
|
175
|
-
_callMethods.push(method);
|
|
176
180
|
if (!method.useDevice) {
|
|
177
181
|
try {
|
|
178
182
|
if (method.useUi) {
|
|
@@ -307,6 +311,7 @@ const onCall = async (message) => {
|
|
|
307
311
|
return Promise.reject(constants_1.ERRORS.TypedError('Method_Cancel'));
|
|
308
312
|
}
|
|
309
313
|
}
|
|
314
|
+
const isDeviceUnlocked = device.features.unlocked;
|
|
310
315
|
try {
|
|
311
316
|
const invalidDeviceState = method.useDeviceState
|
|
312
317
|
? await device.validateState(method.network, method.preauthorized)
|
|
@@ -339,6 +344,9 @@ const onCall = async (message) => {
|
|
|
339
344
|
device.setInternalState(undefined);
|
|
340
345
|
return Promise.reject(error);
|
|
341
346
|
}
|
|
347
|
+
if (!isDeviceUnlocked && device.features.unlocked) {
|
|
348
|
+
postMessage((0, events_2.createDeviceMessage)(events_2.DEVICE.CHANGED, device.toMessageObject()));
|
|
349
|
+
}
|
|
342
350
|
if (method.useUi) {
|
|
343
351
|
await getPopupPromise().promise;
|
|
344
352
|
}
|
package/lib/data/DataManager.js
CHANGED
|
@@ -19,7 +19,10 @@ class DataManager {
|
|
|
19
19
|
await Promise.all(assetPromises);
|
|
20
20
|
this.messages = await (0, assets_1.httpRequest)(`${config_1.config.messages}${ts}`, 'json');
|
|
21
21
|
(0, transportInfo_1.parseBridgeJSON)(this.assets.bridge);
|
|
22
|
-
(0, coinInfo_1.parseCoinsJson)(
|
|
22
|
+
(0, coinInfo_1.parseCoinsJson)({
|
|
23
|
+
...this.assets.coins,
|
|
24
|
+
eth: this.assets.coinsEth,
|
|
25
|
+
});
|
|
23
26
|
(0, firmwareInfo_1.parseFirmware)(this.assets['firmware-t1'], 1);
|
|
24
27
|
(0, firmwareInfo_1.parseFirmware)(this.assets['firmware-t2'], 2);
|
|
25
28
|
}
|
|
@@ -19,7 +19,7 @@ const enhancePostMessageWithAnalytics = (callback, message, data) => {
|
|
|
19
19
|
passphraseProtection: ((_b = device === null || device === void 0 ? void 0 : device.features) === null || _b === void 0 ? void 0 : _b.passphrase_protection) || '',
|
|
20
20
|
backupType: ((_c = device === null || device === void 0 ? void 0 : device.features) === null || _c === void 0 ? void 0 : _c.backup_type) || 'Bip39',
|
|
21
21
|
language: ((_d = device === null || device === void 0 ? void 0 : device.features) === null || _d === void 0 ? void 0 : _d.language) || '',
|
|
22
|
-
model: ((_e = device === null || device === void 0 ? void 0 : device.features) === null || _e === void 0 ? void 0 : _e.
|
|
22
|
+
model: ((_e = device === null || device === void 0 ? void 0 : device.features) === null || _e === void 0 ? void 0 : _e.internal_model) || '',
|
|
23
23
|
vendor: ((_f = device === null || device === void 0 ? void 0 : device.features) === null || _f === void 0 ? void 0 : _f.vendor) || '',
|
|
24
24
|
firmwareRevision: ((_g = device === null || device === void 0 ? void 0 : device.features) === null || _g === void 0 ? void 0 : _g.revision) || '',
|
|
25
25
|
firmwareType: (device === null || device === void 0 ? void 0 : device.firmwareType) || '',
|
package/lib/data/coinInfo.d.ts
CHANGED
|
@@ -30,6 +30,15 @@ export declare const fixCoinInfoNetwork: (ci: BitcoinNetworkInfo, path: number[]
|
|
|
30
30
|
export declare const getCoinInfoByHash: (hash: string, networkInfo: any) => BitcoinNetworkInfo;
|
|
31
31
|
export declare const getCoinInfo: (currency: string) => BitcoinNetworkInfo | EthereumNetworkInfo | MiscNetworkInfo | undefined;
|
|
32
32
|
export declare const getCoinName: (path: number[]) => string;
|
|
33
|
+
export declare const ethereumNetworkInfoBase: {
|
|
34
|
+
blockTime: number;
|
|
35
|
+
minFee: number;
|
|
36
|
+
maxFee: number;
|
|
37
|
+
dustLimit: number;
|
|
38
|
+
defaultFees: import("..").FeeLevel[];
|
|
39
|
+
type: "ethereum";
|
|
40
|
+
decimals: number;
|
|
41
|
+
};
|
|
33
42
|
export declare const parseCoinsJson: (json: any) => void;
|
|
34
43
|
export declare const getUniqueNetworks: (networks: (CoinInfo | undefined)[]) => CoinInfo[];
|
|
35
44
|
export declare const getAllNetworks: () => (BitcoinNetworkInfo | EthereumNetworkInfo | MiscNetworkInfo)[];
|
package/lib/data/coinInfo.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getAllNetworks = exports.getUniqueNetworks = exports.parseCoinsJson = exports.getCoinName = exports.getCoinInfo = exports.getCoinInfoByHash = exports.fixCoinInfoNetwork = exports.getBech32Network = exports.getSegwitNetwork = exports.getMiscNetwork = exports.getEthereumNetwork = exports.getBitcoinNetwork = void 0;
|
|
3
|
+
exports.getAllNetworks = exports.getUniqueNetworks = exports.parseCoinsJson = exports.ethereumNetworkInfoBase = exports.getCoinName = exports.getCoinInfo = exports.getCoinInfoByHash = exports.fixCoinInfoNetwork = exports.getBech32Network = exports.getSegwitNetwork = exports.getMiscNetwork = exports.getEthereumNetwork = exports.getBitcoinNetwork = void 0;
|
|
4
|
+
const defaultFeeLevels_1 = require("./defaultFeeLevels");
|
|
4
5
|
const constants_1 = require("../constants");
|
|
5
6
|
const pathUtils_1 = require("../utils/pathUtils");
|
|
6
7
|
const utils_1 = require("@trezor/utils");
|
|
@@ -151,14 +152,11 @@ const parseBitcoinNetworksJson = (json) => {
|
|
|
151
152
|
bitcoinNetworks.push({
|
|
152
153
|
type: 'bitcoin',
|
|
153
154
|
blockchainLink: coin.blockchain_link,
|
|
154
|
-
blocktime: Math.round(coin.blocktime_seconds / 60),
|
|
155
155
|
cashAddrPrefix: coin.cashaddr_prefix,
|
|
156
156
|
label: coin.coin_label,
|
|
157
157
|
name: coin.coin_name,
|
|
158
158
|
shortcut,
|
|
159
159
|
curveName: coin.curve_name,
|
|
160
|
-
defaultFees: coin.default_fee_b,
|
|
161
|
-
dustLimit: coin.dust_limit,
|
|
162
160
|
forceBip143: coin.force_bip143,
|
|
163
161
|
hashGenesisBlock: coin.hash_genesis_block,
|
|
164
162
|
maxAddressLength: coin.max_address_length,
|
|
@@ -174,74 +172,45 @@ const parseBitcoinNetworksJson = (json) => {
|
|
|
174
172
|
taproot: coin.taproot,
|
|
175
173
|
network,
|
|
176
174
|
isBitcoin,
|
|
177
|
-
maxFee: Math.round(coin.maxfee_kb / 1000),
|
|
178
|
-
minFee: Math.round(coin.minfee_kb / 1000),
|
|
179
|
-
blocks: Math.round(coin.blocktime_seconds / 60),
|
|
180
175
|
decimals: coin.decimals,
|
|
176
|
+
...(0, defaultFeeLevels_1.getBitcoinFeeLevels)(coin),
|
|
181
177
|
});
|
|
182
178
|
});
|
|
183
179
|
};
|
|
180
|
+
exports.ethereumNetworkInfoBase = {
|
|
181
|
+
type: 'ethereum',
|
|
182
|
+
decimals: 16,
|
|
183
|
+
...(0, defaultFeeLevels_1.getEthereumFeeLevels)(),
|
|
184
|
+
};
|
|
184
185
|
const parseEthereumNetworksJson = (json) => {
|
|
185
186
|
Object.keys(json).forEach(key => {
|
|
186
187
|
const network = json[key];
|
|
187
188
|
ethereumNetworks.push({
|
|
188
|
-
|
|
189
|
+
...exports.ethereumNetworkInfoBase,
|
|
189
190
|
blockchainLink: network.blockchain_link,
|
|
190
|
-
blocktime: -1,
|
|
191
|
-
chain: network.chain,
|
|
192
191
|
chainId: network.chain_id,
|
|
193
|
-
defaultFees: [
|
|
194
|
-
{
|
|
195
|
-
label: 'normal',
|
|
196
|
-
feePerUnit: '5000000000',
|
|
197
|
-
feeLimit: '21000',
|
|
198
|
-
},
|
|
199
|
-
],
|
|
200
|
-
minFee: 1,
|
|
201
|
-
maxFee: 10000,
|
|
202
192
|
label: network.name,
|
|
203
193
|
name: network.name,
|
|
204
194
|
shortcut: network.shortcut,
|
|
205
|
-
rskip60: network.rskip60,
|
|
206
195
|
slip44: network.slip44,
|
|
207
196
|
support: network.support,
|
|
208
|
-
network: undefined,
|
|
209
|
-
decimals: 16,
|
|
210
197
|
});
|
|
211
198
|
});
|
|
212
199
|
};
|
|
213
200
|
const parseMiscNetworksJSON = (json, type) => {
|
|
214
201
|
Object.keys(json).forEach(key => {
|
|
215
202
|
const network = json[key];
|
|
216
|
-
let minFee = -1;
|
|
217
|
-
let maxFee = -1;
|
|
218
|
-
let defaultFees = { Normal: -1 };
|
|
219
|
-
const shortcut = network.shortcut.toLowerCase();
|
|
220
|
-
if (shortcut === 'xrp' || shortcut === 'txrp') {
|
|
221
|
-
minFee = 10;
|
|
222
|
-
maxFee = 10000;
|
|
223
|
-
defaultFees = { Normal: 12 };
|
|
224
|
-
}
|
|
225
|
-
if (shortcut === 'ada' || shortcut === 'tada') {
|
|
226
|
-
minFee = 44;
|
|
227
|
-
maxFee = 16384 * 44 + 155381;
|
|
228
|
-
defaultFees = { Normal: 44 };
|
|
229
|
-
}
|
|
230
203
|
miscNetworks.push({
|
|
231
204
|
type: type || 'misc',
|
|
232
205
|
blockchainLink: network.blockchain_link,
|
|
233
|
-
blocktime: -1,
|
|
234
206
|
curve: network.curve,
|
|
235
|
-
defaultFees,
|
|
236
|
-
minFee,
|
|
237
|
-
maxFee,
|
|
238
207
|
label: network.name,
|
|
239
208
|
name: network.name,
|
|
240
209
|
shortcut: network.shortcut,
|
|
241
210
|
slip44: network.slip44,
|
|
242
211
|
support: network.support,
|
|
243
|
-
network: undefined,
|
|
244
212
|
decimals: network.decimals,
|
|
213
|
+
...(0, defaultFeeLevels_1.getMiscFeeLevels)(network),
|
|
245
214
|
});
|
|
246
215
|
});
|
|
247
216
|
};
|
package/lib/data/config.js
CHANGED
|
@@ -47,6 +47,10 @@ exports.config = {
|
|
|
47
47
|
name: 'coins',
|
|
48
48
|
url: './data/coins.json',
|
|
49
49
|
},
|
|
50
|
+
{
|
|
51
|
+
name: 'coinsEth',
|
|
52
|
+
url: './data/coins-eth.json',
|
|
53
|
+
},
|
|
50
54
|
{
|
|
51
55
|
name: 'bridge',
|
|
52
56
|
url: './data/bridge/releases.json',
|
|
@@ -101,7 +105,7 @@ exports.config = {
|
|
|
101
105
|
],
|
|
102
106
|
},
|
|
103
107
|
{
|
|
104
|
-
coin: ['eth', 'tgor'],
|
|
108
|
+
coin: ['eth', 'tsep', 'tgor'],
|
|
105
109
|
min: ['1.8.0', '2.1.0'],
|
|
106
110
|
comment: ['There were protobuf backwards incompatible changes.'],
|
|
107
111
|
},
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { FeeLevel, FeeInfo } from '../types';
|
|
2
|
+
interface CoinsJsonData {
|
|
3
|
+
shortcut: string;
|
|
4
|
+
blocktime_seconds: number;
|
|
5
|
+
default_fee_b: Record<'High' | 'Normal' | 'Economy' | 'Low', number>;
|
|
6
|
+
maxfee_kb: number;
|
|
7
|
+
minfee_kb: number;
|
|
8
|
+
dust_limit: number;
|
|
9
|
+
}
|
|
10
|
+
export type FeeInfoWithLevels = FeeInfo & {
|
|
11
|
+
defaultFees: FeeLevel[];
|
|
12
|
+
};
|
|
13
|
+
export declare const getBitcoinFeeLevels: (coin: CoinsJsonData) => FeeInfoWithLevels;
|
|
14
|
+
export declare const getEthereumFeeLevels: () => FeeInfoWithLevels;
|
|
15
|
+
export declare const getMiscFeeLevels: (data: CoinsJsonData) => FeeInfoWithLevels;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=defaultFeeLevels.d.ts.map
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getMiscFeeLevels = exports.getEthereumFeeLevels = exports.getBitcoinFeeLevels = void 0;
|
|
4
|
+
const BLOCKS_FOR_FEE_LEVEL = {
|
|
5
|
+
btc: {
|
|
6
|
+
high: 1,
|
|
7
|
+
normal: 6,
|
|
8
|
+
economy: 36,
|
|
9
|
+
low: 144,
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
const getDefaultBlocksForFeeLevel = (shortcut, label) => BLOCKS_FOR_FEE_LEVEL[shortcut] && BLOCKS_FOR_FEE_LEVEL[shortcut][label]
|
|
13
|
+
? BLOCKS_FOR_FEE_LEVEL[shortcut][label]
|
|
14
|
+
: -1;
|
|
15
|
+
const getBitcoinFeeLevels = (coin) => {
|
|
16
|
+
const defaultFees = coin.default_fee_b;
|
|
17
|
+
const shortcut = coin.shortcut.toLowerCase();
|
|
18
|
+
const keys = Object.keys(defaultFees);
|
|
19
|
+
const levels = keys
|
|
20
|
+
.sort((levelA, levelB) => defaultFees[levelB] - defaultFees[levelA])
|
|
21
|
+
.map(level => {
|
|
22
|
+
const label = level.toLowerCase();
|
|
23
|
+
return {
|
|
24
|
+
label,
|
|
25
|
+
feePerUnit: defaultFees[level].toString(),
|
|
26
|
+
blocks: getDefaultBlocksForFeeLevel(shortcut, label),
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
return {
|
|
30
|
+
blockTime: Math.max(1, Math.round(coin.blocktime_seconds / 60)),
|
|
31
|
+
dustLimit: coin.dust_limit,
|
|
32
|
+
maxFee: Math.round(coin.maxfee_kb / 1000),
|
|
33
|
+
minFee: Math.round(coin.minfee_kb / 1000),
|
|
34
|
+
defaultFees: levels,
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
exports.getBitcoinFeeLevels = getBitcoinFeeLevels;
|
|
38
|
+
const getEthereumFeeLevels = () => ({
|
|
39
|
+
blockTime: -1,
|
|
40
|
+
defaultFees: [
|
|
41
|
+
{
|
|
42
|
+
label: 'normal',
|
|
43
|
+
feePerUnit: '5000000000',
|
|
44
|
+
feeLimit: '21000',
|
|
45
|
+
blocks: -1,
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
minFee: 1,
|
|
49
|
+
maxFee: 10000,
|
|
50
|
+
dustLimit: -1,
|
|
51
|
+
});
|
|
52
|
+
exports.getEthereumFeeLevels = getEthereumFeeLevels;
|
|
53
|
+
const RIPPLE_FEE_INFO = {
|
|
54
|
+
blockTime: -1,
|
|
55
|
+
defaultFees: [{ label: 'normal', feePerUnit: '12', blocks: -1 }],
|
|
56
|
+
minFee: 10,
|
|
57
|
+
maxFee: 10000,
|
|
58
|
+
dustLimit: -1,
|
|
59
|
+
};
|
|
60
|
+
const CARDANO_FEE_INFO = {
|
|
61
|
+
blockTime: -1,
|
|
62
|
+
defaultFees: [{ label: 'normal', feePerUnit: '44', blocks: -1 }],
|
|
63
|
+
minFee: 44,
|
|
64
|
+
maxFee: 16384 * 44 + 155381,
|
|
65
|
+
dustLimit: -1,
|
|
66
|
+
};
|
|
67
|
+
const MISC_FEE_LEVELS = {
|
|
68
|
+
xrp: RIPPLE_FEE_INFO,
|
|
69
|
+
txrp: RIPPLE_FEE_INFO,
|
|
70
|
+
ada: CARDANO_FEE_INFO,
|
|
71
|
+
tada: CARDANO_FEE_INFO,
|
|
72
|
+
};
|
|
73
|
+
const getMiscFeeLevels = (data) => {
|
|
74
|
+
const shortcut = data.shortcut.toLowerCase();
|
|
75
|
+
return (MISC_FEE_LEVELS[shortcut] || {
|
|
76
|
+
blockTime: -1,
|
|
77
|
+
minFee: -1,
|
|
78
|
+
maxFee: -1,
|
|
79
|
+
defaultFees: [{ label: 'normal', feePerUnit: '-1', blocks: -1 }],
|
|
80
|
+
dustLimit: -1,
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
exports.getMiscFeeLevels = getMiscFeeLevels;
|
|
84
|
+
//# sourceMappingURL=defaultFeeLevels.js.map
|
package/lib/data/version.d.ts
CHANGED
package/lib/data/version.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DEFAULT_DOMAIN = exports.VERSION = void 0;
|
|
4
|
-
exports.VERSION = '9.1.
|
|
4
|
+
exports.VERSION = '9.1.2';
|
|
5
5
|
const versionN = exports.VERSION.split('.').map(s => parseInt(s, 10));
|
|
6
6
|
exports.DEFAULT_DOMAIN = `https://connect.trezor.io/${versionN[0]}/`;
|
|
7
7
|
//# sourceMappingURL=version.js.map
|
package/lib/device/Device.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { PROTO, NETWORK } from '../constants';
|
|
|
4
4
|
import { DEVICE, DeviceButtonRequestPayload } from '../events';
|
|
5
5
|
import { Deferred } from '../utils/deferred';
|
|
6
6
|
import type { Transport, Descriptor } from '@trezor/transport';
|
|
7
|
-
import
|
|
7
|
+
import { Device as DeviceTyped, DeviceFirmwareStatus, Features, ReleaseInfo, UnavailableCapabilities, FirmwareType } from '../types';
|
|
8
8
|
export type RunOptions = {
|
|
9
9
|
skipFinalReload?: boolean;
|
|
10
10
|
waiting?: boolean;
|
|
@@ -44,7 +44,7 @@ export declare class Device extends TypedEmitter<DeviceEvents> {
|
|
|
44
44
|
externalState: string[];
|
|
45
45
|
unavailableCapabilities: UnavailableCapabilities;
|
|
46
46
|
networkTypeState: NETWORK.NetworkType[];
|
|
47
|
-
firmwareType
|
|
47
|
+
firmwareType?: FirmwareType;
|
|
48
48
|
constructor(transport: Transport, descriptor: Descriptor);
|
|
49
49
|
static fromDescriptor(transport: Transport, originalDescriptor: Descriptor): Device;
|
|
50
50
|
static createUnacquired(transport: Transport, descriptor: Descriptor, unreadableError?: string): Device;
|
package/lib/device/Device.js
CHANGED
|
@@ -11,6 +11,7 @@ const deviceFeaturesUtils_1 = require("../utils/deviceFeaturesUtils");
|
|
|
11
11
|
const versionUtils_1 = require("../utils/versionUtils");
|
|
12
12
|
const deferred_1 = require("../utils/deferred");
|
|
13
13
|
const debug_1 = require("../utils/debug");
|
|
14
|
+
const types_1 = require("../types");
|
|
14
15
|
const _log = (0, debug_1.initLog)('Device');
|
|
15
16
|
const parseRunOptions = (options) => {
|
|
16
17
|
if (!options)
|
|
@@ -31,7 +32,6 @@ class Device extends typedEventEmitter_1.TypedEmitter {
|
|
|
31
32
|
this.externalState = [];
|
|
32
33
|
this.unavailableCapabilities = {};
|
|
33
34
|
this.networkTypeState = [];
|
|
34
|
-
this.firmwareType = 'regular';
|
|
35
35
|
this.transport = transport;
|
|
36
36
|
this.originalDescriptor = descriptor;
|
|
37
37
|
this.firstRunPromise = (0, deferred_1.create)();
|
|
@@ -324,12 +324,14 @@ class Device extends typedEventEmitter_1.TypedEmitter {
|
|
|
324
324
|
}
|
|
325
325
|
this.features = feat;
|
|
326
326
|
this.featuresNeedsReload = false;
|
|
327
|
-
this.
|
|
328
|
-
|
|
329
|
-
feat.capabilities
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
327
|
+
if (this.getMode() !== 'bootloader') {
|
|
328
|
+
this.firmwareType =
|
|
329
|
+
feat.capabilities &&
|
|
330
|
+
feat.capabilities.length > 0 &&
|
|
331
|
+
!feat.capabilities.includes('Capability_Bitcoin_like')
|
|
332
|
+
? types_1.FirmwareType.BitcoinOnly
|
|
333
|
+
: types_1.FirmwareType.Regular;
|
|
334
|
+
}
|
|
333
335
|
}
|
|
334
336
|
isUnacquired() {
|
|
335
337
|
return this.features === undefined;
|
|
@@ -311,7 +311,12 @@ class DeviceCommands {
|
|
|
311
311
|
});
|
|
312
312
|
}
|
|
313
313
|
if (res.type === 'PinMatrixRequest') {
|
|
314
|
-
return this._promptPin(res.message.type).then(pin => this._commonCall('PinMatrixAck', { pin })
|
|
314
|
+
return this._promptPin(res.message.type).then(pin => this._commonCall('PinMatrixAck', { pin }).then(response => {
|
|
315
|
+
if (!this.device.features.unlocked) {
|
|
316
|
+
return this.device.getFeatures().then(() => response);
|
|
317
|
+
}
|
|
318
|
+
return response;
|
|
319
|
+
}), () => this._commonCall('Cancel', {}));
|
|
315
320
|
}
|
|
316
321
|
if (res.type === 'PassphraseRequest') {
|
|
317
322
|
const state = this.device.getInternalState();
|
package/lib/events/popup.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export declare const POPUP: {
|
|
|
12
12
|
readonly CLOSED: "popup-closed";
|
|
13
13
|
readonly CANCEL_POPUP_REQUEST: "ui-cancel-popup-request";
|
|
14
14
|
readonly CLOSE_WINDOW: "window.close";
|
|
15
|
+
readonly ANALYTICS_RESPONSE: "popup-analytics-response";
|
|
15
16
|
};
|
|
16
17
|
export interface PopupInit {
|
|
17
18
|
type: typeof POPUP.INIT;
|
|
@@ -41,10 +42,16 @@ export interface PopupClosedMessage {
|
|
|
41
42
|
error: any;
|
|
42
43
|
} | null;
|
|
43
44
|
}
|
|
45
|
+
export interface PopupAnalyticsResponse {
|
|
46
|
+
type: typeof POPUP.ANALYTICS_RESPONSE;
|
|
47
|
+
payload: {
|
|
48
|
+
enabled: boolean;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
44
51
|
export type PopupEvent = {
|
|
45
52
|
type: typeof POPUP.LOADED | typeof POPUP.CANCEL_POPUP_REQUEST;
|
|
46
53
|
payload?: typeof undefined;
|
|
47
|
-
} | PopupInit | PopupHandshake | PopupError | PopupClosedMessage;
|
|
54
|
+
} | PopupInit | PopupHandshake | PopupError | PopupClosedMessage | PopupAnalyticsResponse;
|
|
48
55
|
export type PopupEventMessage = PopupEvent & {
|
|
49
56
|
event: typeof UI_EVENT;
|
|
50
57
|
};
|