diff options
author | Florian Dold <florian.dold@gmail.com> | 2020-04-07 13:37:32 +0530 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2020-04-07 13:37:32 +0530 |
commit | fb2e2f89935240666de66e4b2c11125cb3b2943d (patch) | |
tree | 7b7e148e6cce7bf7639a5e35102f5269f5920ab5 /src | |
parent | 1471aae8927c20d646cc2aa5ab0e20c1a7f2c0ca (diff) |
more lint fixes
Diffstat (limited to 'src')
59 files changed, 371 insertions, 410 deletions
diff --git a/src/android/index.ts b/src/android/index.ts index 9c7efc0e1..019fe1fb3 100644 --- a/src/android/index.ts +++ b/src/android/index.ts @@ -32,7 +32,6 @@ import { Headers, } from "../util/http"; import { NodeHttpLib } from "../headless/NodeHttpLib"; -import { OperationFailedAndReportedError } from "../operations/errors"; import { WalletNotification } from "../types/notifications"; // @ts-ignore: special built-in module @@ -99,7 +98,7 @@ export class AndroidHttpLib implements HttpRequestLibrary { } } - handleTunnelResponse(msg: any) { + handleTunnelResponse(msg: any): void { const myId = msg.id; const p = this.requestMap[myId]; if (!p) { @@ -123,7 +122,7 @@ export class AndroidHttpLib implements HttpRequestLibrary { } } -function sendAkonoMessage(m: string) { +function sendAkonoMessage(m: string): void { // @ts-ignore globalThis.__akono_sendMessage(m); } @@ -266,7 +265,7 @@ class AndroidWalletMessageHandler { } } -export function installAndroidWalletListener() { +export function installAndroidWalletListener(): void { // @ts-ignore const sendMessage: (m: string) => void = globalThis.__akono_sendMessage; if (typeof sendMessage !== "function") { @@ -276,7 +275,7 @@ export function installAndroidWalletListener() { throw new Error(errMsg); } const handler = new AndroidWalletMessageHandler(); - const onMessage = async (msgStr: any) => { + const onMessage = async (msgStr: any): Promise<void> => { if (typeof msgStr !== "string") { console.error("expected string as message"); return; diff --git a/src/crypto/primitives/kdf.ts b/src/crypto/primitives/kdf.ts index 03deb3727..edc681bc1 100644 --- a/src/crypto/primitives/kdf.ts +++ b/src/crypto/primitives/kdf.ts @@ -51,11 +51,11 @@ export function hmac( return digest(b2); } -export function hmacSha512(key: Uint8Array, message: Uint8Array) { +export function hmacSha512(key: Uint8Array, message: Uint8Array): Uint8Array { return hmac(sha512, 128, key, message); } -export function hmacSha256(key: Uint8Array, message: Uint8Array) { +export function hmacSha256(key: Uint8Array, message: Uint8Array): Uint8Array { return hmac(sha256, 64, key, message); } diff --git a/src/crypto/primitives/sha256.ts b/src/crypto/primitives/sha256.ts index ed88b5ffd..97723dbfc 100644 --- a/src/crypto/primitives/sha256.ts +++ b/src/crypto/primitives/sha256.ts @@ -215,7 +215,7 @@ export class HashSha256 { } // Cleans internal buffers and re-initializes hash state. - clean() { + clean(): void { for (let i = 0; i < this.buffer.length; i++) { this.buffer[i] = 0; } @@ -306,14 +306,14 @@ export class HashSha256 { } // Internal function for use in HMAC for optimization. - _saveState(out: Uint32Array) { + _saveState(out: Uint32Array): void { for (let i = 0; i < this.state.length; i++) { out[i] = this.state[i]; } } // Internal function for use in HMAC for optimization. - _restoreState(from: Uint32Array, bytesHashed: number) { + _restoreState(from: Uint32Array, bytesHashed: number): void { for (let i = 0; i < this.state.length; i++) { this.state[i] = from[i]; } @@ -376,7 +376,7 @@ export class HMAC { } // Cleans HMAC state. - clean() { + clean(): void { for (let i = 0; i < this.istate.length; i++) { this.ostate[i] = this.istate[i] = 0; } @@ -418,7 +418,7 @@ export function sha256(data: Uint8Array): Uint8Array { } // Returns HMAC-SHA256 of data under the key. -export function hmacSha256(key: Uint8Array, data: Uint8Array) { +export function hmacSha256(key: Uint8Array, data: Uint8Array): Uint8Array { const h = new HMAC(key).update(data); const digest = h.digest(); h.clean(); diff --git a/src/crypto/talerCrypto.ts b/src/crypto/talerCrypto.ts index 3da4f4a47..457009a04 100644 --- a/src/crypto/talerCrypto.ts +++ b/src/crypto/talerCrypto.ts @@ -191,12 +191,12 @@ function kdfMod( } } -export function stringToBytes(s: string) { +export function stringToBytes(s: string): Uint8Array { const te = new TextEncoder(); return te.encode(s); } -function loadBigInt(arr: Uint8Array) { +function loadBigInt(arr: Uint8Array): bigint.BigInteger { return bigint.fromArray(Array.from(arr), 256, false); } @@ -219,7 +219,7 @@ function rsaBlindingKeyDerive( * @param r KDF result * @param n RSA modulus of the public key */ -function rsaGcdValidate(r: bigint.BigInteger, n: bigint.BigInteger) { +function rsaGcdValidate(r: bigint.BigInteger, n: bigint.BigInteger): void { const t = bigint.gcd(r, n); if (!t.equals(bigint.one)) { throw Error("malicious RSA public key"); diff --git a/src/crypto/workers/cryptoApi.ts b/src/crypto/workers/cryptoApi.ts index 24a43ff47..456bf309e 100644 --- a/src/crypto/workers/cryptoApi.ts +++ b/src/crypto/workers/cryptoApi.ts @@ -34,13 +34,7 @@ import { import { CryptoWorker } from "./cryptoWorker"; -import { - RecoupRequest, - CoinDepositPermission, - RecoupConfirmation, - ExchangeSignKeyJson, - EddsaPublicKeyString, -} from "../../types/talerTypes"; +import { RecoupRequest, CoinDepositPermission } from "../../types/talerTypes"; import { BenchmarkResult, @@ -154,7 +148,7 @@ export class CryptoApi { /** * Terminate all worker threads. */ - terminateWorkers() { + terminateWorkers(): void { for (const worker of this.workers) { if (worker.w) { CryptoApi.enableTracing && console.log("terminating worker"); @@ -172,7 +166,7 @@ export class CryptoApi { } } - stop() { + stop(): void { this.terminateWorkers(); this.stopped = true; } @@ -192,11 +186,14 @@ export class CryptoApi { } ws.currentWorkItem = work; this.numBusy++; + let worker: CryptoWorker; if (!ws.w) { - const w = this.workerFactory.startWorker(); - w.onmessage = (m: MessageEvent) => this.handleWorkerMessage(ws, m); - w.onerror = (e: ErrorEvent) => this.handleWorkerError(ws, e); - ws.w = w; + worker = this.workerFactory.startWorker(); + worker.onmessage = (m: MessageEvent) => this.handleWorkerMessage(ws, m); + worker.onerror = (e: ErrorEvent) => this.handleWorkerError(ws, e); + ws.w = worker; + } else { + worker = ws.w; } const msg: any = { @@ -206,28 +203,28 @@ export class CryptoApi { }; this.resetWorkerTimeout(ws); work.startTime = timer.performanceNow(); - setTimeout(() => ws.w!.postMessage(msg), 0); + setTimeout(() => worker.postMessage(msg), 0); } - resetWorkerTimeout(ws: WorkerState) { + resetWorkerTimeout(ws: WorkerState): void { if (ws.terminationTimerHandle !== null) { ws.terminationTimerHandle.clear(); ws.terminationTimerHandle = null; } - const destroy = () => { + const destroy = (): void => { // terminate worker if it's idle if (ws.w && ws.currentWorkItem === null) { - ws.w!.terminate(); + ws.w.terminate(); ws.w = null; } }; ws.terminationTimerHandle = timer.after(15 * 1000, destroy); } - handleWorkerError(ws: WorkerState, e: ErrorEvent) { + handleWorkerError(ws: WorkerState, e: ErrorEvent): void { if (ws.currentWorkItem) { console.error( - `error in worker during ${ws.currentWorkItem!.operation}`, + `error in worker during ${ws.currentWorkItem.operation}`, e, ); } else { @@ -235,8 +232,10 @@ export class CryptoApi { } console.error(e.message); try { - ws.w!.terminate(); - ws.w = null; + if (ws.w) { + ws.w.terminate(); + ws.w = null; + } } catch (e) { console.error(e); } @@ -248,19 +247,22 @@ export class CryptoApi { this.findWork(ws); } - private findWork(ws: WorkerState) { + private findWork(ws: WorkerState): void { // try to find more work for this worker for (let i = 0; i < NUM_PRIO; i++) { const q = this.workQueues[NUM_PRIO - i - 1]; if (q.length !== 0) { - const work: WorkItem = q.shift()!; + const work: WorkItem | undefined = q.shift(); + if (!work) { + continue; + } this.wake(ws, work); return; } } } - handleWorkerMessage(ws: WorkerState, msg: MessageEvent) { + handleWorkerMessage(ws: WorkerState, msg: MessageEvent): void { const id = msg.data.id; if (typeof id !== "number") { console.error("rpc id must be number"); diff --git a/src/crypto/workers/cryptoImplementation.ts b/src/crypto/workers/cryptoImplementation.ts index 0a3c217ab..96ad29bc0 100644 --- a/src/crypto/workers/cryptoImplementation.ts +++ b/src/crypto/workers/cryptoImplementation.ts @@ -36,13 +36,7 @@ import { CoinSourceType, } from "../../types/dbTypes"; -import { - CoinDepositPermission, - RecoupRequest, - RecoupConfirmation, - ExchangeSignKeyJson, - EddsaPublicKeyString, -} from "../../types/talerTypes"; +import { CoinDepositPermission, RecoupRequest } from "../../types/talerTypes"; import { BenchmarkResult, PlanchetCreationResult, @@ -70,11 +64,7 @@ import { } from "../talerCrypto"; import { randomBytes } from "../primitives/nacl-fast"; import { kdf } from "../primitives/kdf"; -import { - Timestamp, - getTimestampNow, - timestampIsBetween, -} from "../../util/time"; +import { Timestamp, getTimestampNow } from "../../util/time"; enum SignaturePurpose { RESERVE_WITHDRAW = 1200, @@ -144,24 +134,9 @@ function buildSigPS(purposeNum: number): SignaturePurposeBuilder { return new SignaturePurposeBuilder(purposeNum); } -function checkSignKeyOkay( - key: string, - exchangeKeys: ExchangeSignKeyJson[], -): boolean { - const now = getTimestampNow(); - for (const k of exchangeKeys) { - if (k.key == key) { - return timestampIsBetween(now, k.stamp_start, k.stamp_end); - } - } - return false; -} - export class CryptoImplementation { static enableTracing = false; - constructor() {} - /** * Create a pre-coin of the given denomination to be withdrawn from then given * reserve. @@ -535,7 +510,7 @@ export class CryptoImplementation { let time_eddsa_create = 0; for (let i = 0; i < repetitions; i++) { const start = timer.performanceNow(); - const pair = createEddsaKeyPair(); + createEddsaKeyPair(); time_eddsa_create += timer.performanceNow() - start; } diff --git a/src/crypto/workers/nodeThreadWorker.ts b/src/crypto/workers/nodeThreadWorker.ts index d289c14b2..6c9dfc569 100644 --- a/src/crypto/workers/nodeThreadWorker.ts +++ b/src/crypto/workers/nodeThreadWorker.ts @@ -1,5 +1,3 @@ -import { CryptoWorkerFactory } from "./cryptoApi"; - /* This file is part of TALER (C) 2016 GNUnet e.V. @@ -16,8 +14,10 @@ import { CryptoWorkerFactory } from "./cryptoApi"; TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -// tslint:disable:no-var-requires - +/** + * Imports + */ +import { CryptoWorkerFactory } from "./cryptoApi"; import { CryptoWorker } from "./cryptoWorker"; import os from "os"; import { CryptoImplementation } from "./cryptoImplementation"; @@ -55,7 +55,7 @@ const workerCode = ` * This function is executed in the worker thread to handle * a message. */ -export function handleWorkerMessage(msg: any) { +export function handleWorkerMessage(msg: any): void { const args = msg.args; if (!Array.isArray(args)) { console.error("args must be array"); @@ -72,7 +72,7 @@ export function handleWorkerMessage(msg: any) { return; } - const handleRequest = async () => { + const handleRequest = async (): Promise<void> => { const impl = new CryptoImplementation(); if (!(operation in impl)) { @@ -82,6 +82,7 @@ export function handleWorkerMessage(msg: any) { try { const result = (impl as any)[operation](...args); + // eslint-disable-next-line @typescript-eslint/no-var-requires const worker_threads = require("worker_threads"); const p = worker_threads.parentPort; worker_threads.parentPort?.postMessage; @@ -101,7 +102,7 @@ export function handleWorkerMessage(msg: any) { }); } -export function handleWorkerError(e: Error) { +export function handleWorkerError(e: Error): void { console.log("got error from worker", e); } @@ -135,6 +136,7 @@ class NodeThreadCryptoWorker implements CryptoWorker { private nodeWorker: import("worker_threads").Worker; constructor() { + // eslint-disable-next-line @typescript-eslint/no-var-requires const worker_threads = require("worker_threads"); this.nodeWorker = new worker_threads.Worker(workerCode, { eval: true }); this.nodeWorker.on("error", (err: Error) => { @@ -168,14 +170,14 @@ class NodeThreadCryptoWorker implements CryptoWorker { /** * Send a message to the worker thread. */ - postMessage(msg: any) { + postMessage(msg: any): void { this.nodeWorker.postMessage(msg); } /** * Forcibly terminate the worker thread. */ - terminate() { + terminate(): void { this.nodeWorker.terminate(); } } diff --git a/src/crypto/workers/synchronousWorker.ts b/src/crypto/workers/synchronousWorker.ts index f4bcf396c..2cc740975 100644 --- a/src/crypto/workers/synchronousWorker.ts +++ b/src/crypto/workers/synchronousWorker.ts @@ -70,13 +70,17 @@ export class SynchronousCryptoWorker { } } - private dispatchMessage(msg: any) { + private dispatchMessage(msg: any): void { if (this.onmessage) { this.onmessage({ data: msg }); } } - private async handleRequest(operation: string, id: number, args: string[]) { + private async handleRequest( + operation: string, + id: number, + args: string[], + ): Promise<void> { const impl = new CryptoImplementation(); if (!(operation in impl)) { @@ -102,7 +106,7 @@ export class SynchronousCryptoWorker { /** * Send a message to the worker thread. */ - postMessage(msg: any) { + postMessage(msg: any): void { const args = msg.args; if (!Array.isArray(args)) { console.error("args must be array"); @@ -127,7 +131,7 @@ export class SynchronousCryptoWorker { /** * Forcibly terminate the worker thread. */ - terminate() { + terminate(): void { // This is a no-op. } } @@ -23,7 +23,7 @@ export function openTalerDatabase( db: IDBDatabase, oldVersion: number, newVersion: number, - ) => { + ): void => { switch (oldVersion) { case 0: // DB does not exist yet for (const n in Stores) { @@ -53,6 +53,6 @@ export function openTalerDatabase( ); } -export function deleteTalerDatabase(idbFactory: IDBFactory) { +export function deleteTalerDatabase(idbFactory: IDBFactory): void { Database.deleteDatabase(idbFactory, TALER_DB_NAME); } diff --git a/src/headless/bank.ts b/src/headless/bank.ts index 81b5293bd..2177908a6 100644 --- a/src/headless/bank.ts +++ b/src/headless/bank.ts @@ -95,7 +95,7 @@ export class Bank { amount: string, reservePub: string, exchangePaytoUri: string, - ) { + ): Promise<void> { const reqUrl = new URL("testing/withdraw", this.bankBaseUrl).href; const body = { diff --git a/src/headless/clk.ts b/src/headless/clk.ts index 09f758ad4..a905464bd 100644 --- a/src/headless/clk.ts +++ b/src/headless/clk.ts @@ -117,7 +117,7 @@ export class CommandGroup<GN extends keyof any, TG> { private scArgs: SubcommandArgs, ) {} - action(f: ActionFn<TG>) { + action(f: ActionFn<TG>): void { if (this.myAction) { throw Error("only one action supported per command"); } @@ -269,7 +269,7 @@ export class CommandGroup<GN extends keyof any, TG> { return cg as any; } - printHelp(progName: string, parents: CommandGroup<any, any>[]) { + printHelp(progName: string, parents: CommandGroup<any, any>[]): void { let usageSpec = ""; for (const p of parents) { usageSpec += (p.name ?? progName) + " "; @@ -320,7 +320,7 @@ export class CommandGroup<GN extends keyof any, TG> { parents: CommandGroup<any, any>[], unparsedArgs: string[], parsedArgs: any, - ) { + ): void { let posArgIndex = 0; let argsTerminated = false; let i; @@ -507,7 +507,7 @@ export class Program<PN extends keyof any, T> { }); } - run() { + run(): void { const args = process.argv; if (args.length < 2) { console.error( diff --git a/src/headless/helpers.ts b/src/headless/helpers.ts index 11e2c90de..47a0844bd 100644 --- a/src/headless/helpers.ts +++ b/src/headless/helpers.ts @@ -106,7 +106,7 @@ export async function getDefaultNodeWallet( myHttpLib = new NodeHttpLib(); } - const myVersionChange = () => { + const myVersionChange = (): Promise<void> => { console.error("version change requested, should not happen"); throw Error(); }; @@ -141,7 +141,7 @@ export async function withdrawTestBalance( amount = "TESTKUDOS:10", bankBaseUrl = "https://bank.test.taler.net/", exchangeBaseUrl = "https://exchange.test.taler.net/", -) { +): Promise<void> { const reserveResponse = await myWallet.createReserve({ amount: amounts.parseOrThrow(amount), exchange: exchangeBaseUrl, diff --git a/src/headless/merchant.ts b/src/headless/merchant.ts index 27e7e3f21..b479c5a8a 100644 --- a/src/headless/merchant.ts +++ b/src/headless/merchant.ts @@ -65,7 +65,7 @@ export class MerchantBackendConnection { constructor(public merchantBaseUrl: string, public apiKey: string) {} - async authorizeTip(amount: string, justification: string) { + async authorizeTip(amount: string, justification: string): Promise<string> { const reqUrl = new URL("tip-authorize", this.merchantBaseUrl).href; const tipReq = { amount, diff --git a/src/headless/taler-wallet-cli.ts b/src/headless/taler-wallet-cli.ts index a7dcce9a3..3da01a2dd 100644 --- a/src/headless/taler-wallet-cli.ts +++ b/src/headless/taler-wallet-cli.ts @@ -22,7 +22,7 @@ import { runIntegrationTest, runIntegrationTestBasic } from "./integrationtest"; import { Wallet } from "../wallet"; import qrcodeGenerator from "qrcode-generator"; import * as clk from "./clk"; -import { BridgeIDBFactory, MemoryBackend } from "idb-bridge"; +import { BridgeIDBFactory } from "idb-bridge"; import { Logger } from "../util/logging"; import { Amounts } from "../util/amounts"; import { decodeCrock } from "../crypto/talerCrypto"; @@ -46,7 +46,7 @@ async function doPay( wallet: Wallet, payUrl: string, options: { alwaysYes: boolean } = { alwaysYes: true }, -) { +): Promise<void> { const result = await wallet.preparePayForUri(payUrl); if (result.status === "error") { console.error("Could not pay:", result.error); @@ -89,21 +89,22 @@ async function doPay( } if (pay) { - const payRes = await wallet.confirmPay(result.proposalId, undefined); + await wallet.confirmPay(result.proposalId, undefined); console.log("paid!"); } else { console.log("not paying"); } } -function applyVerbose(verbose: boolean) { +function applyVerbose(verbose: boolean): void { if (verbose) { console.log("enabled verbose logging"); BridgeIDBFactory.enableTracing = true; } } -function printVersion() { +function printVersion(): void { + // eslint-disable-next-line @typescript-eslint/no-var-requires const info = require("../../../package.json"); console.log(`${info.version}`); process.exit(0); @@ -329,7 +330,7 @@ exchangesCli .flag("force", ["-f", "--force"]) .action(async (args) => { await withWallet(args, async (wallet) => { - const res = await wallet.updateExchangeFromUrl( + await wallet.updateExchangeFromUrl( args.exchangesUpdateCmd.url, args.exchangesUpdateCmd.force, ); diff --git a/src/operations/balance.ts b/src/operations/balance.ts index 7c2d0e3fe..c369af193 100644 --- a/src/operations/balance.ts +++ b/src/operations/balance.ts @@ -18,9 +18,9 @@ * Imports. */ import { WalletBalance, WalletBalanceEntry } from "../types/walletTypes"; -import { Database, TransactionHandle } from "../util/query"; +import { TransactionHandle } from "../util/query"; import { InternalWalletState } from "./state"; -import { Stores, TipRecord, CoinStatus } from "../types/dbTypes"; +import { Stores, CoinStatus } from "../types/dbTypes"; import * as Amounts from "../util/amounts"; import { AmountJson } from "../util/amounts"; import { Logger } from "../util/logging"; diff --git a/src/operations/exchanges.ts b/src/operations/exchanges.ts index 27fed0b6c..a9e5158e9 100644 --- a/src/operations/exchanges.ts +++ b/src/operations/exchanges.ts @@ -460,7 +460,8 @@ export async function updateExchangeFromUrl( baseUrl: string, forceNow = false, ): Promise<ExchangeRecord> { - const onOpErr = (e: OperationError): Promise<void> => setExchangeError(ws, baseUrl, e); + const onOpErr = (e: OperationError): Promise<void> => + setExchangeError(ws, baseUrl, e); return await guardOperationException( () => updateExchangeFromUrlImpl(ws, baseUrl, forceNow), onOpErr, diff --git a/src/operations/pending.ts b/src/operations/pending.ts index cee929aa2..3e548a27f 100644 --- a/src/operations/pending.ts +++ b/src/operations/pending.ts @@ -37,7 +37,7 @@ import { } from "../util/time"; import { TransactionHandle } from "../util/query"; import { InternalWalletState } from "./state"; -import { getBalances, getBalancesInsideTransaction } from "./balance"; +import { getBalancesInsideTransaction } from "./balance"; import { ReserveType } from "../types/history"; function updateRetryDelay( @@ -286,13 +286,23 @@ async function gatherProposalPending( if (onlyDue) { return; } - resp.pendingOperations.push({ - type: PendingOperationType.ProposalChoice, - givesLifeness: false, - merchantBaseUrl: proposal.download!!.contractData.merchantBaseUrl, - proposalId: proposal.proposalId, - proposalTimestamp: proposal.timestamp, - }); + const dl = proposal.download; + if (!dl) { + resp.pendingOperations.push({ + type: PendingOperationType.Bug, + message: "proposal is in invalid state", + details: {}, + givesLifeness: false, + }); + } else { + resp.pendingOperations.push({ + type: PendingOperationType.ProposalChoice, + givesLifeness: false, + merchantBaseUrl: dl.contractData.merchantBaseUrl, + proposalId: proposal.proposalId, + proposalTimestamp: proposal.timestamp, + }); + } } else if (proposal.proposalStatus == ProposalStatus.DOWNLOADING) { resp.nextRetryDelay = updateRetryDelay( resp.nextRetryDelay, diff --git a/src/operations/recoup.ts b/src/operations/recoup.ts index 97bc39564..e1c2325d7 100644 --- a/src/operations/recoup.ts +++ b/src/operations/recoup.ts @@ -279,7 +279,7 @@ async function recoupRefreshCoin( async function resetRecoupGroupRetry( ws: InternalWalletState, recoupGroupId: string, -) { +): Promise<void> { await ws.db.mutate(Stores.recoupGroups, recoupGroupId, (x) => { if (x.retryInfo.active) { x.retryInfo = initRetryInfo(); @@ -294,7 +294,7 @@ export async function processRecoupGroup( forceNow = false, ): Promise<void> { await ws.memoProcessRecoup.memo(recoupGroupId, async () => { - const onOpErr = (e: OperationError) => + const onOpErr = (e: OperationError): Promise<void> => incrementRecoupRetry(ws, recoupGroupId, e); return await guardOperationException( async () => await processRecoupGroupImpl(ws, recoupGroupId, forceNow), diff --git a/src/operations/refresh.ts b/src/operations/refresh.ts index 23d192e0a..924769334 100644 --- a/src/operations/refresh.ts +++ b/src/operations/refresh.ts @@ -28,7 +28,7 @@ import { CoinSourceType, } from "../types/dbTypes"; import { amountToPretty } from "../util/helpers"; -import { Database, TransactionHandle } from "../util/query"; +import { TransactionHandle } from "../util/query"; import { InternalWalletState } from "./state"; import { Logger } from "../util/logging"; import { getWithdrawDenomList } from "./withdraw"; @@ -390,8 +390,7 @@ async function refreshReveal( console.error("denom not found"); continue; } - const pc = - refreshSession.planchetsForGammas[refreshSession.norevealIndex!][i]; + const pc = refreshSession.planchetsForGammas[norevealIndex][i]; const denomSig = await ws.cryptoApi.rsaUnblind( respJson.ev_sigs[i].ev_sig, pc.blindingKey, @@ -485,7 +484,7 @@ export async function processRefreshGroup( forceNow = false, ): Promise<void> { await ws.memoProcessRefresh.memo(refreshGroupId, async () => { - const onOpErr = (e: OperationError) => + const onOpErr = (e: OperationError): Promise<void> => incrementRefreshRetry(ws, refreshGroupId, e); return await guardOperationException( async () => await processRefreshGroupImpl(ws, refreshGroupId, forceNow), @@ -497,7 +496,7 @@ export async function processRefreshGroup( async function resetRefreshGroupRetry( ws: InternalWalletState, refreshSessionId: string, -) { +): Promise<void> { await ws.db.mutate(Stores.refreshGroups, refreshSessionId, (x) => { if (x.retryInfo.active) { x.retryInfo = initRetryInfo(); @@ -510,7 +509,7 @@ async function processRefreshGroupImpl( ws: InternalWalletState, refreshGroupId: string, forceNow: boolean, -) { +): Promise<void> { if (forceNow) { await resetRefreshGroupRetry(ws, refreshGroupId); } @@ -532,7 +531,7 @@ async function processRefreshSession( ws: InternalWalletState, refreshGroupId: string, coinIndex: number, -) { +): Promise<void> { logger.trace( `processing refresh session for coin ${coinIndex} of group ${refreshGroupId}`, ); diff --git a/src/operations/refund.ts b/src/operations/refund.ts index af9a48895..8feb2baea 100644 --- a/src/operations/refund.ts +++ b/src/operations/refund.ts @@ -465,7 +465,7 @@ async function processPurchaseApplyRefundImpl( // Avoid duplicates const refreshCoinsMap: { [coinPub: string]: CoinPublicKey } = {}; - const modCoin = async (perm: MerchantRefundPermission) => { + const modCoin = async (perm: MerchantRefundPermission): Promise<void> => { const c = await tx.get(Stores.coins, perm.coin_pub); if (!c) { console.warn("coin not found, can't apply refund"); diff --git a/src/operations/reserves.ts b/src/operations/reserves.ts index 2ee1b358f..153ad6b88 100644 --- a/src/operations/reserves.ts +++ b/src/operations/reserves.ts @@ -44,10 +44,7 @@ import { getExchangeTrust, getExchangePaytoUri, } from "./exchanges"; -import { - WithdrawOperationStatusResponse, - codecForWithdrawOperationStatusResponse, -} from "../types/talerTypes"; +import { codecForWithdrawOperationStatusResponse } from "../types/talerTypes"; import { assertUnreachable } from "../util/assertUnreachable"; import { encodeCrock, getRandomBytes } from "../crypto/talerCrypto"; import { randomBytes } from "../crypto/primitives/nacl-fast"; @@ -71,7 +68,10 @@ import { const logger = new Logger("reserves.ts"); -async function resetReserveRetry(ws: InternalWalletState, reservePub: string) { +async function resetReserveRetry( + ws: InternalWalletState, + reservePub: string, +): Promise<void> { await ws.db.mutate(Stores.reserves, reservePub, (x) => { if (x.retryInfo.active) { x.retryInfo = initRetryInfo(); @@ -101,8 +101,6 @@ export async function createReserve( reserveStatus = ReserveRecordStatus.UNCONFIRMED; } - const currency = req.amount.currency; - const reserveRecord: ReserveRecord = { timestampCreated: now, exchangeBaseUrl: canonExchange, @@ -251,7 +249,7 @@ export async function processReserve( forceNow = false, ): Promise<void> { return ws.memoProcessReserve.memo(reservePub, async () => { - const onOpError = (err: OperationError) => + const onOpError = (err: OperationError): Promise<void> => incrementReserveRetry(ws, reservePub, err); await guardOperationException( () => processReserveImpl(ws, reservePub, forceNow), @@ -280,7 +278,8 @@ async function registerReserveWithBank( if (reserve.timestampReserveInfoPosted) { throw Error("bank claims that reserve info selection is not done"); } - const bankResp = await ws.http.postJson(bankStatusUrl, { + // FIXME: parse bank response + await ws.http.postJson(bankStatusUrl, { reserve_pub: reservePub, selected_exchange: reserve.exchangeWire, }); @@ -305,7 +304,7 @@ export async function processReserveBankStatus( ws: InternalWalletState, reservePub: string, ): Promise<void> { - const onOpError = (err: OperationError) => + const onOpError = (err: OperationError): Promise<void> => incrementReserveRetry(ws, reservePub, err); await guardOperationException( () => processReserveBankStatusImpl(ws, reservePub), @@ -330,20 +329,13 @@ async function processReserveBankStatusImpl( return; } - let status: WithdrawOperationStatusResponse; - try { - const statusResp = await ws.http.get(bankStatusUrl); - if (statusResp.status !== 200) { - throw Error( - `unexpected status ${statusResp.status} for bank status query`, - ); - } - status = codecForWithdrawOperationStatusResponse().decode( - await statusResp.json(), - ); - } catch (e) { - throw e; + const statusResp = await ws.http.get(bankStatusUrl); + if (statusResp.status !== 200) { + throw Error(`unexpected status ${statusResp.status} for bank status query`); } + const status = codecForWithdrawOperationStatusResponse().decode( + await statusResp.json(), + ); ws.notify({ type: NotificationType.Wildcard }); diff --git a/src/operations/state.ts b/src/operations/state.ts index 246a71266..97d591244 100644 --- a/src/operations/state.ts +++ b/src/operations/state.ts @@ -49,7 +49,7 @@ export class InternalWalletState { this.cryptoApi = new CryptoApi(cryptoWorkerFactory); } - public notify(n: WalletNotification) { + public notify(n: WalletNotification): void { logger.trace("Notification", n); for (const l of this.listeners) { const nc = JSON.parse(JSON.stringify(n)); diff --git a/src/operations/tip.ts b/src/operations/tip.ts index 1a88dbca3..6f492ea31 100644 --- a/src/operations/tip.ts +++ b/src/operations/tip.ts @@ -18,9 +18,7 @@ import { InternalWalletState } from "./state"; import { parseTipUri } from "../util/taleruri"; import { TipStatus, OperationError } from "../types/walletTypes"; import { - TipPickupGetResponse, TipPlanchetDetail, - TipResponse, codecForTipPickupGetResponse, codecForTipResponse, } from "../types/talerTypes"; @@ -149,7 +147,8 @@ export async function processTip( tipId: string, forceNow = false, ): Promise<void> { - const onOpErr = (e: OperationError) => incrementTipRetry(ws, tipId, e); + const onOpErr = (e: OperationError): Promise<void> => + incrementTipRetry(ws, tipId, e); await guardOperationException( () => processTipImpl(ws, tipId, forceNow), onOpErr, @@ -172,7 +171,7 @@ async function processTipImpl( ws: InternalWalletState, tipId: string, forceNow: boolean, -) { +): Promise<void> { if (forceNow) { await resetTipRetry(ws, tipId); } diff --git a/src/operations/withdraw.ts b/src/operations/withdraw.ts index 70ecf9aed..1f5bfd0b9 100644 --- a/src/operations/withdraw.ts +++ b/src/operations/withdraw.ts @@ -21,7 +21,6 @@ import { DenominationStatus, CoinStatus, CoinRecord, - PlanchetRecord, initRetryInfo, updateRetryInfoTimeout, CoinSourceType, @@ -52,14 +51,10 @@ import { timestampCmp, timestampSubtractDuraction, } from "../util/time"; -import { - summarizeReserveHistory, - ReserveHistorySummary, -} from "../util/reserveHistoryUtil"; const logger = new Logger("withdraw.ts"); -function isWithdrawableDenom(d: DenominationRecord) { +function isWithdrawableDenom(d: DenominationRecord): boolean { const now = getTimestampNow(); const started = timestampCmp(now, d.stampStart) >= 0; const lastPossibleWithdraw = timestampSubtractDuraction( @@ -175,8 +170,6 @@ async function processPlanchet( if (withdrawalGroup.withdrawn[coinIdx]) { return; } - if (withdrawalGroup.source.type === "reserve") { - } const planchet = withdrawalGroup.planchets[coinIdx]; if (!planchet) { console.log("processPlanchet: planchet not found"); @@ -248,7 +241,6 @@ async function processPlanchet( }; let withdrawalGroupFinished = false; - let summary: ReserveHistorySummary | undefined = undefined; const success = await ws.db.runWithWriteTransaction( [Stores.coins, Stores.withdrawalGroups, Stores.reserves], @@ -276,12 +268,6 @@ async function processPlanchet( withdrawalGroupFinished = true; } await tx.put(Stores.withdrawalGroups, ws); - if (!planchet.isFromTip) { - const r = await tx.get(Stores.reserves, planchet.reservePub); - if (r) { - summary = summarizeReserveHistory(r.reserveTransactions, r.currency); - } - } await tx.add(Stores.coins, coin); return true; }, @@ -396,7 +382,7 @@ export async function processWithdrawGroup( withdrawalGroupId: string, forceNow = false, ): Promise<void> { - const onOpErr = (e: OperationError) => + const onOpErr = (e: OperationError): Promise<void> => incrementWithdrawalRetry(ws, withdrawalGroupId, e); await guardOperationException( () => processWithdrawGroupImpl(ws, withdrawalGroupId, forceNow), @@ -407,7 +393,7 @@ export async function processWithdrawGroup( async function resetWithdrawalGroupRetry( ws: InternalWalletState, withdrawalGroupId: string, -) { +): Promise<void> { await ws.db.mutate(Stores.withdrawalGroups, withdrawalGroupId, (x) => { if (x.retryInfo.active) { x.retryInfo = initRetryInfo(); diff --git a/src/types/ReserveStatus.ts b/src/types/ReserveStatus.ts index 5a3011b37..18601b9a7 100644 --- a/src/types/ReserveStatus.ts +++ b/src/types/ReserveStatus.ts @@ -51,7 +51,7 @@ export interface ReserveStatus { } export const codecForReserveStatus = (): Codec<ReserveStatus> => - makeCodecForObject<ReserveStatus>() - .property("balance", codecForString) - .property("history", makeCodecForList(codecForReserveTransaction())) - .build("ReserveStatus"); + makeCodecForObject<ReserveStatus>() + .property("balance", codecForString) + .property("history", makeCodecForList(codecForReserveTransaction())) + .build("ReserveStatus"); diff --git a/src/types/ReserveTransaction.ts b/src/types/ReserveTransaction.ts index acbd502ea..bdd9b0f93 100644 --- a/src/types/ReserveTransaction.ts +++ b/src/types/ReserveTransaction.ts @@ -179,67 +179,72 @@ export type ReserveTransaction = | ReserveClosingTransaction | ReserveRecoupTransaction; -export const codecForReserveWithdrawTransaction = (): Codec<ReserveWithdrawTransaction> => - makeCodecForObject<ReserveWithdrawTransaction>() - .property("amount", codecForString) - .property("h_coin_envelope", codecForString) - .property("h_denom_pub", codecForString) - .property("reserve_sig", codecForString) - .property( - "type", - makeCodecForConstString(ReserveTransactionType.Withdraw), - ) - .property("withdraw_fee", codecForString) - .build("ReserveWithdrawTransaction"); - -export const codecForReserveCreditTransaction = (): Codec<ReserveCreditTransaction> => - makeCodecForObject<ReserveCreditTransaction>() - .property("amount", codecForString) - .property("sender_account_url", codecForString) - .property("timestamp", codecForTimestamp) - .property("wire_reference", codecForString) - .property("type", makeCodecForConstString(ReserveTransactionType.Credit)) - .build("ReserveCreditTransaction"); - -export const codecForReserveClosingTransaction = (): Codec<ReserveClosingTransaction> => - makeCodecForObject<ReserveClosingTransaction>() - .property("amount", codecForString) - .property("closing_fee", codecForString) - .property("exchange_pub", codecForString) - .property("exchange_sig", codecForString) - .property("h_wire", codecForString) - .property("timestamp", codecForTimestamp) - .property("type", makeCodecForConstString(ReserveTransactionType.Closing)) - .property("wtid", codecForString) - .build("ReserveClosingTransaction"); - -export const codecForReserveRecoupTransaction = (): Codec<ReserveRecoupTransaction> => - makeCodecForObject<ReserveRecoupTransaction>() - .property("amount", codecForString) - .property("coin_pub", codecForString) - .property("exchange_pub", codecForString) - .property("exchange_sig", codecForString) - .property("timestamp", codecForTimestamp) - .property("type", makeCodecForConstString(ReserveTransactionType.Recoup)) - .build("ReserveRecoupTransaction"); +export const codecForReserveWithdrawTransaction = (): Codec< + ReserveWithdrawTransaction +> => + makeCodecForObject<ReserveWithdrawTransaction>() + .property("amount", codecForString) + .property("h_coin_envelope", codecForString) + .property("h_denom_pub", codecForString) + .property("reserve_sig", codecForString) + .property("type", makeCodecForConstString(ReserveTransactionType.Withdraw)) + .property("withdraw_fee", codecForString) + .build("ReserveWithdrawTransaction"); + +export const codecForReserveCreditTransaction = (): Codec< + ReserveCreditTransaction +> => + makeCodecForObject<ReserveCreditTransaction>() + .property("amount", codecForString) + .property("sender_account_url", codecForString) + .property("timestamp", codecForTimestamp) + .property("wire_reference", codecForString) + .property("type", makeCodecForConstString(ReserveTransactionType.Credit)) + .build("ReserveCreditTransaction"); + +export const codecForReserveClosingTransaction = (): Codec< + ReserveClosingTransaction +> => + makeCodecForObject<ReserveClosingTransaction>() + .property("amount", codecForString) + .property("closing_fee", codecForString) + .property("exchange_pub", codecForString) + .property("exchange_sig", codecForString) + .property("h_wire", codecForString) + .property("timestamp", codecForTimestamp) + .property("type", makeCodecForConstString(ReserveTransactionType.Closing)) + .property("wtid", codecForString) + .build("ReserveClosingTransaction"); + +export const codecForReserveRecoupTransaction = (): Codec< + ReserveRecoupTransaction +> => + makeCodecForObject<ReserveRecoupTransaction>() + .property("amount", codecForString) + .property("coin_pub", codecForString) + .property("exchange_pub", codecForString) + .property("exchange_sig", codecForString) + .property("timestamp", codecForTimestamp) + .property("type", makeCodecForConstString(ReserveTransactionType.Recoup)) + .build("ReserveRecoupTransaction"); export const codecForReserveTransaction = (): Codec<ReserveTransaction> => - makeCodecForUnion<ReserveTransaction>() - .discriminateOn("type") - .alternative( - ReserveTransactionType.Withdraw, - codecForReserveWithdrawTransaction(), - ) - .alternative( - ReserveTransactionType.Closing, - codecForReserveClosingTransaction(), - ) - .alternative( - ReserveTransactionType.Recoup, - codecForReserveRecoupTransaction(), - ) - .alternative( - ReserveTransactionType.Credit, - codecForReserveCreditTransaction(), - ) - .build<ReserveTransaction>("ReserveTransaction"); + makeCodecForUnion<ReserveTransaction>() + .discriminateOn("type") + .alternative( + ReserveTransactionType.Withdraw, + codecForReserveWithdrawTransaction(), + ) + .alternative( + ReserveTransactionType.Closing, + codecForReserveClosingTransaction(), + ) + .alternative( + ReserveTransactionType.Recoup, + codecForReserveRecoupTransaction(), + ) + .alternative( + ReserveTransactionType.Credit, + codecForReserveCreditTransaction(), + ) + .build<ReserveTransaction>("ReserveTransaction"); diff --git a/src/types/dbTypes.ts b/src/types/dbTypes.ts index 434993cb5..009b05315 100644 --- a/src/types/dbTypes.ts +++ b/src/types/dbTypes.ts @@ -43,7 +43,6 @@ import { ReserveRecoupTransaction, } from "./ReserveTransaction"; import { Timestamp, Duration, getTimestampNow } from "../util/time"; -import { Wallet } from "../wallet"; export enum ReserveRecordStatus { /** @@ -1524,6 +1523,7 @@ export class WalletImportRecord { /** * The stores and indices for the wallet database. */ +// eslint-disable-next-line @typescript-eslint/no-namespace export namespace Stores { class ExchangesStore extends Store<ExchangeRecord> { constructor() { diff --git a/src/types/history.ts b/src/types/history.ts index 8179f6261..a5f4e9d3f 100644 --- a/src/types/history.ts +++ b/src/types/history.ts @@ -22,7 +22,6 @@ * Imports. */ import { RefreshReason } from "./walletTypes"; -import { ReserveTransaction } from "./ReserveTransaction"; import { WithdrawalSource } from "./dbTypes"; import { Timestamp } from "../util/time"; diff --git a/src/types/notifications.ts b/src/types/notifications.ts index 05d3c273a..3cd5be898 100644 --- a/src/types/notifications.ts +++ b/src/types/notifications.ts @@ -1,6 +1,3 @@ -import { OperationError } from "./walletTypes"; -import { WithdrawCoinSource, WithdrawalSource } from "./dbTypes"; - /* This file is part of GNU Taler (C) 2019 GNUnet e.V. @@ -22,6 +19,12 @@ import { WithdrawCoinSource, WithdrawalSource } from "./dbTypes"; * of the wallet. */ +/** + * Imports. + */ +import { OperationError } from "./walletTypes"; +import { WithdrawalSource } from "./dbTypes"; + export const enum NotificationType { CoinWithdrawn = "coin-withdrawn", ProposalAccepted = "proposal-accepted", diff --git a/src/types/pending.ts b/src/types/pending.ts index 5bca8c391..4ff82f55e 100644 --- a/src/types/pending.ts +++ b/src/types/pending.ts @@ -25,7 +25,6 @@ import { OperationError, WalletBalance } from "./walletTypes"; import { WithdrawalSource, RetryInfo, ReserveRecordStatus } from "./dbTypes"; import { Timestamp, Duration } from "../util/time"; import { ReserveType } from "./history"; -import { AmountString } from "./talerTypes"; export const enum PendingOperationType { Bug = "bug", diff --git a/src/types/talerTypes.ts b/src/types/talerTypes.ts index 74157b18b..799c84dc5 100644 --- a/src/types/talerTypes.ts +++ b/src/types/talerTypes.ts @@ -963,22 +963,22 @@ export const codecForWithdrawOperationStatusResponse = (): Codec< .build("WithdrawOperationStatusResponse"); export const codecForTipPickupGetResponse = (): Codec<TipPickupGetResponse> => - makeCodecForObject<TipPickupGetResponse>() - .property("extra", codecForAny) - .property("amount", codecForString) - .property("amount_left", codecForString) - .property("exchange_url", codecForString) - .property("stamp_expire", codecForTimestamp) - .property("stamp_created", codecForTimestamp) - .build("TipPickupGetResponse"); + makeCodecForObject<TipPickupGetResponse>() + .property("extra", codecForAny) + .property("amount", codecForString) + .property("amount_left", codecForString) + .property("exchange_url", codecForString) + .property("stamp_expire", codecForTimestamp) + .property("stamp_created", codecForTimestamp) + .build("TipPickupGetResponse"); export const codecForRecoupConfirmation = (): Codec<RecoupConfirmation> => - makeCodecForObject<RecoupConfirmation>() - .property("reserve_pub", makeCodecOptional(codecForString)) - .property("old_coin_pub", makeCodecOptional(codecForString)) - .build("RecoupConfirmation"); + makeCodecForObject<RecoupConfirmation>() + .property("reserve_pub", makeCodecOptional(codecForString)) + .property("old_coin_pub", makeCodecOptional(codecForString)) + .build("RecoupConfirmation"); export const codecForWithdrawResponse = (): Codec<WithdrawResponse> => - makeCodecForObject<WithdrawResponse>() - .property("ev_sig", codecForString) - .build("WithdrawResponse"); + makeCodecForObject<WithdrawResponse>() + .property("ev_sig", codecForString) + .build("WithdrawResponse"); diff --git a/src/types/walletTypes.ts b/src/types/walletTypes.ts index 3d919c6f1..113a137ca 100644 --- a/src/types/walletTypes.ts +++ b/src/types/walletTypes.ts @@ -260,13 +260,13 @@ export interface CreateReserveRequest { } export const codecForCreateReserveRequest = (): Codec<CreateReserveRequest> => - makeCodecForObject<CreateReserveRequest>() - .property("amount", codecForAmountJson()) - .property("exchange", codecForString) - .property("exchangeWire", codecForString) - .property("senderWire", makeCodecOptional(codecForString)) - .property("bankWithdrawStatusUrl", makeCodecOptional(codecForString)) - .build("CreateReserveRequest"); + makeCodecForObject<CreateReserveRequest>() + .property("amount", codecForAmountJson()) + .property("exchange", codecForString) + .property("exchangeWire", codecForString) + .property("senderWire", makeCodecOptional(codecForString)) + .property("bankWithdrawStatusUrl", makeCodecOptional(codecForString)) + .build("CreateReserveRequest"); /** * Request to mark a reserve as confirmed. @@ -280,9 +280,9 @@ export interface ConfirmReserveRequest { } export const codecForConfirmReserveRequest = (): Codec<ConfirmReserveRequest> => - makeCodecForObject<ConfirmReserveRequest>() - .property("reservePub", codecForString) - .build("ConfirmReserveRequest"); + makeCodecForObject<ConfirmReserveRequest>() + .property("reservePub", codecForString) + .build("ConfirmReserveRequest"); /** * Wire coins to the user's own bank account. diff --git a/src/util/RequestThrottler.ts b/src/util/RequestThrottler.ts index c99c7e949..d979fbfcf 100644 --- a/src/util/RequestThrottler.ts +++ b/src/util/RequestThrottler.ts @@ -21,12 +21,7 @@ /** * Imports. */ -import { - getTimestampNow, - Timestamp, - timestampSubtractDuraction, - timestampDifference, -} from "../util/time"; +import { getTimestampNow, timestampDifference } from "../util/time"; /** * Maximum request per second, per origin. diff --git a/src/util/amounts.ts b/src/util/amounts.ts index da1c19233..5953f5130 100644 --- a/src/util/amounts.ts +++ b/src/util/amounts.ts @@ -67,11 +67,11 @@ export interface AmountJson { } export const codecForAmountJson = (): Codec<AmountJson> => - makeCodecForObject<AmountJson>() - .property("currency", codecForString) - .property("value", codecForNumber) - .property("fraction", codecForNumber) - .build("AmountJson"); + makeCodecForObject<AmountJson>() + .property("currency", codecForString) + .property("value", codecForNumber) + .property("fraction", codecForNumber) + .build("AmountJson"); /** * Result of a possibly overflowing operation. diff --git a/src/util/codec.ts b/src/util/codec.ts index 480e1eec7..136c5b053 100644 --- a/src/util/codec.ts +++ b/src/util/codec.ts @@ -346,4 +346,4 @@ export function makeCodecOptional<V>( return innerCodec.decode(x, c); }, }; -}
\ No newline at end of file +} diff --git a/src/util/helpers.ts b/src/util/helpers.ts index 0e19d7aba..7cd9e4234 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -39,7 +39,7 @@ export function amountToPretty(amount: AmountJson): string { * * See http://api.taler.net/wallet.html#general */ -export function canonicalizeBaseUrl(url: string) { +export function canonicalizeBaseUrl(url: string): string { if (!url.startsWith("http") && !url.startsWith("https")) { url = "https://" + url; } @@ -145,13 +145,3 @@ export function strcmp(s1: string, s2: string): number { } return 0; } - -/** - * Run a function and return its result. - * - * Used as a nicer-looking way to do immediately invoked function - * expressions (IFFEs). - */ -export function runBlock<T>(f: () => T) { - return f(); -} diff --git a/src/util/http.ts b/src/util/http.ts index 3842347dc..0ac989a17 100644 --- a/src/util/http.ts +++ b/src/util/http.ts @@ -136,9 +136,13 @@ export class BrowserHttpLib implements HttpRequestLibrary { const headerMap = new Headers(); arr.forEach(function (line) { const parts = line.split(": "); - const header = parts.shift(); + const headerName = parts.shift(); + if (!headerName) { + console.error("invalid header"); + return; + } const value = parts.join(": "); - headerMap.set(header!, value); + headerMap.set(headerName, value); }); const resp: HttpResponse = { status: myRequest.status, @@ -156,7 +160,11 @@ export class BrowserHttpLib implements HttpRequestLibrary { return this.req("get", url, undefined, opt); } - postJson(url: string, body: any, opt?: HttpRequestOptions): Promise<HttpResponse> { + postJson( + url: string, + body: any, + opt?: HttpRequestOptions, + ): Promise<HttpResponse> { return this.req("post", url, JSON.stringify(body), opt); } diff --git a/src/util/query.ts b/src/util/query.ts index 256395d42..8dd3ff1e2 100644 --- a/src/util/query.ts +++ b/src/util/query.ts @@ -292,7 +292,11 @@ export class TransactionHandle { return requestToPromise(req); } - mutate<T>(store: Store<T>, key: any, f: (x: T) => T | undefined): Promise<void> { + mutate<T>( + store: Store<T>, + key: any, + f: (x: T) => T | undefined, + ): Promise<void> { const req = this.tx.objectStore(store.name).openCursor(key); return applyMutation(req, f); } diff --git a/src/util/talerconfig.ts b/src/util/talerconfig.ts index 61c75574f..ec08c352f 100644 --- a/src/util/talerconfig.ts +++ b/src/util/talerconfig.ts @@ -59,8 +59,6 @@ export class ConfigValue<T> { export class Configuration { private sectionMap: SectionMap = {}; - constructor() {} - loadFromString(s: string): void { const reComment = /^\s*#.*$/; const reSection = /^\s*\[\s*([^\]]*)\s*\]\s*$/; diff --git a/src/util/taleruri-test.ts b/src/util/taleruri-test.ts index 9efc1846d..1510880c5 100644 --- a/src/util/taleruri-test.ts +++ b/src/util/taleruri-test.ts @@ -28,7 +28,7 @@ test("taler pay url parsing: wrong scheme", (t) => { t.is(r1, undefined); const url2 = "taler://refund/a/b/c/d/e/f"; - const r2 = parsePayUri(url1); + const r2 = parsePayUri(url2); t.is(r2, undefined); }); diff --git a/src/util/taleruri.ts b/src/util/taleruri.ts index 8ad79669f..46cc199f8 100644 --- a/src/util/taleruri.ts +++ b/src/util/taleruri.ts @@ -97,7 +97,7 @@ export function classifyTalerUri(s: string): TalerUriType { return TalerUriType.Unknown; } -export function getOrderDownloadUrl(merchantBaseUrl: string, orderId: string) { +export function getOrderDownloadUrl(merchantBaseUrl: string, orderId: string): string { const u = new URL("proposal", merchantBaseUrl); u.searchParams.set("order_id", orderId); return u.href; diff --git a/src/util/timer.ts b/src/util/timer.ts index 18132a812..9d743b8e9 100644 --- a/src/util/timer.ts +++ b/src/util/timer.ts @@ -26,7 +26,6 @@ */ import { Duration } from "./time"; - /** * Cancelable timer. */ diff --git a/src/wallet.ts b/src/wallet.ts index 02450523e..273a9f875 100644 --- a/src/wallet.ts +++ b/src/wallet.ts @@ -154,7 +154,10 @@ export class Wallet { this.ws = new InternalWalletState(db, http, cryptoWorkerFactory); } - getExchangePaytoUri(exchangeBaseUrl: string, supportedTargetTypes: string[]): Promise<string> { + getExchangePaytoUri( + exchangeBaseUrl: string, + supportedTargetTypes: string[], + ): Promise<string> { return getExchangePaytoUri(this.ws, exchangeBaseUrl, supportedTargetTypes); } diff --git a/src/webex/compat.ts b/src/webex/compat.ts index f1a68f33e..1cbf34a2c 100644 --- a/src/webex/compat.ts +++ b/src/webex/compat.ts @@ -30,6 +30,6 @@ export function isFirefox(): boolean { /** * Check if we are running under nodejs. */ -export function isNode() { +export function isNode(): boolean { return typeof process !== "undefined" && process.release.name === "node"; } diff --git a/src/webex/i18n.tsx b/src/webex/i18n.tsx index ed6fe868f..3f23267d5 100644 --- a/src/webex/i18n.tsx +++ b/src/webex/i18n.tsx @@ -57,7 +57,7 @@ function setupJed(): any { /** * Convert template strings to a msgid */ -function toI18nString(stringSeq: ReadonlyArray<string>) { +function toI18nString(stringSeq: ReadonlyArray<string>): string { let s = ""; for (let i = 0; i < stringSeq.length; i++) { s += stringSeq[i]; @@ -71,7 +71,7 @@ function toI18nString(stringSeq: ReadonlyArray<string>) { /** * Internationalize a string template with arbitrary serialized values. */ -export function str(stringSeq: TemplateStringsArray, ...values: any[]) { +export function str(stringSeq: TemplateStringsArray, ...values: any[]): string { const s = toI18nString(stringSeq); const tr = jed .translate(s) @@ -226,8 +226,8 @@ export class TranslatePlural extends React.Component< typeof childArray[i] === "string" && typeof childArray[i + 1] === "string" ) { - childArray[i + i] = - ((childArray[i] as string) + childArray[i + 1]) as string; + childArray[i + i] = ((childArray[i] as string) + + childArray[i + 1]) as string; childArray.splice(i, 1); } } @@ -267,8 +267,8 @@ export class TranslateSingular extends React.Component< typeof childArray[i] === "string" && typeof childArray[i + 1] === "string" ) { - childArray[i + i] = - ((childArray[i] as string) + childArray[i + 1]) as string; + childArray[i + i] = ((childArray[i] as string) + + childArray[i + 1]) as string; childArray.splice(i, 1); } } diff --git a/src/webex/messages.ts b/src/webex/messages.ts index b695b4ab6..19d125a89 100644 --- a/src/webex/messages.ts +++ b/src/webex/messages.ts @@ -23,7 +23,6 @@ import { AmountJson } from "../util/amounts"; import * as dbTypes from "../types/dbTypes"; -import * as talerTypes from "../types/talerTypes"; import * as walletTypes from "../types/walletTypes"; import { UpgradeResponse } from "./wxApi"; @@ -172,22 +171,3 @@ export interface MessageMap { */ export type MessageType = keyof MessageMap; -/** - * Make a request whose details match the request type. - */ -export function makeRequest<T extends MessageType>( - type: T, - details: MessageMap[T]["request"], -) { - return { type, details }; -} - -/** - * Make a response that matches the request type. - */ -export function makeResponse<T extends MessageType>( - type: T, - response: MessageMap[T]["response"], -) { - return response; -} diff --git a/src/webex/pageEntryPoint.ts b/src/webex/pageEntryPoint.ts index 04e3dd8d1..dd9c13031 100644 --- a/src/webex/pageEntryPoint.ts +++ b/src/webex/pageEntryPoint.ts @@ -25,7 +25,7 @@ import { createPopup } from "./pages/popup"; import { createWithdrawPage } from "./pages/withdraw"; import { createWelcomePage } from "./pages/welcome"; -function main() { +function main(): void { try { let mainElement; const m = location.pathname.match(/([^/]+)$/); diff --git a/src/webex/pages/add-auditor.tsx b/src/webex/pages/add-auditor.tsx index fc7de920f..c28d15cad 100644 --- a/src/webex/pages/add-auditor.tsx +++ b/src/webex/pages/add-auditor.tsx @@ -91,9 +91,7 @@ function ConfirmAuditor(props: ConfirmAuditorProps): JSX.Element { {addDone ? ( <div> Auditor was added! You can also{" "} - <a href={chrome.extension.getURL("/auditors.html")}> - view and edit - </a>{" "} + <a href={chrome.extension.getURL("/auditors.html")}>view and edit</a>{" "} auditors. </div> ) : ( diff --git a/src/webex/pages/auditors.tsx b/src/webex/pages/auditors.tsx index e933aeace..ac93afd31 100644 --- a/src/webex/pages/auditors.tsx +++ b/src/webex/pages/auditors.tsx @@ -29,7 +29,6 @@ import { import { getCurrencies, updateCurrency } from "../wxApi"; import * as React from "react"; -import * as ReactDOM from "react-dom"; interface CurrencyListState { currencies?: CurrencyRecord[]; @@ -49,13 +48,16 @@ class CurrencyList extends React.Component<{}, CurrencyListState> { this.state = {} as any; } - async update() { + async update(): Promise<void> { const currencies = await getCurrencies(); console.log("currencies: ", currencies); this.setState({ currencies }); } - async confirmRemoveAuditor(c: CurrencyRecord, a: AuditorRecord) { + async confirmRemoveAuditor( + c: CurrencyRecord, + a: AuditorRecord, + ): Promise<void> { if ( window.confirm( `Do you really want to remove auditor ${a.baseUrl} for currency ${c.name}?`, @@ -66,7 +68,10 @@ class CurrencyList extends React.Component<{}, CurrencyListState> { } } - async confirmRemoveExchange(c: CurrencyRecord, e: ExchangeForCurrencyRecord) { + async confirmRemoveExchange( + c: CurrencyRecord, + e: ExchangeForCurrencyRecord, + ): Promise<void> { if ( window.confirm( `Do you really want to remove exchange ${e.baseUrl} for currency ${c.name}?`, @@ -86,7 +91,7 @@ class CurrencyList extends React.Component<{}, CurrencyListState> { <p>Trusted Auditors:</p> <ul> {c.auditors.map((a) => ( - <li> + <li key={a.baseUrl}> {a.baseUrl}{" "} <button className="pure-button button-destructive" @@ -114,7 +119,7 @@ class CurrencyList extends React.Component<{}, CurrencyListState> { <p>Trusted Exchanges:</p> <ul> {c.exchanges.map((e) => ( - <li> + <li key={e.baseUrl}> {e.baseUrl}{" "} <button className="pure-button button-destructive" @@ -137,7 +142,7 @@ class CurrencyList extends React.Component<{}, CurrencyListState> { return ( <div id="main"> {currencies.map((c) => ( - <div> + <div key={c.name}> <h1>Currency {c.name}</h1> <p>Displayed with {c.fractionalDigits} fractional digits.</p> <h2>Auditors</h2> @@ -151,6 +156,6 @@ class CurrencyList extends React.Component<{}, CurrencyListState> { } } -function makeAuditorsPage() { +export function makeAuditorsPage(): JSX.Element { return <CurrencyList />; } diff --git a/src/webex/pages/pay.tsx b/src/webex/pages/pay.tsx index e3dd630b6..61f287708 100644 --- a/src/webex/pages/pay.tsx +++ b/src/webex/pages/pay.tsx @@ -47,7 +47,7 @@ function TalerPayDialog({ talerPayUri }: { talerPayUri: string }): JSX.Element { setPayStatus(p); }; doFetch(); - }, [numTries]); + }, [numTries, talerPayUri]); if (!payStatus) { return <span>Loading payment information ...</span>; diff --git a/src/webex/pages/payback.tsx b/src/webex/pages/payback.tsx index 9c53aac91..5d42f5f47 100644 --- a/src/webex/pages/payback.tsx +++ b/src/webex/pages/payback.tsx @@ -25,6 +25,6 @@ */ import * as React from "react"; -export function makePaybackPage() { +export function makePaybackPage(): JSX.Element { return <div>not implemented</div>; } diff --git a/src/webex/pages/popup.tsx b/src/webex/pages/popup.tsx index f62f64b73..cdb09d444 100644 --- a/src/webex/pages/popup.tsx +++ b/src/webex/pages/popup.tsx @@ -31,11 +31,7 @@ import * as Amounts from "../../util/amounts"; import { WalletBalance, WalletBalanceEntry } from "../../types/walletTypes"; -import { - abbrev, - renderAmount, - PageLink, -} from "../renderHtml"; +import { abbrev, renderAmount, PageLink } from "../renderHtml"; import * as wxApi from "../wxApi"; import React, { Fragment } from "react"; @@ -671,7 +667,7 @@ class WalletHistory extends React.Component<any, any> { console.log("rendering history"); const history: HistoryEvent[] = this.myHistory; if (this.gotError) { - return i18n.str`Error: could not retrieve event history`; + return <span>i18n.str`Error: could not retrieve event history`</span>; } if (!history) { @@ -734,18 +730,10 @@ function WalletDebug(props: any): JSX.Element { return ( <div> <p>Debug tools:</p> - <button onClick={openExtensionPage("/popup.html")}> - wallet tab - </button> - <button onClick={openExtensionPage("/benchmark.html")}> - benchmark - </button> - <button onClick={openExtensionPage("/show-db.html")}> - show db - </button> - <button onClick={openExtensionPage("/tree.html")}> - show tree - </button> + <button onClick={openExtensionPage("/popup.html")}>wallet tab</button> + <button onClick={openExtensionPage("/benchmark.html")}>benchmark</button> + <button onClick={openExtensionPage("/show-db.html")}>show db</button> + <button onClick={openExtensionPage("/tree.html")}>show tree</button> <br /> <button onClick={confirmReset}>reset</button> <button onClick={reload}>reload chrome extension</button> @@ -788,4 +776,4 @@ function WalletPopup(): JSX.Element { export function createPopup(): JSX.Element { chrome.runtime.connect({ name: "popup" }); return <WalletPopup />; -}
\ No newline at end of file +} diff --git a/src/webex/pages/refund.tsx b/src/webex/pages/refund.tsx index 4a13317cd..621a286bb 100644 --- a/src/webex/pages/refund.tsx +++ b/src/webex/pages/refund.tsx @@ -47,7 +47,7 @@ function RefundStatusView(props: { talerRefundUri: string }): JSX.Element { } }; doFetch(); - }, []); + }, [props.talerRefundUri]); console.log("rendering"); @@ -63,7 +63,7 @@ function RefundStatusView(props: { talerRefundUri: string }): JSX.Element { <> <h2>Refund Status</h2> <p> - The product <em>{purchaseDetails.contractTerms.summary!}</em> has + The product <em>{purchaseDetails.contractTerms.summary}</em> has received a total refund of{" "} <AmountView amount={purchaseDetails.totalRefundAmount} />. </p> @@ -77,7 +77,7 @@ export function createRefundPage(): JSX.Element { const container = document.getElementById("container"); if (!container) { - throw Error("fatal: can't mount component, container missing") + throw Error("fatal: can't mount component, container missing"); } const talerRefundUri = url.searchParams.get("talerRefundUri"); diff --git a/src/webex/pages/reset-required.tsx b/src/webex/pages/reset-required.tsx index e58243b34..9e40e7981 100644 --- a/src/webex/pages/reset-required.tsx +++ b/src/webex/pages/reset-required.tsx @@ -42,17 +42,17 @@ class ResetNotification extends React.Component<any, State> { this.state = { checked: false, resetRequired: true }; setInterval(() => this.update(), 500); } - async update() { + async update(): Promise<void> { const res = await wxApi.checkUpgrade(); this.setState({ resetRequired: res.dbResetRequired }); } - render() { + render(): JSX.Element { if (this.state.resetRequired) { return ( <div> <h1>Manual Reset Reqired</h1> <p> - The wallet's database in your browser is incompatible with the{" "} + The wallet's database in your browser is incompatible with the{" "} currently installed wallet. Please reset manually. </p> <p> @@ -88,6 +88,6 @@ class ResetNotification extends React.Component<any, State> { } } -export function createResetRequiredPage() { +export function createResetRequiredPage(): JSX.Element { return <ResetNotification />; } diff --git a/src/webex/pages/return-coins.tsx b/src/webex/pages/return-coins.tsx index 7d759705f..ccdb6db53 100644 --- a/src/webex/pages/return-coins.tsx +++ b/src/webex/pages/return-coins.tsx @@ -290,8 +290,9 @@ class ReturnCoins extends React.Component<{}, ReturnCoinsState> { <div id="main"> <h1>Wire electronic cash back to own bank account</h1> <p> - You can send coins back into your own bank account. Note that you're - acting as a merchant when doing this, and thus the same fees apply. + You can send coins back into your own bank account. Note that + you're acting as a merchant when doing this, and thus the same + fees apply. </p> {this.state.lastConfirmedDetail ? ( <p className="okaybox"> diff --git a/src/webex/pages/tip.tsx b/src/webex/pages/tip.tsx index 9c797f50d..4a1d3743a 100644 --- a/src/webex/pages/tip.tsx +++ b/src/webex/pages/tip.tsx @@ -25,10 +25,7 @@ import * as React from "react"; import { acceptTip, getTipStatus } from "../wxApi"; -import { - renderAmount, - ProgressButton, -} from "../renderHtml"; +import { renderAmount, ProgressButton } from "../renderHtml"; import { useState, useEffect } from "react"; import { TipStatus } from "../../types/walletTypes"; @@ -45,7 +42,7 @@ function TipDisplay(props: { talerTipUri: string }): JSX.Element { setTipStatus(ts); }; doFetch(); - }, []); + }, [props.talerTipUri]); if (discarded) { return <span>You've discarded the tip.</span>; @@ -96,11 +93,11 @@ function TipDisplay(props: { talerTipUri: string }): JSX.Element { } export function createTipPage(): JSX.Element { - const url = new URL(document.location.href); - const talerTipUri = url.searchParams.get("talerTipUri"); - if (typeof talerTipUri !== "string") { - throw Error("talerTipUri must be a string"); - } + const url = new URL(document.location.href); + const talerTipUri = url.searchParams.get("talerTipUri"); + if (typeof talerTipUri !== "string") { + throw Error("talerTipUri must be a string"); + } - return <TipDisplay talerTipUri={talerTipUri} />; + return <TipDisplay talerTipUri={talerTipUri} />; } diff --git a/src/webex/pages/welcome.tsx b/src/webex/pages/welcome.tsx index a99cadb05..eecbe2be5 100644 --- a/src/webex/pages/welcome.tsx +++ b/src/webex/pages/welcome.tsx @@ -69,7 +69,7 @@ function Diagnostics(): JSX.Element { <p>Problems detected:</p> <ol> {diagnostics.errors.map((errMsg) => ( - <li>{errMsg}</li> + <li key={errMsg}>{errMsg}</li> ))} </ol> {diagnostics.firefoxIdbProblem ? ( @@ -112,4 +112,4 @@ function Welcome(): JSX.Element { export function createWelcomePage(): JSX.Element { return <Welcome />; -}
\ No newline at end of file +} diff --git a/src/webex/pages/withdraw.tsx b/src/webex/pages/withdraw.tsx index 9020ddb0b..efd0adc86 100644 --- a/src/webex/pages/withdraw.tsx +++ b/src/webex/pages/withdraw.tsx @@ -30,7 +30,9 @@ import { WithdrawDetailView, renderAmount } from "../renderHtml"; import React, { useState, useEffect } from "react"; import { getWithdrawDetails, acceptWithdrawal } from "../wxApi"; -function NewExchangeSelection(props: { talerWithdrawUri: string }): JSX.Element { +function NewExchangeSelection(props: { + talerWithdrawUri: string; +}): JSX.Element { const [details, setDetails] = useState<WithdrawDetails | undefined>(); const [selectedExchange, setSelectedExchange] = useState< string | undefined @@ -63,7 +65,7 @@ function NewExchangeSelection(props: { talerWithdrawUri: string }): JSX.Element setDetails(d); }; fetchData(); - }, [selectedExchange, errMsg, selecting]); + }, [selectedExchange, errMsg, selecting, talerWithdrawUri]); if (errMsg) { return ( @@ -145,8 +147,11 @@ function NewExchangeSelection(props: { talerWithdrawUri: string }): JSX.Element } const accept = async (): Promise<void> => { + if (!selectedExchange) { + throw Error("can't accept, no exchange selected"); + } console.log("accepting exchange", selectedExchange); - const res = await acceptWithdrawal(talerWithdrawUri, selectedExchange!); + const res = await acceptWithdrawal(talerWithdrawUri, selectedExchange); console.log("accept withdrawal response", res); if (res.confirmTransferUrl) { document.location.href = res.confirmTransferUrl; @@ -198,9 +203,9 @@ function NewExchangeSelection(props: { talerWithdrawUri: string }): JSX.Element export function createWithdrawPage(): JSX.Element { const url = new URL(document.location.href); - const talerWithdrawUri = url.searchParams.get("talerWithdrawUri"); - if (!talerWithdrawUri) { - throw Error("withdraw URI required"); - } - return <NewExchangeSelection talerWithdrawUri={talerWithdrawUri} />; -}
\ No newline at end of file + const talerWithdrawUri = url.searchParams.get("talerWithdrawUri"); + if (!talerWithdrawUri) { + throw Error("withdraw URI required"); + } + return <NewExchangeSelection talerWithdrawUri={talerWithdrawUri} />; +} diff --git a/src/webex/renderHtml.tsx b/src/webex/renderHtml.tsx index f5a6a7e4d..b1363abfb 100644 --- a/src/webex/renderHtml.tsx +++ b/src/webex/renderHtml.tsx @@ -127,6 +127,37 @@ export class Collapsible extends React.Component< } } +function WireFee(props: { + s: string; + rci: ExchangeWithdrawDetails; +}): JSX.Element { + return ( + <> + <thead> + <tr> + <th colSpan={3}>Wire Method {props.s}</th> + </tr> + <tr> + <th>Applies Until</th> + <th>Wire Fee</th> + <th>Closing Fee</th> + </tr> + </thead> + , + <tbody> + {props.rci.wireFees.feesForType[props.s].map((f) => ( + <tr key={f.sig}> + <td>{stringifyTimestamp(f.endStamp)}</td> + <td>{renderAmount(f.wireFee)}</td> + <td>{renderAmount(f.closingFee)}</td> + </tr> + ))} + </tbody> + , + </> + ); +} + function AuditorDetailsView(props: { rci: ExchangeWithdrawDetails | null; }): JSX.Element { @@ -145,7 +176,7 @@ function AuditorDetailsView(props: { return ( <div> {(rci.exchangeInfo.details?.auditors ?? []).map((a) => ( - <div> + <div key={a.auditor_pub}> <h3>Auditor {a.auditor_url}</h3> <p> Public key: <ExpanderText text={a.auditor_pub} /> @@ -202,30 +233,6 @@ function FeeDetailsView(props: { ); } - function wireFee(s: string) { - return [ - <thead> - <tr> - <th colSpan={3}>Wire Method {s}</th> - </tr> - <tr> - <th>Applies Until</th> - <th>Wire Fee</th> - <th>Closing Fee</th> - </tr> - </thead>, - <tbody> - {rci!.wireFees.feesForType[s].map((f) => ( - <tr> - <td>{stringifyTimestamp(f.endStamp)}</td> - <td>{renderAmount(f.wireFee)}</td> - <td>{renderAmount(f.closingFee)}</td> - </tr> - ))} - </tbody>, - ]; - } - const withdrawFee = renderAmount(rci.withdrawFee); const overhead = renderAmount(rci.overhead); @@ -265,7 +272,9 @@ function FeeDetailsView(props: { <h3>Wire Fees</h3> <div style={{ overflow: "auto" }}> <table className="pure-table"> - {Object.keys(rci.wireFees.feesForType).map(wireFee)} + {Object.keys(rci.wireFees.feesForType).map((s) => ( + <WireFee key={s} s={s} rci={rci} /> + ))} </table> </div> </div> @@ -337,7 +346,12 @@ export function PageLink( ): JSX.Element { const url = chrome.extension.getURL(`/${props.pageName}`); return ( - <a className="actionLink" href={url} target="_blank" rel="noopener noreferrer"> + <a + className="actionLink" + href={url} + target="_blank" + rel="noopener noreferrer" + > {props.children} </a> ); |