Skip to content

Commit

Permalink
Update typescript and tslib
Browse files Browse the repository at this point in the history
Also update @typescript-eslint/eslint-plugin, @typescript-eslint/parser and eslint-config-airbnb-typescript
for compatibility with the updated typescript version, and fix newly reported type and lint issues.

Additionally, with the merge of rollup/plugins#818, the rootDir hack for making
typescript build in combination with emitting declaration files could now be removed. For the previous hack
see rollup/plugins#61 (comment) and
rollup/plugins#287.
  • Loading branch information
danimoh committed Nov 21, 2023
1 parent a05b632 commit 77cd7dd
Show file tree
Hide file tree
Showing 17 changed files with 745 additions and 178 deletions.
4 changes: 3 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ module.exports = {
ecmaVersion: 2020,
},
root: true,
plugins: ['import'],
rules: {
'no-console': 'off',
'no-debugger': isProduction ? 'error' : 'off',
Expand Down Expand Up @@ -47,9 +48,10 @@ module.exports = {
'@typescript-eslint/no-namespace': 'off',
'@typescript-eslint/lines-between-class-members': 'off',

// False positives that are checked by TS
// Disable rules that are already checked by TS.
indent: 'off',
'no-redeclare': 'off',
'@typescript-eslint/no-redeclare': 'off',
'@typescript-eslint/no-use-before-define': 'off',
'import/no-unresolved': 'off',
'import/extensions': 'off',
Expand Down
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,19 @@
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^13.0.6",
"@rollup/plugin-typescript": "^8.1.1",
"@typescript-eslint/eslint-plugin": "^4.14.2",
"@typescript-eslint/parser": "^4.14.2",
"@typescript-eslint/eslint-plugin": "^6.12.0",
"@typescript-eslint/parser": "^6.12.0",
"bitcoinjs-message": "^2.2.0",
"eslint": "^7.19.0",
"eslint-config-airbnb-typescript": "^12.3.1",
"eslint-config-airbnb-typescript": "^17.1.0",
"eslint-plugin-import": "^2.22.1",
"rollup": "^2.68.0",
"rollup-plugin-copy": "^3.3.0",
"rollup-plugin-livereload": "^2.0.0",
"rollup-plugin-serve": "^1.1.0",
"rollup-plugin-sourcemaps": "^0.6.3",
"tslib": "^2.1.0",
"typescript": "^4.1.3"
"tslib": "^2.6.2",
"typescript": "^5.2.2"
},
"dependencies": {
"@ledgerhq/hw-app-btc": "^10.0.9",
Expand Down
4 changes: 0 additions & 4 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,6 @@ export default (commandLineArgs) => {
include: ['src/high-level-api/**', 'src/low-level-api/**', 'src/lib/**'],
declaration: true,
declarationDir: 'dist',
// temporary, see https://github.com/rollup/plugins/issues/61#issuecomment-596270901 and
// https://github.com/rollup/plugins/issues/287
rootDir: 'src',
noEmitOnError: isProduction,
}),
// Read code including sourcemaps. Has to happen after typescript as ts files should be loaded by typescript
Expand Down Expand Up @@ -204,7 +201,6 @@ export default (commandLineArgs) => {
include: ['src/low-level-api/**', 'src/lib/**'],
declaration: true,
declarationDir: 'dist',
rootDir: 'src', // temporary, see https://github.com/rollup/plugins/issues/61#issuecomment-596270901
noEmitOnError: isProduction,
}),
resolve({
Expand Down
3 changes: 2 additions & 1 deletion src/demo/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import TransportU2F from '@ledgerhq/hw-transport-u2f';
import NetworkTransportForUrls from '@ledgerhq/hw-transport-http';
// dev dependencies for the demo page
/* eslint-disable import/no-extraneous-dependencies */
// Note: we installed @ledgerhq/logs and bitcoinjs-message only as dev dependencies, as they're only used in the demo.
import { listen as onLog } from '@ledgerhq/logs';
import { verify as verifySignedMessageBitcoin } from 'bitcoinjs-message';
/* eslint-enable import/no-extraneous-dependencies */
Expand Down Expand Up @@ -1053,7 +1054,7 @@ window.addEventListener('load', () => {
}
$txSignatureNimiq.textContent = Nimiq.BufferUtils.toHex(signature);
} catch (error) {
displayStatus(error);
displayStatus(error instanceof Error ? error.message : String(error));
}
}

Expand Down
16 changes: 10 additions & 6 deletions src/high-level-api/ledger-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ export default class LedgerApi {
} catch (e) {
const error = new ErrorState(
ErrorType.LOADING_DEPENDENCIES_FAILED,
`Failed loading dependencies: ${e.message || e}`,
`Failed loading dependencies: ${e instanceof Error ? e.message : e}`,
undefined,
);
LedgerApi._setState(error);
Expand Down Expand Up @@ -517,7 +517,7 @@ export default class LedgerApi {
LedgerApi._setState(e);
}

const message = (e.message || e || '').toLowerCase();
const message = (e instanceof Error ? e.message : String(e)).toLowerCase();
// "timeout" used to happen for u2f, it's "device_ineligible" or "other_error" now (see
// transport-comparison.md). "timed out" is for Chrome WebAuthn timeout; "denied permission" for
// Firefox WebAuthn timeout.
Expand Down Expand Up @@ -613,7 +613,7 @@ export default class LedgerApi {
try {
LedgerApi._currentConnection = await request.checkCoinAppConnection(transport);
} catch (e) {
const message = (e.message || e || '').toLowerCase();
const message = (e instanceof Error ? e.message : String(e)).toLowerCase();
if (message.indexOf('busy') !== -1) {
throw new ErrorState(
ErrorType.LEDGER_BUSY,
Expand Down Expand Up @@ -669,7 +669,7 @@ export default class LedgerApi {
if (transportType === LedgerApi._transportType) {
throw new ErrorState(
ErrorType.LOADING_DEPENDENCIES_FAILED,
`Failed loading dependencies: ${e.message || e}`,
`Failed loading dependencies: ${e instanceof Error ? e.message : e}`,
request,
);
}
Expand All @@ -691,7 +691,7 @@ export default class LedgerApi {
);
} catch (e) {
if (transportType === LedgerApi._transportType) {
const message = (e.message || e).toLowerCase();
const message = (e instanceof Error ? e.message : String(e)).toLowerCase();
if (/no device selected|access denied|cancelled the requestdevice/i.test(message)) {
LedgerApi._connectionAborted = true;
throw new ErrorState(
Expand All @@ -700,7 +700,11 @@ export default class LedgerApi {
request,
);
} else if (message.indexOf('user gesture') !== -1) {
throw new ErrorState(ErrorType.USER_INTERACTION_REQUIRED, e, request);
throw new ErrorState(
ErrorType.USER_INTERACTION_REQUIRED,
e instanceof Error ? e : String(e),
request,
);
} else {
throw e; // rethrow unknown exception
}
Expand Down
39 changes: 22 additions & 17 deletions src/high-level-api/requests/bitcoin/request-bitcoin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type Transport = import('@ledgerhq/hw-transport').default;
type LowLevelApiConstructor = typeof import('@ledgerhq/hw-app-btc').default;
type LowLevelApi = InstanceType<LowLevelApiConstructor>;
type BitcoinLib = typeof import('./bitcoin-lib');
type Sha256 = typeof import('sha.js/sha256').default;

export { RequestTypeBitcoin };

Expand Down Expand Up @@ -46,15 +47,15 @@ export default abstract class RequestBitcoin<T> extends Request<T> {
// Ignore errors.
Promise.all([
this._loadLowLevelApi(), // needed by all requests
this._isWalletIdDerivationRequired ? import('sha.js/sha256') : null,
this._isWalletIdDerivationRequired ? this._loadSha256() : null,
]).catch(() => {});
}

public async checkCoinAppConnection(transport: Transport): Promise<CoinAppConnection> {
const coinAppConnection = await super.checkCoinAppConnection(transport, 'BTC');
if (!this._isWalletIdDerivationRequired) return coinAppConnection; // skip wallet id derivation

// Note that api and sha256 are preloaded in the constructor, therefore we don't need to optimize for load order
// Note that api and Sha256 are preloaded in the constructor, therefore we don't need to optimize for load order
// or execution order here.
const api = await this._getLowLevelApi(transport); // throws LOADING_DEPENDENCIES_FAILED on failure
// TODO For u2f and WebAuthn, the Ledger displays a confirmation screen to get the public key if the user has
Expand All @@ -69,19 +70,9 @@ export default abstract class RequestBitcoin<T> extends Request<T> {
isInternal: false,
}));

let Sha256: typeof import('sha.js/sha256').default;
try {
// Note that loading sha here only for wallet id calculation is not really wasteful as it's also imported
// by the ledger api and bitcoinjs.
Sha256 = (await import('sha.js/sha256')).default;
} catch (e) {
throw new ErrorState(
ErrorType.LOADING_DEPENDENCIES_FAILED,
`Failed loading dependencies: ${e.message || e}`,
this,
);
}

// Note that loading sha.js here only for wallet id calculation is not really wasteful as it's also imported by
// @ledgerhq/hw-app-bitcoin and bitcoinjs-lib via create-hash anyway.
const Sha256 = await this._loadSha256();
const walletId = new Sha256().update(publicKey, 'hex').digest('base64');
coinAppConnection.walletId = walletId; // change the original object which equals _coinAppConnection
this._checkExpectedWalletId(walletId);
Expand Down Expand Up @@ -118,7 +109,7 @@ export default abstract class RequestBitcoin<T> extends Request<T> {
} catch (e) {
throw new ErrorState(
ErrorType.LOADING_DEPENDENCIES_FAILED,
`Failed loading dependencies: ${e.message || e}`,
`Failed loading dependencies: ${e instanceof Error ? e.message : e}`,
this,
);
}
Expand All @@ -130,7 +121,21 @@ export default abstract class RequestBitcoin<T> extends Request<T> {
} catch (e) {
throw new ErrorState(
ErrorType.LOADING_DEPENDENCIES_FAILED,
`Failed loading dependencies: ${e.message || e}`,
`Failed loading dependencies: ${e instanceof Error ? e.message : e}`,
this,
);
}
}

protected async _loadSha256(): Promise<Sha256> {
try {
// Note: we've not installed sha.js as dependency, to make sure we're using the version that comes with
// @ledgerhq/hw-app-btc and bitcoinjs-lib#create-hash without the risk of bundling an additional version.
return (await import('sha.js/sha256')).default; // eslint-disable-line import/no-extraneous-dependencies
} catch (e) {
throw new ErrorState(
ErrorType.LOADING_DEPENDENCIES_FAILED,
`Failed loading dependencies: ${e instanceof Error ? e.message : e}`,
this,
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export default class RequestGetAddressAndPublicKeyBitcoin extends RequestBitcoin
} catch (e) {
throw new ErrorState(
ErrorType.REQUEST_ASSERTION_FAILED,
`Invalid keyPath ${keyPath}: ${e.message || e}`,
`Invalid keyPath ${keyPath}: ${e instanceof Error ? e.message : e}`,
this,
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ export default class RequestGetExtendedPublicKeyBitcoin extends RequestBitcoin<s
extendedPubKey.network = networkInfo;
return extendedPubKey.toBase58();
} catch (e) {
throw new ErrorState(ErrorType.REQUEST_ASSERTION_FAILED, e, this);
throw new ErrorState(ErrorType.REQUEST_ASSERTION_FAILED, e instanceof Error ? e : String(e), this);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export default class RequestSignMessageBitcoin extends RequestBitcoin<MessageSig
} catch (e) {
throw new ErrorState(
ErrorType.REQUEST_ASSERTION_FAILED,
`Invalid keyPath ${keyPath}: ${e.message || e}`,
`Invalid keyPath ${keyPath}: ${e instanceof Error ? e.message : e}`,
this,
);
}
Expand Down Expand Up @@ -74,7 +74,7 @@ export default class RequestSignMessageBitcoin extends RequestBitcoin<MessageSig
throw new Error('Message too long');
}
} catch (e) {
throw new ErrorState(ErrorType.REQUEST_ASSERTION_FAILED, e, this);
throw new ErrorState(ErrorType.REQUEST_ASSERTION_FAILED, e instanceof Error ? e : String(e), this);
}

if (this.network === Network.TESTNET && this._addressType === AddressTypeBitcoin.LEGACY) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export default class RequestSignTransactionBitcoin extends RequestBitcoin<string
} catch (e) {
throw new ErrorState(
ErrorType.REQUEST_ASSERTION_FAILED,
`Invalid request: ${e.message || e}`,
`Invalid request: ${e instanceof Error ? e.message : e}`,
this,
);
}
Expand Down Expand Up @@ -275,7 +275,7 @@ export default class RequestSignTransactionBitcoin extends RequestBitcoin<string
parsedTransaction.useTrustedInputForSegwit = useTrustedInputForSegwit;
}
} catch (e) {
throw new ErrorState(ErrorType.REQUEST_ASSERTION_FAILED, e, this);
throw new ErrorState(ErrorType.REQUEST_ASSERTION_FAILED, e instanceof Error ? e : String(e), this);
}

// Note: We make api calls outside of the try...catch block to let the exceptions fall through such that
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default class RequestDeriveAddressesNimiq extends RequestNimiq<Array<{ ad
} catch (e) {
throw new ErrorState(
ErrorType.REQUEST_ASSERTION_FAILED,
`Invalid keyPath ${keyPath}: ${e.message || e}`,
`Invalid keyPath ${keyPath}: ${e instanceof Error ? e.message : e}`,
this,
);
}
Expand Down
4 changes: 2 additions & 2 deletions src/high-level-api/requests/nimiq/request-nimiq.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export default abstract class RequestNimiq<T> extends Request<T> {
} catch (e) {
throw new ErrorState(
ErrorType.LOADING_DEPENDENCIES_FAILED,
`Failed loading dependencies: ${e.message || e}`,
`Failed loading dependencies: ${e instanceof Error ? e.message : e}`,
this,
);
}
Expand All @@ -96,7 +96,7 @@ export default abstract class RequestNimiq<T> extends Request<T> {
} catch (e) {
throw new ErrorState(
ErrorType.LOADING_DEPENDENCIES_FAILED,
`Failed loading dependencies: ${e.message || e}`,
`Failed loading dependencies: ${e instanceof Error ? e.message : e}`,
this,
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export default class RequestSignMessageNimiq extends RequestWithKeyPathNimiq<Mes
throw new Error('Message too long');
}
} catch (e) {
throw new ErrorState(ErrorType.REQUEST_ASSERTION_FAILED, e, this);
throw new ErrorState(ErrorType.REQUEST_ASSERTION_FAILED, e instanceof Error ? e : String(e), this);
}

const { publicKey } = await api.getPublicKey(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export default class RequestSignTransactionNimiq extends RequestWithKeyPathNimiq
fee, tx.validityStartHeight, /* signature */ undefined, networkId);
}
} catch (e) {
throw new ErrorState(ErrorType.REQUEST_ASSERTION_FAILED, e, this);
throw new ErrorState(ErrorType.REQUEST_ASSERTION_FAILED, e instanceof Error ? e : String(e), this);
}

const { signature: signatureBytes } = await api.signTransaction(
Expand All @@ -111,7 +111,7 @@ export default class RequestSignTransactionNimiq extends RequestWithKeyPathNimiq
nimiqTx.proof = Nimiq.SignatureProof.singleSig(signerPubKey!, signature).serialize();
}
} catch (e) {
throw new ErrorState(ErrorType.REQUEST_ASSERTION_FAILED, e, this);
throw new ErrorState(ErrorType.REQUEST_ASSERTION_FAILED, e instanceof Error ? e : String(e), this);
}

return nimiqTx;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default abstract class RequestWithKeyPathNimiq<T> extends RequestNimiq<T>
}
throw new ErrorState(
ErrorType.REQUEST_ASSERTION_FAILED,
`Invalid keyPath ${keyPath}: ${e.message || e}`,
`Invalid keyPath ${keyPath}: ${e instanceof Error ? e.message : e}`,
this,
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/high-level-api/transport-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export function getNetworkEndpoint(): string {
* @param transportType
*/
export async function loadTransportLibrary(transportType: TransportType)
: Promise<TransportWebUsbConstructor|TransportConstructor> {
: Promise<TransportWebUsbConstructor | TransportConstructor> {
switch (transportType) {
case TransportType.WEB_HID:
return (await import('@ledgerhq/hw-transport-webhid')).default;
Expand Down
Loading

0 comments on commit 77cd7dd

Please sign in to comment.