gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] 03/05: make linter less grumpy


From: gnunet
Subject: [taler-wallet-core] 03/05: make linter less grumpy
Date: Tue, 07 Apr 2020 10:12:22 +0200

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository wallet-core.

commit 47787c0b0b846d5f4a057661efdd05d8786032f1
Author: Florian Dold <address@hidden>
AuthorDate: Mon Apr 6 23:32:01 2020 +0530

    make linter less grumpy
---
 .eslintrc.js                       |   29 +-
 Makefile                           |    3 +
 src/crypto/primitives/nacl-fast.ts | 1362 +++---------------------------------
 src/operations/pay.ts              |   10 +-
 src/operations/refund.ts           |   16 +-
 src/types/ReserveStatus.ts         |   10 +-
 src/types/ReserveTransaction.ts    |   32 +-
 src/types/talerTypes.ts            |  410 +++++------
 src/types/walletTypes.ts           |   16 +-
 src/util/amounts.ts                |   12 +-
 src/util/asyncMemo.ts              |    8 +-
 src/util/codec.ts                  |    6 +-
 src/util/http.ts                   |    8 +-
 src/util/logging.ts                |   10 +-
 src/util/query.ts                  |   10 +-
 src/util/time.ts                   |    6 +-
 src/wallet-test.ts                 |    3 -
 src/wallet.ts                      |   13 +-
 src/webex/chromeBadge.ts           |   22 +-
 src/webex/notify.ts                |   16 +-
 src/webex/pages/add-auditor.tsx    |    4 +-
 src/webex/pages/benchmark.tsx      |   10 +-
 src/webex/pages/pay.tsx            |   10 +-
 src/webex/pages/popup.tsx          |   68 +-
 src/webex/pages/refund.tsx         |   13 +-
 src/webex/pages/return-coins.tsx   |   17 +-
 src/webex/pages/tip.tsx            |   19 +-
 src/webex/pages/welcome.tsx        |    8 +-
 src/webex/pages/withdraw.tsx       |   29 +-
 src/webex/renderHtml.tsx           |   28 +-
 src/webex/wxApi.ts                 |   11 +-
 src/webex/wxBackend.ts             |   89 +--
 32 files changed, 528 insertions(+), 1780 deletions(-)

diff --git a/.eslintrc.js b/.eslintrc.js
index acc5305f..c3e58825 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,13 +1,26 @@
 module.exports = {
   root: true,
-  parser: '@typescript-eslint/parser',
-  plugins: [
-    '@typescript-eslint',
-  ],
+  parser: "@typescript-eslint/parser",
+  plugins: ["@typescript-eslint"],
   extends: [
-    'eslint:recommended',
-    'plugin:@typescript-eslint/eslint-recommended',
-    'plugin:@typescript-eslint/recommended',
+    "eslint:recommended",
+    "plugin:@typescript-eslint/eslint-recommended",
+    "plugin:@typescript-eslint/recommended",
+    "plugin:react/recommended",
   ],
-  rules: {},
+  rules: {
+    "no-constant-condition": ["error", { "checkLoops": false }],
+    "prefer-const": ["warn", { destructuring: "all" }],
+    "@typescript-eslint/camelcase": "off",
+    "@typescript-eslint/no-explicit-any": "off",
+    "@typescript-eslint/no-unused-vars": ["warn", { args: "none" }],
+    "@typescript-eslint/explicit-function-return-type": [
+      "warn",
+      { allowExpressions: true },
+    ],
+    "@typescript-eslint/no-use-before-define": [
+      "error",
+      { functions: false, classes: false },
+    ],
+  },
 };
diff --git a/Makefile b/Makefile
index 0be32c4b..873282ec 100644
--- a/Makefile
+++ b/Makefile
@@ -84,3 +84,6 @@ endif
 rollup: tsc
        ./node_modules/.bin/rollup -c
 
+.PHONY: lint
+lint:
+       ./node_modules/.bin/eslint 'src/**/*'
diff --git a/src/crypto/primitives/nacl-fast.ts 
b/src/crypto/primitives/nacl-fast.ts
index 1defe1ad..8d4aaeb6 100644
--- a/src/crypto/primitives/nacl-fast.ts
+++ b/src/crypto/primitives/nacl-fast.ts
@@ -5,7 +5,7 @@
 // Implementation derived from TweetNaCl version 20140427.
 // See for details: http://tweetnacl.cr.yp.to/
 
-const gf = function (init: number[] = []) {
+const gf = function (init: number[] = []): Float64Array {
   const r = new Float64Array(16);
   if (init) for (let i = 0; i < init.length; i++) r[i] = init[i];
   return r;
@@ -16,7 +16,6 @@ let randombytes = function (x: Uint8Array, n: number): void {
   throw new Error("no PRNG");
 };
 
-const _0 = new Uint8Array(16);
 const _9 = new Uint8Array(32);
 _9[0] = 9;
 
@@ -115,7 +114,7 @@ const I = gf([
   0x2b83,
 ]);
 
-function ts64(x: Uint8Array, i: number, h: number, l: number) {
+function ts64(x: Uint8Array, i: number, h: number, l: number): void {
   x[i] = (h >> 24) & 0xff;
   x[i + 1] = (h >> 16) & 0xff;
   x[i + 2] = (h >> 8) & 0xff;
@@ -126,20 +125,17 @@ function ts64(x: Uint8Array, i: number, h: number, l: 
number) {
   x[i + 7] = l & 0xff;
 }
 
-function vn(x: Uint8Array, xi: number, y: Uint8Array, yi: number, n: number) {
-  let i,
-    d = 0;
-  for (i = 0; i < n; i++) d |= x[xi + i] ^ y[yi + i];
-  return (1 & ((d - 1) >>> 8)) - 1;
-}
-
-function crypto_verify_16(
+function vn(
   x: Uint8Array,
   xi: number,
   y: Uint8Array,
   yi: number,
-) {
-  return vn(x, xi, y, yi, 16);
+  n: number,
+): number {
+  let i,
+    d = 0;
+  for (i = 0; i < n; i++) d |= x[xi + i] ^ y[yi + i];
+  return (1 & ((d - 1) >>> 8)) - 1;
 }
 
 function crypto_verify_32(
@@ -147,1014 +143,16 @@ function crypto_verify_32(
   xi: number,
   y: Uint8Array,
   yi: number,
-) {
+): number {
   return vn(x, xi, y, yi, 32);
 }
 
-// prettier-ignore
-function core_salsa20(o: Uint8Array, p: Uint8Array, k: Uint8Array, c: 
Uint8Array) {
-  const j0  = c[ 0] & 0xff | (c[ 1] & 0xff)<<8 | (c[ 2] & 0xff)<<16 | (c[ 3] & 
0xff)<<24,
-      j1  = k[ 0] & 0xff | (k[ 1] & 0xff)<<8 | (k[ 2] & 0xff)<<16 | (k[ 3] & 
0xff)<<24,
-      j2  = k[ 4] & 0xff | (k[ 5] & 0xff)<<8 | (k[ 6] & 0xff)<<16 | (k[ 7] & 
0xff)<<24,
-      j3  = k[ 8] & 0xff | (k[ 9] & 0xff)<<8 | (k[10] & 0xff)<<16 | (k[11] & 
0xff)<<24,
-      j4  = k[12] & 0xff | (k[13] & 0xff)<<8 | (k[14] & 0xff)<<16 | (k[15] & 
0xff)<<24,
-      j5  = c[ 4] & 0xff | (c[ 5] & 0xff)<<8 | (c[ 6] & 0xff)<<16 | (c[ 7] & 
0xff)<<24,
-      j6  = p[ 0] & 0xff | (p[ 1] & 0xff)<<8 | (p[ 2] & 0xff)<<16 | (p[ 3] & 
0xff)<<24,
-      j7  = p[ 4] & 0xff | (p[ 5] & 0xff)<<8 | (p[ 6] & 0xff)<<16 | (p[ 7] & 
0xff)<<24,
-      j8  = p[ 8] & 0xff | (p[ 9] & 0xff)<<8 | (p[10] & 0xff)<<16 | (p[11] & 
0xff)<<24,
-      j9  = p[12] & 0xff | (p[13] & 0xff)<<8 | (p[14] & 0xff)<<16 | (p[15] & 
0xff)<<24,
-      j10 = c[ 8] & 0xff | (c[ 9] & 0xff)<<8 | (c[10] & 0xff)<<16 | (c[11] & 
0xff)<<24,
-      j11 = k[16] & 0xff | (k[17] & 0xff)<<8 | (k[18] & 0xff)<<16 | (k[19] & 
0xff)<<24,
-      j12 = k[20] & 0xff | (k[21] & 0xff)<<8 | (k[22] & 0xff)<<16 | (k[23] & 
0xff)<<24,
-      j13 = k[24] & 0xff | (k[25] & 0xff)<<8 | (k[26] & 0xff)<<16 | (k[27] & 
0xff)<<24,
-      j14 = k[28] & 0xff | (k[29] & 0xff)<<8 | (k[30] & 0xff)<<16 | (k[31] & 
0xff)<<24,
-      j15 = c[12] & 0xff | (c[13] & 0xff)<<8 | (c[14] & 0xff)<<16 | (c[15] & 
0xff)<<24;
-
-  let x0 = j0, x1 = j1, x2 = j2, x3 = j3, x4 = j4, x5 = j5, x6 = j6, x7 = j7,
-      x8 = j8, x9 = j9, x10 = j10, x11 = j11, x12 = j12, x13 = j13, x14 = j14,
-      x15 = j15, u;
-
-  for (let i = 0; i < 20; i += 2) {
-    u = x0 + x12 | 0;
-    x4 ^= u<<7 | u>>>(32-7);
-    u = x4 + x0 | 0;
-    x8 ^= u<<9 | u>>>(32-9);
-    u = x8 + x4 | 0;
-    x12 ^= u<<13 | u>>>(32-13);
-    u = x12 + x8 | 0;
-    x0 ^= u<<18 | u>>>(32-18);
-
-    u = x5 + x1 | 0;
-    x9 ^= u<<7 | u>>>(32-7);
-    u = x9 + x5 | 0;
-    x13 ^= u<<9 | u>>>(32-9);
-    u = x13 + x9 | 0;
-    x1 ^= u<<13 | u>>>(32-13);
-    u = x1 + x13 | 0;
-    x5 ^= u<<18 | u>>>(32-18);
-
-    u = x10 + x6 | 0;
-    x14 ^= u<<7 | u>>>(32-7);
-    u = x14 + x10 | 0;
-    x2 ^= u<<9 | u>>>(32-9);
-    u = x2 + x14 | 0;
-    x6 ^= u<<13 | u>>>(32-13);
-    u = x6 + x2 | 0;
-    x10 ^= u<<18 | u>>>(32-18);
-
-    u = x15 + x11 | 0;
-    x3 ^= u<<7 | u>>>(32-7);
-    u = x3 + x15 | 0;
-    x7 ^= u<<9 | u>>>(32-9);
-    u = x7 + x3 | 0;
-    x11 ^= u<<13 | u>>>(32-13);
-    u = x11 + x7 | 0;
-    x15 ^= u<<18 | u>>>(32-18);
-
-    u = x0 + x3 | 0;
-    x1 ^= u<<7 | u>>>(32-7);
-    u = x1 + x0 | 0;
-    x2 ^= u<<9 | u>>>(32-9);
-    u = x2 + x1 | 0;
-    x3 ^= u<<13 | u>>>(32-13);
-    u = x3 + x2 | 0;
-    x0 ^= u<<18 | u>>>(32-18);
-
-    u = x5 + x4 | 0;
-    x6 ^= u<<7 | u>>>(32-7);
-    u = x6 + x5 | 0;
-    x7 ^= u<<9 | u>>>(32-9);
-    u = x7 + x6 | 0;
-    x4 ^= u<<13 | u>>>(32-13);
-    u = x4 + x7 | 0;
-    x5 ^= u<<18 | u>>>(32-18);
-
-    u = x10 + x9 | 0;
-    x11 ^= u<<7 | u>>>(32-7);
-    u = x11 + x10 | 0;
-    x8 ^= u<<9 | u>>>(32-9);
-    u = x8 + x11 | 0;
-    x9 ^= u<<13 | u>>>(32-13);
-    u = x9 + x8 | 0;
-    x10 ^= u<<18 | u>>>(32-18);
-
-    u = x15 + x14 | 0;
-    x12 ^= u<<7 | u>>>(32-7);
-    u = x12 + x15 | 0;
-    x13 ^= u<<9 | u>>>(32-9);
-    u = x13 + x12 | 0;
-    x14 ^= u<<13 | u>>>(32-13);
-    u = x14 + x13 | 0;
-    x15 ^= u<<18 | u>>>(32-18);
-  }
-   x0 =  x0 +  j0 | 0;
-   x1 =  x1 +  j1 | 0;
-   x2 =  x2 +  j2 | 0;
-   x3 =  x3 +  j3 | 0;
-   x4 =  x4 +  j4 | 0;
-   x5 =  x5 +  j5 | 0;
-   x6 =  x6 +  j6 | 0;
-   x7 =  x7 +  j7 | 0;
-   x8 =  x8 +  j8 | 0;
-   x9 =  x9 +  j9 | 0;
-  x10 = x10 + j10 | 0;
-  x11 = x11 + j11 | 0;
-  x12 = x12 + j12 | 0;
-  x13 = x13 + j13 | 0;
-  x14 = x14 + j14 | 0;
-  x15 = x15 + j15 | 0;
-
-  o[ 0] = x0 >>>  0 & 0xff;
-  o[ 1] = x0 >>>  8 & 0xff;
-  o[ 2] = x0 >>> 16 & 0xff;
-  o[ 3] = x0 >>> 24 & 0xff;
-
-  o[ 4] = x1 >>>  0 & 0xff;
-  o[ 5] = x1 >>>  8 & 0xff;
-  o[ 6] = x1 >>> 16 & 0xff;
-  o[ 7] = x1 >>> 24 & 0xff;
-
-  o[ 8] = x2 >>>  0 & 0xff;
-  o[ 9] = x2 >>>  8 & 0xff;
-  o[10] = x2 >>> 16 & 0xff;
-  o[11] = x2 >>> 24 & 0xff;
-
-  o[12] = x3 >>>  0 & 0xff;
-  o[13] = x3 >>>  8 & 0xff;
-  o[14] = x3 >>> 16 & 0xff;
-  o[15] = x3 >>> 24 & 0xff;
-
-  o[16] = x4 >>>  0 & 0xff;
-  o[17] = x4 >>>  8 & 0xff;
-  o[18] = x4 >>> 16 & 0xff;
-  o[19] = x4 >>> 24 & 0xff;
-
-  o[20] = x5 >>>  0 & 0xff;
-  o[21] = x5 >>>  8 & 0xff;
-  o[22] = x5 >>> 16 & 0xff;
-  o[23] = x5 >>> 24 & 0xff;
-
-  o[24] = x6 >>>  0 & 0xff;
-  o[25] = x6 >>>  8 & 0xff;
-  o[26] = x6 >>> 16 & 0xff;
-  o[27] = x6 >>> 24 & 0xff;
-
-  o[28] = x7 >>>  0 & 0xff;
-  o[29] = x7 >>>  8 & 0xff;
-  o[30] = x7 >>> 16 & 0xff;
-  o[31] = x7 >>> 24 & 0xff;
-
-  o[32] = x8 >>>  0 & 0xff;
-  o[33] = x8 >>>  8 & 0xff;
-  o[34] = x8 >>> 16 & 0xff;
-  o[35] = x8 >>> 24 & 0xff;
-
-  o[36] = x9 >>>  0 & 0xff;
-  o[37] = x9 >>>  8 & 0xff;
-  o[38] = x9 >>> 16 & 0xff;
-  o[39] = x9 >>> 24 & 0xff;
-
-  o[40] = x10 >>>  0 & 0xff;
-  o[41] = x10 >>>  8 & 0xff;
-  o[42] = x10 >>> 16 & 0xff;
-  o[43] = x10 >>> 24 & 0xff;
-
-  o[44] = x11 >>>  0 & 0xff;
-  o[45] = x11 >>>  8 & 0xff;
-  o[46] = x11 >>> 16 & 0xff;
-  o[47] = x11 >>> 24 & 0xff;
-
-  o[48] = x12 >>>  0 & 0xff;
-  o[49] = x12 >>>  8 & 0xff;
-  o[50] = x12 >>> 16 & 0xff;
-  o[51] = x12 >>> 24 & 0xff;
-
-  o[52] = x13 >>>  0 & 0xff;
-  o[53] = x13 >>>  8 & 0xff;
-  o[54] = x13 >>> 16 & 0xff;
-  o[55] = x13 >>> 24 & 0xff;
-
-  o[56] = x14 >>>  0 & 0xff;
-  o[57] = x14 >>>  8 & 0xff;
-  o[58] = x14 >>> 16 & 0xff;
-  o[59] = x14 >>> 24 & 0xff;
-
-  o[60] = x15 >>>  0 & 0xff;
-  o[61] = x15 >>>  8 & 0xff;
-  o[62] = x15 >>> 16 & 0xff;
-  o[63] = x15 >>> 24 & 0xff;
-}
-
-function core_hsalsa20(
-  o: Uint8Array,
-  p: Uint8Array,
-  k: Uint8Array,
-  c: Uint8Array,
-) {
-  const j0 =
-      (c[0] & 0xff) |
-      ((c[1] & 0xff) << 8) |
-      ((c[2] & 0xff) << 16) |
-      ((c[3] & 0xff) << 24),
-    j1 =
-      (k[0] & 0xff) |
-      ((k[1] & 0xff) << 8) |
-      ((k[2] & 0xff) << 16) |
-      ((k[3] & 0xff) << 24),
-    j2 =
-      (k[4] & 0xff) |
-      ((k[5] & 0xff) << 8) |
-      ((k[6] & 0xff) << 16) |
-      ((k[7] & 0xff) << 24),
-    j3 =
-      (k[8] & 0xff) |
-      ((k[9] & 0xff) << 8) |
-      ((k[10] & 0xff) << 16) |
-      ((k[11] & 0xff) << 24),
-    j4 =
-      (k[12] & 0xff) |
-      ((k[13] & 0xff) << 8) |
-      ((k[14] & 0xff) << 16) |
-      ((k[15] & 0xff) << 24),
-    j5 =
-      (c[4] & 0xff) |
-      ((c[5] & 0xff) << 8) |
-      ((c[6] & 0xff) << 16) |
-      ((c[7] & 0xff) << 24),
-    j6 =
-      (p[0] & 0xff) |
-      ((p[1] & 0xff) << 8) |
-      ((p[2] & 0xff) << 16) |
-      ((p[3] & 0xff) << 24),
-    j7 =
-      (p[4] & 0xff) |
-      ((p[5] & 0xff) << 8) |
-      ((p[6] & 0xff) << 16) |
-      ((p[7] & 0xff) << 24),
-    j8 =
-      (p[8] & 0xff) |
-      ((p[9] & 0xff) << 8) |
-      ((p[10] & 0xff) << 16) |
-      ((p[11] & 0xff) << 24),
-    j9 =
-      (p[12] & 0xff) |
-      ((p[13] & 0xff) << 8) |
-      ((p[14] & 0xff) << 16) |
-      ((p[15] & 0xff) << 24),
-    j10 =
-      (c[8] & 0xff) |
-      ((c[9] & 0xff) << 8) |
-      ((c[10] & 0xff) << 16) |
-      ((c[11] & 0xff) << 24),
-    j11 =
-      (k[16] & 0xff) |
-      ((k[17] & 0xff) << 8) |
-      ((k[18] & 0xff) << 16) |
-      ((k[19] & 0xff) << 24),
-    j12 =
-      (k[20] & 0xff) |
-      ((k[21] & 0xff) << 8) |
-      ((k[22] & 0xff) << 16) |
-      ((k[23] & 0xff) << 24),
-    j13 =
-      (k[24] & 0xff) |
-      ((k[25] & 0xff) << 8) |
-      ((k[26] & 0xff) << 16) |
-      ((k[27] & 0xff) << 24),
-    j14 =
-      (k[28] & 0xff) |
-      ((k[29] & 0xff) << 8) |
-      ((k[30] & 0xff) << 16) |
-      ((k[31] & 0xff) << 24),
-    j15 =
-      (c[12] & 0xff) |
-      ((c[13] & 0xff) << 8) |
-      ((c[14] & 0xff) << 16) |
-      ((c[15] & 0xff) << 24);
-
-  let x0 = j0,
-    x1 = j1,
-    x2 = j2,
-    x3 = j3,
-    x4 = j4,
-    x5 = j5,
-    x6 = j6,
-    x7 = j7,
-    x8 = j8,
-    x9 = j9,
-    x10 = j10,
-    x11 = j11,
-    x12 = j12,
-    x13 = j13,
-    x14 = j14,
-    x15 = j15,
-    u;
-
-  for (let i = 0; i < 20; i += 2) {
-    u = (x0 + x12) | 0;
-    x4 ^= (u << 7) | (u >>> (32 - 7));
-    u = (x4 + x0) | 0;
-    x8 ^= (u << 9) | (u >>> (32 - 9));
-    u = (x8 + x4) | 0;
-    x12 ^= (u << 13) | (u >>> (32 - 13));
-    u = (x12 + x8) | 0;
-    x0 ^= (u << 18) | (u >>> (32 - 18));
-
-    u = (x5 + x1) | 0;
-    x9 ^= (u << 7) | (u >>> (32 - 7));
-    u = (x9 + x5) | 0;
-    x13 ^= (u << 9) | (u >>> (32 - 9));
-    u = (x13 + x9) | 0;
-    x1 ^= (u << 13) | (u >>> (32 - 13));
-    u = (x1 + x13) | 0;
-    x5 ^= (u << 18) | (u >>> (32 - 18));
-
-    u = (x10 + x6) | 0;
-    x14 ^= (u << 7) | (u >>> (32 - 7));
-    u = (x14 + x10) | 0;
-    x2 ^= (u << 9) | (u >>> (32 - 9));
-    u = (x2 + x14) | 0;
-    x6 ^= (u << 13) | (u >>> (32 - 13));
-    u = (x6 + x2) | 0;
-    x10 ^= (u << 18) | (u >>> (32 - 18));
-
-    u = (x15 + x11) | 0;
-    x3 ^= (u << 7) | (u >>> (32 - 7));
-    u = (x3 + x15) | 0;
-    x7 ^= (u << 9) | (u >>> (32 - 9));
-    u = (x7 + x3) | 0;
-    x11 ^= (u << 13) | (u >>> (32 - 13));
-    u = (x11 + x7) | 0;
-    x15 ^= (u << 18) | (u >>> (32 - 18));
-
-    u = (x0 + x3) | 0;
-    x1 ^= (u << 7) | (u >>> (32 - 7));
-    u = (x1 + x0) | 0;
-    x2 ^= (u << 9) | (u >>> (32 - 9));
-    u = (x2 + x1) | 0;
-    x3 ^= (u << 13) | (u >>> (32 - 13));
-    u = (x3 + x2) | 0;
-    x0 ^= (u << 18) | (u >>> (32 - 18));
-
-    u = (x5 + x4) | 0;
-    x6 ^= (u << 7) | (u >>> (32 - 7));
-    u = (x6 + x5) | 0;
-    x7 ^= (u << 9) | (u >>> (32 - 9));
-    u = (x7 + x6) | 0;
-    x4 ^= (u << 13) | (u >>> (32 - 13));
-    u = (x4 + x7) | 0;
-    x5 ^= (u << 18) | (u >>> (32 - 18));
-
-    u = (x10 + x9) | 0;
-    x11 ^= (u << 7) | (u >>> (32 - 7));
-    u = (x11 + x10) | 0;
-    x8 ^= (u << 9) | (u >>> (32 - 9));
-    u = (x8 + x11) | 0;
-    x9 ^= (u << 13) | (u >>> (32 - 13));
-    u = (x9 + x8) | 0;
-    x10 ^= (u << 18) | (u >>> (32 - 18));
-
-    u = (x15 + x14) | 0;
-    x12 ^= (u << 7) | (u >>> (32 - 7));
-    u = (x12 + x15) | 0;
-    x13 ^= (u << 9) | (u >>> (32 - 9));
-    u = (x13 + x12) | 0;
-    x14 ^= (u << 13) | (u >>> (32 - 13));
-    u = (x14 + x13) | 0;
-    x15 ^= (u << 18) | (u >>> (32 - 18));
-  }
-
-  o[0] = (x0 >>> 0) & 0xff;
-  o[1] = (x0 >>> 8) & 0xff;
-  o[2] = (x0 >>> 16) & 0xff;
-  o[3] = (x0 >>> 24) & 0xff;
-
-  o[4] = (x5 >>> 0) & 0xff;
-  o[5] = (x5 >>> 8) & 0xff;
-  o[6] = (x5 >>> 16) & 0xff;
-  o[7] = (x5 >>> 24) & 0xff;
-
-  o[8] = (x10 >>> 0) & 0xff;
-  o[9] = (x10 >>> 8) & 0xff;
-  o[10] = (x10 >>> 16) & 0xff;
-  o[11] = (x10 >>> 24) & 0xff;
-
-  o[12] = (x15 >>> 0) & 0xff;
-  o[13] = (x15 >>> 8) & 0xff;
-  o[14] = (x15 >>> 16) & 0xff;
-  o[15] = (x15 >>> 24) & 0xff;
-
-  o[16] = (x6 >>> 0) & 0xff;
-  o[17] = (x6 >>> 8) & 0xff;
-  o[18] = (x6 >>> 16) & 0xff;
-  o[19] = (x6 >>> 24) & 0xff;
-
-  o[20] = (x7 >>> 0) & 0xff;
-  o[21] = (x7 >>> 8) & 0xff;
-  o[22] = (x7 >>> 16) & 0xff;
-  o[23] = (x7 >>> 24) & 0xff;
-
-  o[24] = (x8 >>> 0) & 0xff;
-  o[25] = (x8 >>> 8) & 0xff;
-  o[26] = (x8 >>> 16) & 0xff;
-  o[27] = (x8 >>> 24) & 0xff;
-
-  o[28] = (x9 >>> 0) & 0xff;
-  o[29] = (x9 >>> 8) & 0xff;
-  o[30] = (x9 >>> 16) & 0xff;
-  o[31] = (x9 >>> 24) & 0xff;
-}
-
-function crypto_core_salsa20(
-  out: Uint8Array,
-  inp: Uint8Array,
-  k: Uint8Array,
-  c: Uint8Array,
-) {
-  core_salsa20(out, inp, k, c);
-}
-
-function crypto_core_hsalsa20(
-  out: Uint8Array,
-  inp: Uint8Array,
-  k: Uint8Array,
-  c: Uint8Array,
-) {
-  core_hsalsa20(out, inp, k, c);
-}
-
-const sigma = new Uint8Array([
-  101,
-  120,
-  112,
-  97,
-  110,
-  100,
-  32,
-  51,
-  50,
-  45,
-  98,
-  121,
-  116,
-  101,
-  32,
-  107,
-]);
-// "expand 32-byte k"
-
-function crypto_stream_salsa20_xor(
-  c: Uint8Array,
-  cpos: number,
-  m: Uint8Array,
-  mpos: number,
-  b: number,
-  n: Uint8Array,
-  k: Uint8Array,
-) {
-  const z = new Uint8Array(16),
-    x = new Uint8Array(64);
-  let u, i;
-  for (i = 0; i < 16; i++) z[i] = 0;
-  for (i = 0; i < 8; i++) z[i] = n[i];
-  while (b >= 64) {
-    crypto_core_salsa20(x, z, k, sigma);
-    for (i = 0; i < 64; i++) c[cpos + i] = m[mpos + i] ^ x[i];
-    u = 1;
-    for (i = 8; i < 16; i++) {
-      u = (u + (z[i] & 0xff)) | 0;
-      z[i] = u & 0xff;
-      u >>>= 8;
-    }
-    b -= 64;
-    cpos += 64;
-    mpos += 64;
-  }
-  if (b > 0) {
-    crypto_core_salsa20(x, z, k, sigma);
-    for (i = 0; i < b; i++) c[cpos + i] = m[mpos + i] ^ x[i];
-  }
-  return 0;
-}
-
-function crypto_stream_salsa20(
-  c: Uint8Array,
-  cpos: number,
-  b: number,
-  n: Uint8Array,
-  k: Uint8Array,
-) {
-  const z = new Uint8Array(16),
-    x = new Uint8Array(64);
-  let u, i;
-  for (i = 0; i < 16; i++) z[i] = 0;
-  for (i = 0; i < 8; i++) z[i] = n[i];
-  while (b >= 64) {
-    crypto_core_salsa20(x, z, k, sigma);
-    for (i = 0; i < 64; i++) c[cpos + i] = x[i];
-    u = 1;
-    for (i = 8; i < 16; i++) {
-      u = (u + (z[i] & 0xff)) | 0;
-      z[i] = u & 0xff;
-      u >>>= 8;
-    }
-    b -= 64;
-    cpos += 64;
-  }
-  if (b > 0) {
-    crypto_core_salsa20(x, z, k, sigma);
-    for (i = 0; i < b; i++) c[cpos + i] = x[i];
-  }
-  return 0;
-}
-
-function crypto_stream(
-  c: Uint8Array,
-  cpos: number,
-  d: number,
-  n: Uint8Array,
-  k: Uint8Array,
-) {
-  const s = new Uint8Array(32);
-  crypto_core_hsalsa20(s, n, k, sigma);
-  const sn = new Uint8Array(8);
-  for (let i = 0; i < 8; i++) sn[i] = n[i + 16];
-  return crypto_stream_salsa20(c, cpos, d, sn, s);
-}
-
-function crypto_stream_xor(
-  c: Uint8Array,
-  cpos: number,
-  m: Uint8Array,
-  mpos: number,
-  d: number,
-  n: Uint8Array,
-  k: Uint8Array,
-) {
-  const s = new Uint8Array(32);
-  crypto_core_hsalsa20(s, n, k, sigma);
-  const sn = new Uint8Array(8);
-  for (let i = 0; i < 8; i++) sn[i] = n[i + 16];
-  return crypto_stream_salsa20_xor(c, cpos, m, mpos, d, sn, s);
-}
-
-/*
- * Port of Andrew Moon's Poly1305-donna-16. Public domain.
- * https://github.com/floodyberry/poly1305-donna
- */
-
-class poly1305 {
-  buffer = new Uint8Array(16);
-  r = new Uint16Array(10);
-  h = new Uint16Array(10);
-  pad = new Uint16Array(8);
-  leftover = 0;
-  fin = 0;
-
-  constructor(key: Uint8Array) {
-    let t0, t1, t2, t3, t4, t5, t6, t7;
-
-    t0 = (key[0] & 0xff) | ((key[1] & 0xff) << 8);
-    this.r[0] = t0 & 0x1fff;
-    t1 = (key[2] & 0xff) | ((key[3] & 0xff) << 8);
-    this.r[1] = ((t0 >>> 13) | (t1 << 3)) & 0x1fff;
-    t2 = (key[4] & 0xff) | ((key[5] & 0xff) << 8);
-    this.r[2] = ((t1 >>> 10) | (t2 << 6)) & 0x1f03;
-    t3 = (key[6] & 0xff) | ((key[7] & 0xff) << 8);
-    this.r[3] = ((t2 >>> 7) | (t3 << 9)) & 0x1fff;
-    t4 = (key[8] & 0xff) | ((key[9] & 0xff) << 8);
-    this.r[4] = ((t3 >>> 4) | (t4 << 12)) & 0x00ff;
-    this.r[5] = (t4 >>> 1) & 0x1ffe;
-    t5 = (key[10] & 0xff) | ((key[11] & 0xff) << 8);
-    this.r[6] = ((t4 >>> 14) | (t5 << 2)) & 0x1fff;
-    t6 = (key[12] & 0xff) | ((key[13] & 0xff) << 8);
-    this.r[7] = ((t5 >>> 11) | (t6 << 5)) & 0x1f81;
-    t7 = (key[14] & 0xff) | ((key[15] & 0xff) << 8);
-    this.r[8] = ((t6 >>> 8) | (t7 << 8)) & 0x1fff;
-    this.r[9] = (t7 >>> 5) & 0x007f;
-
-    this.pad[0] = (key[16] & 0xff) | ((key[17] & 0xff) << 8);
-    this.pad[1] = (key[18] & 0xff) | ((key[19] & 0xff) << 8);
-    this.pad[2] = (key[20] & 0xff) | ((key[21] & 0xff) << 8);
-    this.pad[3] = (key[22] & 0xff) | ((key[23] & 0xff) << 8);
-    this.pad[4] = (key[24] & 0xff) | ((key[25] & 0xff) << 8);
-    this.pad[5] = (key[26] & 0xff) | ((key[27] & 0xff) << 8);
-    this.pad[6] = (key[28] & 0xff) | ((key[29] & 0xff) << 8);
-    this.pad[7] = (key[30] & 0xff) | ((key[31] & 0xff) << 8);
-  }
-
-  blocks(m: Uint8Array, mpos: number, bytes: number) {
-    const hibit = this.fin ? 0 : 1 << 11;
-    let t0, t1, t2, t3, t4, t5, t6, t7, c;
-    let d0, d1, d2, d3, d4, d5, d6, d7, d8, d9;
-
-    let h0 = this.h[0],
-      h1 = this.h[1],
-      h2 = this.h[2],
-      h3 = this.h[3],
-      h4 = this.h[4],
-      h5 = this.h[5],
-      h6 = this.h[6],
-      h7 = this.h[7],
-      h8 = this.h[8],
-      h9 = this.h[9];
-
-    const r0 = this.r[0],
-      r1 = this.r[1],
-      r2 = this.r[2],
-      r3 = this.r[3],
-      r4 = this.r[4],
-      r5 = this.r[5],
-      r6 = this.r[6],
-      r7 = this.r[7],
-      r8 = this.r[8],
-      r9 = this.r[9];
-
-    while (bytes >= 16) {
-      t0 = (m[mpos + 0] & 0xff) | ((m[mpos + 1] & 0xff) << 8);
-      h0 += t0 & 0x1fff;
-      t1 = (m[mpos + 2] & 0xff) | ((m[mpos + 3] & 0xff) << 8);
-      h1 += ((t0 >>> 13) | (t1 << 3)) & 0x1fff;
-      t2 = (m[mpos + 4] & 0xff) | ((m[mpos + 5] & 0xff) << 8);
-      h2 += ((t1 >>> 10) | (t2 << 6)) & 0x1fff;
-      t3 = (m[mpos + 6] & 0xff) | ((m[mpos + 7] & 0xff) << 8);
-      h3 += ((t2 >>> 7) | (t3 << 9)) & 0x1fff;
-      t4 = (m[mpos + 8] & 0xff) | ((m[mpos + 9] & 0xff) << 8);
-      h4 += ((t3 >>> 4) | (t4 << 12)) & 0x1fff;
-      h5 += (t4 >>> 1) & 0x1fff;
-      t5 = (m[mpos + 10] & 0xff) | ((m[mpos + 11] & 0xff) << 8);
-      h6 += ((t4 >>> 14) | (t5 << 2)) & 0x1fff;
-      t6 = (m[mpos + 12] & 0xff) | ((m[mpos + 13] & 0xff) << 8);
-      h7 += ((t5 >>> 11) | (t6 << 5)) & 0x1fff;
-      t7 = (m[mpos + 14] & 0xff) | ((m[mpos + 15] & 0xff) << 8);
-      h8 += ((t6 >>> 8) | (t7 << 8)) & 0x1fff;
-      h9 += (t7 >>> 5) | hibit;
-
-      c = 0;
-
-      d0 = c;
-      d0 += h0 * r0;
-      d0 += h1 * (5 * r9);
-      d0 += h2 * (5 * r8);
-      d0 += h3 * (5 * r7);
-      d0 += h4 * (5 * r6);
-      c = d0 >>> 13;
-      d0 &= 0x1fff;
-      d0 += h5 * (5 * r5);
-      d0 += h6 * (5 * r4);
-      d0 += h7 * (5 * r3);
-      d0 += h8 * (5 * r2);
-      d0 += h9 * (5 * r1);
-      c += d0 >>> 13;
-      d0 &= 0x1fff;
-
-      d1 = c;
-      d1 += h0 * r1;
-      d1 += h1 * r0;
-      d1 += h2 * (5 * r9);
-      d1 += h3 * (5 * r8);
-      d1 += h4 * (5 * r7);
-      c = d1 >>> 13;
-      d1 &= 0x1fff;
-      d1 += h5 * (5 * r6);
-      d1 += h6 * (5 * r5);
-      d1 += h7 * (5 * r4);
-      d1 += h8 * (5 * r3);
-      d1 += h9 * (5 * r2);
-      c += d1 >>> 13;
-      d1 &= 0x1fff;
-
-      d2 = c;
-      d2 += h0 * r2;
-      d2 += h1 * r1;
-      d2 += h2 * r0;
-      d2 += h3 * (5 * r9);
-      d2 += h4 * (5 * r8);
-      c = d2 >>> 13;
-      d2 &= 0x1fff;
-      d2 += h5 * (5 * r7);
-      d2 += h6 * (5 * r6);
-      d2 += h7 * (5 * r5);
-      d2 += h8 * (5 * r4);
-      d2 += h9 * (5 * r3);
-      c += d2 >>> 13;
-      d2 &= 0x1fff;
-
-      d3 = c;
-      d3 += h0 * r3;
-      d3 += h1 * r2;
-      d3 += h2 * r1;
-      d3 += h3 * r0;
-      d3 += h4 * (5 * r9);
-      c = d3 >>> 13;
-      d3 &= 0x1fff;
-      d3 += h5 * (5 * r8);
-      d3 += h6 * (5 * r7);
-      d3 += h7 * (5 * r6);
-      d3 += h8 * (5 * r5);
-      d3 += h9 * (5 * r4);
-      c += d3 >>> 13;
-      d3 &= 0x1fff;
-
-      d4 = c;
-      d4 += h0 * r4;
-      d4 += h1 * r3;
-      d4 += h2 * r2;
-      d4 += h3 * r1;
-      d4 += h4 * r0;
-      c = d4 >>> 13;
-      d4 &= 0x1fff;
-      d4 += h5 * (5 * r9);
-      d4 += h6 * (5 * r8);
-      d4 += h7 * (5 * r7);
-      d4 += h8 * (5 * r6);
-      d4 += h9 * (5 * r5);
-      c += d4 >>> 13;
-      d4 &= 0x1fff;
-
-      d5 = c;
-      d5 += h0 * r5;
-      d5 += h1 * r4;
-      d5 += h2 * r3;
-      d5 += h3 * r2;
-      d5 += h4 * r1;
-      c = d5 >>> 13;
-      d5 &= 0x1fff;
-      d5 += h5 * r0;
-      d5 += h6 * (5 * r9);
-      d5 += h7 * (5 * r8);
-      d5 += h8 * (5 * r7);
-      d5 += h9 * (5 * r6);
-      c += d5 >>> 13;
-      d5 &= 0x1fff;
-
-      d6 = c;
-      d6 += h0 * r6;
-      d6 += h1 * r5;
-      d6 += h2 * r4;
-      d6 += h3 * r3;
-      d6 += h4 * r2;
-      c = d6 >>> 13;
-      d6 &= 0x1fff;
-      d6 += h5 * r1;
-      d6 += h6 * r0;
-      d6 += h7 * (5 * r9);
-      d6 += h8 * (5 * r8);
-      d6 += h9 * (5 * r7);
-      c += d6 >>> 13;
-      d6 &= 0x1fff;
-
-      d7 = c;
-      d7 += h0 * r7;
-      d7 += h1 * r6;
-      d7 += h2 * r5;
-      d7 += h3 * r4;
-      d7 += h4 * r3;
-      c = d7 >>> 13;
-      d7 &= 0x1fff;
-      d7 += h5 * r2;
-      d7 += h6 * r1;
-      d7 += h7 * r0;
-      d7 += h8 * (5 * r9);
-      d7 += h9 * (5 * r8);
-      c += d7 >>> 13;
-      d7 &= 0x1fff;
-
-      d8 = c;
-      d8 += h0 * r8;
-      d8 += h1 * r7;
-      d8 += h2 * r6;
-      d8 += h3 * r5;
-      d8 += h4 * r4;
-      c = d8 >>> 13;
-      d8 &= 0x1fff;
-      d8 += h5 * r3;
-      d8 += h6 * r2;
-      d8 += h7 * r1;
-      d8 += h8 * r0;
-      d8 += h9 * (5 * r9);
-      c += d8 >>> 13;
-      d8 &= 0x1fff;
-
-      d9 = c;
-      d9 += h0 * r9;
-      d9 += h1 * r8;
-      d9 += h2 * r7;
-      d9 += h3 * r6;
-      d9 += h4 * r5;
-      c = d9 >>> 13;
-      d9 &= 0x1fff;
-      d9 += h5 * r4;
-      d9 += h6 * r3;
-      d9 += h7 * r2;
-      d9 += h8 * r1;
-      d9 += h9 * r0;
-      c += d9 >>> 13;
-      d9 &= 0x1fff;
-
-      c = ((c << 2) + c) | 0;
-      c = (c + d0) | 0;
-      d0 = c & 0x1fff;
-      c = c >>> 13;
-      d1 += c;
-
-      h0 = d0;
-      h1 = d1;
-      h2 = d2;
-      h3 = d3;
-      h4 = d4;
-      h5 = d5;
-      h6 = d6;
-      h7 = d7;
-      h8 = d8;
-      h9 = d9;
-
-      mpos += 16;
-      bytes -= 16;
-    }
-    this.h[0] = h0;
-    this.h[1] = h1;
-    this.h[2] = h2;
-    this.h[3] = h3;
-    this.h[4] = h4;
-    this.h[5] = h5;
-    this.h[6] = h6;
-    this.h[7] = h7;
-    this.h[8] = h8;
-    this.h[9] = h9;
-  }
-
-  finish(mac: Uint8Array, macpos: number) {
-    const g = new Uint16Array(10);
-    let c, mask, f, i;
-
-    if (this.leftover) {
-      i = this.leftover;
-      this.buffer[i++] = 1;
-      for (; i < 16; i++) this.buffer[i] = 0;
-      this.fin = 1;
-      this.blocks(this.buffer, 0, 16);
-    }
-
-    c = this.h[1] >>> 13;
-    this.h[1] &= 0x1fff;
-    for (i = 2; i < 10; i++) {
-      this.h[i] += c;
-      c = this.h[i] >>> 13;
-      this.h[i] &= 0x1fff;
-    }
-    this.h[0] += c * 5;
-    c = this.h[0] >>> 13;
-    this.h[0] &= 0x1fff;
-    this.h[1] += c;
-    c = this.h[1] >>> 13;
-    this.h[1] &= 0x1fff;
-    this.h[2] += c;
-
-    g[0] = this.h[0] + 5;
-    c = g[0] >>> 13;
-    g[0] &= 0x1fff;
-    for (i = 1; i < 10; i++) {
-      g[i] = this.h[i] + c;
-      c = g[i] >>> 13;
-      g[i] &= 0x1fff;
-    }
-    g[9] -= 1 << 13;
-
-    mask = (c ^ 1) - 1;
-    for (i = 0; i < 10; i++) g[i] &= mask;
-    mask = ~mask;
-    for (i = 0; i < 10; i++) this.h[i] = (this.h[i] & mask) | g[i];
-
-    this.h[0] = (this.h[0] | (this.h[1] << 13)) & 0xffff;
-    this.h[1] = ((this.h[1] >>> 3) | (this.h[2] << 10)) & 0xffff;
-    this.h[2] = ((this.h[2] >>> 6) | (this.h[3] << 7)) & 0xffff;
-    this.h[3] = ((this.h[3] >>> 9) | (this.h[4] << 4)) & 0xffff;
-    this.h[4] =
-      ((this.h[4] >>> 12) | (this.h[5] << 1) | (this.h[6] << 14)) & 0xffff;
-    this.h[5] = ((this.h[6] >>> 2) | (this.h[7] << 11)) & 0xffff;
-    this.h[6] = ((this.h[7] >>> 5) | (this.h[8] << 8)) & 0xffff;
-    this.h[7] = ((this.h[8] >>> 8) | (this.h[9] << 5)) & 0xffff;
-
-    f = this.h[0] + this.pad[0];
-    this.h[0] = f & 0xffff;
-    for (i = 1; i < 8; i++) {
-      f = (((this.h[i] + this.pad[i]) | 0) + (f >>> 16)) | 0;
-      this.h[i] = f & 0xffff;
-    }
-
-    mac[macpos + 0] = (this.h[0] >>> 0) & 0xff;
-    mac[macpos + 1] = (this.h[0] >>> 8) & 0xff;
-    mac[macpos + 2] = (this.h[1] >>> 0) & 0xff;
-    mac[macpos + 3] = (this.h[1] >>> 8) & 0xff;
-    mac[macpos + 4] = (this.h[2] >>> 0) & 0xff;
-    mac[macpos + 5] = (this.h[2] >>> 8) & 0xff;
-    mac[macpos + 6] = (this.h[3] >>> 0) & 0xff;
-    mac[macpos + 7] = (this.h[3] >>> 8) & 0xff;
-    mac[macpos + 8] = (this.h[4] >>> 0) & 0xff;
-    mac[macpos + 9] = (this.h[4] >>> 8) & 0xff;
-    mac[macpos + 10] = (this.h[5] >>> 0) & 0xff;
-    mac[macpos + 11] = (this.h[5] >>> 8) & 0xff;
-    mac[macpos + 12] = (this.h[6] >>> 0) & 0xff;
-    mac[macpos + 13] = (this.h[6] >>> 8) & 0xff;
-    mac[macpos + 14] = (this.h[7] >>> 0) & 0xff;
-    mac[macpos + 15] = (this.h[7] >>> 8) & 0xff;
-  }
-
-  update(m: Uint8Array, mpos: number, bytes: number) {
-    let i, want;
-
-    if (this.leftover) {
-      want = 16 - this.leftover;
-      if (want > bytes) want = bytes;
-      for (i = 0; i < want; i++) this.buffer[this.leftover + i] = m[mpos + i];
-      bytes -= want;
-      mpos += want;
-      this.leftover += want;
-      if (this.leftover < 16) return;
-      this.blocks(this.buffer, 0, 16);
-      this.leftover = 0;
-    }
-
-    if (bytes >= 16) {
-      want = bytes - (bytes % 16);
-      this.blocks(m, mpos, want);
-      mpos += want;
-      bytes -= want;
-    }
-
-    if (bytes) {
-      for (i = 0; i < bytes; i++) this.buffer[this.leftover + i] = m[mpos + i];
-      this.leftover += bytes;
-    }
-  }
-}
-
-function crypto_onetimeauth(
-  out: Uint8Array,
-  outpos: number,
-  m: Uint8Array,
-  mpos: number,
-  n: number,
-  k: Uint8Array,
-) {
-  const s = new poly1305(k);
-  s.update(m, mpos, n);
-  s.finish(out, outpos);
-  return 0;
-}
-
-function crypto_onetimeauth_verify(
-  h: Uint8Array,
-  hpos: number,
-  m: Uint8Array,
-  mpos: number,
-  n: number,
-  k: Uint8Array,
-) {
-  const x = new Uint8Array(16);
-  crypto_onetimeauth(x, 0, m, mpos, n, k);
-  return crypto_verify_16(h, hpos, x, 0);
-}
-
-function crypto_secretbox(
-  c: Uint8Array,
-  m: Uint8Array,
-  d: number,
-  n: Uint8Array,
-  k: Uint8Array,
-) {
-  let i;
-  if (d < 32) return -1;
-  crypto_stream_xor(c, 0, m, 0, d, n, k);
-  crypto_onetimeauth(c, 16, c, 32, d - 32, c);
-  for (i = 0; i < 16; i++) c[i] = 0;
-  return 0;
-}
-
-function crypto_secretbox_open(
-  m: Uint8Array,
-  c: Uint8Array,
-  d: number,
-  n: Uint8Array,
-  k: Uint8Array,
-) {
-  let i;
-  const x = new Uint8Array(32);
-  if (d < 32) return -1;
-  crypto_stream(x, 0, 32, n, k);
-  if (crypto_onetimeauth_verify(c, 16, c, 32, d - 32, x) !== 0) return -1;
-  crypto_stream_xor(m, 0, c, 0, d, n, k);
-  for (i = 0; i < 32; i++) m[i] = 0;
-  return 0;
-}
-
-function set25519(r: Float64Array, a: Float64Array) {
+function set25519(r: Float64Array, a: Float64Array): void {
   let i;
   for (i = 0; i < 16; i++) r[i] = a[i] | 0;
 }
 
-function car25519(o: Float64Array) {
+function car25519(o: Float64Array): void {
   let i,
     v,
     c = 1;
@@ -1166,9 +164,9 @@ function car25519(o: Float64Array) {
   o[0] += c - 1 + 37 * (c - 1);
 }
 
-function sel25519(p: Float64Array, q: Float64Array, b: number) {
-  let t,
-    c = ~(b - 1);
+function sel25519(p: Float64Array, q: Float64Array, b: number): void {
+  let t;
+  const c = ~(b - 1);
   for (let i = 0; i < 16; i++) {
     t = c & (p[i] ^ q[i]);
     p[i] ^= t;
@@ -1176,7 +174,7 @@ function sel25519(p: Float64Array, q: Float64Array, b: 
number) {
   }
 }
 
-function pack25519(o: Uint8Array, n: Float64Array) {
+function pack25519(o: Uint8Array, n: Float64Array): void {
   let i, j, b;
   const m = gf(),
     t = gf();
@@ -1201,7 +199,7 @@ function pack25519(o: Uint8Array, n: Float64Array) {
   }
 }
 
-function neq25519(a: Float64Array, b: Float64Array) {
+function neq25519(a: Float64Array, b: Float64Array): number {
   const c = new Uint8Array(32),
     d = new Uint8Array(32);
   pack25519(c, a);
@@ -1209,27 +207,27 @@ function neq25519(a: Float64Array, b: Float64Array) {
   return crypto_verify_32(c, 0, d, 0);
 }
 
-function par25519(a: Float64Array) {
+function par25519(a: Float64Array): number {
   const d = new Uint8Array(32);
   pack25519(d, a);
   return d[0] & 1;
 }
 
-function unpack25519(o: Float64Array, n: Uint8Array) {
+function unpack25519(o: Float64Array, n: Uint8Array): void {
   let i;
   for (i = 0; i < 16; i++) o[i] = n[2 * i] + (n[2 * i + 1] << 8);
   o[15] &= 0x7fff;
 }
 
-function A(o: Float64Array, a: Float64Array, b: Float64Array) {
+function A(o: Float64Array, a: Float64Array, b: Float64Array): void {
   for (let i = 0; i < 16; i++) o[i] = a[i] + b[i];
 }
 
-function Z(o: Float64Array, a: Float64Array, b: Float64Array) {
+function Z(o: Float64Array, a: Float64Array, b: Float64Array): void {
   for (let i = 0; i < 16; i++) o[i] = a[i] - b[i];
 }
 
-function M(o: Float64Array, a: Float64Array, b: Float64Array) {
+function M(o: Float64Array, a: Float64Array, b: Float64Array): void {
   let v,
     c,
     t0 = 0,
@@ -1262,8 +260,8 @@ function M(o: Float64Array, a: Float64Array, b: 
Float64Array) {
     t27 = 0,
     t28 = 0,
     t29 = 0,
-    t30 = 0,
-    b0 = b[0],
+    t30 = 0;
+  const b0 = b[0],
     b1 = b[1],
     b2 = b[2],
     b3 = b[3],
@@ -1692,11 +690,11 @@ function M(o: Float64Array, a: Float64Array, b: 
Float64Array) {
   o[15] = t15;
 }
 
-function S(o: Float64Array, a: Float64Array) {
+function S(o: Float64Array, a: Float64Array): void {
   M(o, a, a);
 }
 
-function inv25519(o: Float64Array, i: Float64Array) {
+function inv25519(o: Float64Array, i: Float64Array): void {
   const c = gf();
   let a;
   for (a = 0; a < 16; a++) c[a] = i[a];
@@ -1707,7 +705,7 @@ function inv25519(o: Float64Array, i: Float64Array) {
   for (a = 0; a < 16; a++) o[a] = c[a];
 }
 
-function pow2523(o: Float64Array, i: Float64Array) {
+function pow2523(o: Float64Array, i: Float64Array): void {
   const c = gf();
   let a;
   for (a = 0; a < 16; a++) c[a] = i[a];
@@ -1718,11 +716,15 @@ function pow2523(o: Float64Array, i: Float64Array) {
   for (a = 0; a < 16; a++) o[a] = c[a];
 }
 
-function crypto_scalarmult(q: Uint8Array, n: Uint8Array, p: Uint8Array) {
+function crypto_scalarmult(
+  q: Uint8Array,
+  n: Uint8Array,
+  p: Uint8Array,
+): number {
   const z = new Uint8Array(32);
-  let x = new Float64Array(80),
-    r,
-    i;
+  const x = new Float64Array(80);
+  let r;
+  let i;
   const a = gf(),
     b = gf(),
     c = gf(),
@@ -1777,50 +779,10 @@ function crypto_scalarmult(q: Uint8Array, n: Uint8Array, 
p: Uint8Array) {
   return 0;
 }
 
-function crypto_scalarmult_base(q: Uint8Array, n: Uint8Array) {
+function crypto_scalarmult_base(q: Uint8Array, n: Uint8Array): number {
   return crypto_scalarmult(q, n, _9);
 }
 
-function crypto_box_keypair(y: Uint8Array, x: Uint8Array) {
-  randombytes(x, 32);
-  return crypto_scalarmult_base(y, x);
-}
-
-function crypto_box_beforenm(k: Uint8Array, y: Uint8Array, x: Uint8Array) {
-  const s = new Uint8Array(32);
-  crypto_scalarmult(s, x, y);
-  return crypto_core_hsalsa20(k, _0, s, sigma);
-}
-
-const crypto_box_afternm = crypto_secretbox;
-const crypto_box_open_afternm = crypto_secretbox_open;
-
-function crypto_box(
-  c: Uint8Array,
-  m: Uint8Array,
-  d: number,
-  n: Uint8Array,
-  y: Uint8Array,
-  x: Uint8Array,
-) {
-  const k = new Uint8Array(32);
-  crypto_box_beforenm(k, y, x);
-  return crypto_box_afternm(c, m, d, n, k);
-}
-
-function crypto_box_open(
-  m: Uint8Array,
-  c: Uint8Array,
-  d: number,
-  n: Uint8Array,
-  y: Uint8Array,
-  x: Uint8Array,
-) {
-  const k = new Uint8Array(32);
-  crypto_box_beforenm(k, y, x);
-  return crypto_box_open_afternm(m, c, d, n, k);
-}
-
 // prettier-ignore
 const K = [
   0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd,
@@ -1870,10 +832,10 @@ function crypto_hashblocks_hl(
   hl: Int32Array,
   m: Uint8Array,
   n: number,
-) {
-  let wh = new Int32Array(16),
-    wl = new Int32Array(16),
-    bh0,
+): number {
+  const wh = new Int32Array(16),
+    wl = new Int32Array(16);
+  let bh0,
     bh1,
     bh2,
     bh3,
@@ -2338,7 +1300,7 @@ function crypto_hashblocks_hl(
   return n;
 }
 
-function crypto_hash(out: Uint8Array, m: Uint8Array, n: number) {
+function crypto_hash(out: Uint8Array, m: Uint8Array, n: number): number {
   const hh = new Int32Array(8);
   const hl = new Int32Array(8);
   const x = new Uint8Array(256);
@@ -2450,7 +1412,7 @@ export class HashState {
   }
 }
 
-function add(p: Float64Array[], q: Float64Array[]) {
+function add(p: Float64Array[], q: Float64Array[]): void {
   const a = gf(),
     b = gf(),
     c = gf(),
@@ -2482,14 +1444,14 @@ function add(p: Float64Array[], q: Float64Array[]) {
   M(p[3], e, h);
 }
 
-function cswap(p: Float64Array[], q: Float64Array[], b: number) {
+function cswap(p: Float64Array[], q: Float64Array[], b: number): void {
   let i;
   for (i = 0; i < 4; i++) {
     sel25519(p[i], q[i], b);
   }
 }
 
-function pack(r: Uint8Array, p: Float64Array[]) {
+function pack(r: Uint8Array, p: Float64Array[]): void {
   const tx = gf(),
     ty = gf(),
     zi = gf();
@@ -2500,7 +1462,7 @@ function pack(r: Uint8Array, p: Float64Array[]) {
   r[31] ^= par25519(tx) << 7;
 }
 
-function scalarmult(p: Float64Array[], q: Float64Array[], s: Uint8Array) {
+function scalarmult(p: Float64Array[], q: Float64Array[], s: Uint8Array): void 
{
   let b, i;
   set25519(p[0], gf0);
   set25519(p[1], gf1);
@@ -2515,7 +1477,7 @@ function scalarmult(p: Float64Array[], q: Float64Array[], 
s: Uint8Array) {
   }
 }
 
-function scalarbase(p: Float64Array[], s: Uint8Array) {
+function scalarbase(p: Float64Array[], s: Uint8Array): void {
   const q = [gf(), gf(), gf(), gf()];
   set25519(q[0], X);
   set25519(q[1], Y);
@@ -2580,7 +1542,7 @@ const L = new Float64Array([
   0x10,
 ]);
 
-function modL(r: Uint8Array, x: Float64Array) {
+function modL(r: Uint8Array, x: Float64Array): void {
   let carry, i, j, k;
   for (i = 63; i >= 32; --i) {
     carry = 0;
@@ -2605,7 +1567,7 @@ function modL(r: Uint8Array, x: Float64Array) {
   }
 }
 
-function reduce(r: Uint8Array) {
+function reduce(r: Uint8Array): void {
   const x = new Float64Array(64);
   for (let i = 0; i < 64; i++) x[i] = r[i];
   for (let i = 0; i < 64; i++) r[i] = 0;
@@ -2613,13 +1575,17 @@ function reduce(r: Uint8Array) {
 }
 
 // Note: difference from C - smlen returned, not passed as argument.
-function crypto_sign(sm: Uint8Array, m: Uint8Array, n: number, sk: Uint8Array) 
{
+function crypto_sign(
+  sm: Uint8Array,
+  m: Uint8Array,
+  n: number,
+  sk: Uint8Array,
+): number {
   const d = new Uint8Array(64),
     h = new Uint8Array(64),
     r = new Uint8Array(64);
-  let i,
-    j,
-    x = new Float64Array(64);
+  let i, j;
+  const x = new Float64Array(64);
   const p = [gf(), gf(), gf(), gf()];
 
   crypto_hash(d, sk, 32);
@@ -2652,7 +1618,7 @@ function crypto_sign(sm: Uint8Array, m: Uint8Array, n: 
number, sk: Uint8Array) {
   return smlen;
 }
 
-function unpackneg(r: Float64Array[], p: Uint8Array) {
+function unpackneg(r: Float64Array[], p: Uint8Array): number {
   const t = gf();
   const chk = gf();
   const num = gf();
@@ -2699,7 +1665,7 @@ function crypto_sign_open(
   sm: Uint8Array,
   n: number,
   pk: Uint8Array,
-) {
+): number {
   let i, mlen;
   const t = new Uint8Array(32),
     h = new Uint8Array(64);
@@ -2732,131 +1698,34 @@ function crypto_sign_open(
   return mlen;
 }
 
-const crypto_secretbox_KEYBYTES = 32,
-  crypto_secretbox_NONCEBYTES = 24,
-  crypto_secretbox_ZEROBYTES = 32,
-  crypto_secretbox_BOXZEROBYTES = 16,
-  crypto_scalarmult_BYTES = 32,
+const crypto_scalarmult_BYTES = 32,
   crypto_scalarmult_SCALARBYTES = 32,
-  crypto_box_PUBLICKEYBYTES = 32,
-  crypto_box_SECRETKEYBYTES = 32,
-  crypto_box_BEFORENMBYTES = 32,
-  crypto_box_NONCEBYTES = crypto_secretbox_NONCEBYTES,
-  crypto_box_ZEROBYTES = crypto_secretbox_ZEROBYTES,
-  crypto_box_BOXZEROBYTES = crypto_secretbox_BOXZEROBYTES,
   crypto_sign_BYTES = 64,
   crypto_sign_PUBLICKEYBYTES = 32,
   crypto_sign_SECRETKEYBYTES = 64,
   crypto_sign_SEEDBYTES = 32,
   crypto_hash_BYTES = 64;
 
-const lowlevel = {
-  crypto_core_hsalsa20: crypto_core_hsalsa20,
-  crypto_stream_xor: crypto_stream_xor,
-  crypto_stream: crypto_stream,
-  crypto_stream_salsa20_xor: crypto_stream_salsa20_xor,
-  crypto_stream_salsa20: crypto_stream_salsa20,
-  crypto_onetimeauth: crypto_onetimeauth,
-  crypto_onetimeauth_verify: crypto_onetimeauth_verify,
-  crypto_verify_16: crypto_verify_16,
-  crypto_verify_32: crypto_verify_32,
-  crypto_secretbox: crypto_secretbox,
-  crypto_secretbox_open: crypto_secretbox_open,
-  crypto_scalarmult: crypto_scalarmult,
-  crypto_scalarmult_base: crypto_scalarmult_base,
-  crypto_box_beforenm: crypto_box_beforenm,
-  crypto_box_afternm: crypto_box_afternm,
-  crypto_box: crypto_box,
-  crypto_box_open: crypto_box_open,
-  crypto_box_keypair: crypto_box_keypair,
-  crypto_hash: crypto_hash,
-  crypto_sign: crypto_sign,
-  crypto_sign_keypair: crypto_sign_keypair,
-  crypto_sign_open: crypto_sign_open,
-
-  crypto_secretbox_KEYBYTES: crypto_secretbox_KEYBYTES,
-  crypto_secretbox_NONCEBYTES: crypto_secretbox_NONCEBYTES,
-  crypto_secretbox_ZEROBYTES: crypto_secretbox_ZEROBYTES,
-  crypto_secretbox_BOXZEROBYTES: crypto_secretbox_BOXZEROBYTES,
-  crypto_scalarmult_BYTES: crypto_scalarmult_BYTES,
-  crypto_scalarmult_SCALARBYTES: crypto_scalarmult_SCALARBYTES,
-  crypto_box_PUBLICKEYBYTES: crypto_box_PUBLICKEYBYTES,
-  crypto_box_SECRETKEYBYTES: crypto_box_SECRETKEYBYTES,
-  crypto_box_BEFORENMBYTES: crypto_box_BEFORENMBYTES,
-  crypto_box_NONCEBYTES: crypto_box_NONCEBYTES,
-  crypto_box_ZEROBYTES: crypto_box_ZEROBYTES,
-  crypto_box_BOXZEROBYTES: crypto_box_BOXZEROBYTES,
-  crypto_sign_BYTES: crypto_sign_BYTES,
-  crypto_sign_PUBLICKEYBYTES: crypto_sign_PUBLICKEYBYTES,
-  crypto_sign_SECRETKEYBYTES: crypto_sign_SECRETKEYBYTES,
-  crypto_sign_SEEDBYTES: crypto_sign_SEEDBYTES,
-  crypto_hash_BYTES: crypto_hash_BYTES,
-};
-
 /* High-level API */
 
-function checkLengths(k: Uint8Array, n: Uint8Array) {
-  if (k.length !== crypto_secretbox_KEYBYTES) throw new Error("bad key size");
-  if (n.length !== crypto_secretbox_NONCEBYTES)
-    throw new Error("bad nonce size");
-}
-
-function checkBoxLengths(pk: Uint8Array, sk: Uint8Array) {
-  if (pk.length !== crypto_box_PUBLICKEYBYTES)
-    throw new Error("bad public key size");
-  if (sk.length !== crypto_box_SECRETKEYBYTES)
-    throw new Error("bad secret key size");
-}
-
-function checkArrayTypes(...args: Uint8Array[]) {
+function checkArrayTypes(...args: Uint8Array[]): void {
   for (let i = 0; i < args.length; i++) {
     if (!(args[i] instanceof Uint8Array))
       throw new TypeError("unexpected type, use Uint8Array");
   }
 }
 
-function cleanup(arr: Uint8Array) {
+function cleanup(arr: Uint8Array): void {
   for (let i = 0; i < arr.length; i++) arr[i] = 0;
 }
 
-export function randomBytes(n: number) {
+export function randomBytes(n: number): Uint8Array {
   const b = new Uint8Array(n);
   randombytes(b, n);
   return b;
 }
 
-export function secretbox(msg: Uint8Array, nonce: Uint8Array, key: Uint8Array) 
{
-  checkArrayTypes(msg, nonce, key);
-  checkLengths(key, nonce);
-  const m = new Uint8Array(crypto_secretbox_ZEROBYTES + msg.length);
-  const c = new Uint8Array(m.length);
-  for (let i = 0; i < msg.length; i++)
-    m[i + crypto_secretbox_ZEROBYTES] = msg[i];
-  crypto_secretbox(c, m, m.length, nonce, key);
-  return c.subarray(crypto_secretbox_BOXZEROBYTES);
-}
-
-export function secretbox_open(
-  box: Uint8Array,
-  nonce: Uint8Array,
-  key: Uint8Array,
-) {
-  checkArrayTypes(box, nonce, key);
-  checkLengths(key, nonce);
-  const c = new Uint8Array(crypto_secretbox_BOXZEROBYTES + box.length);
-  const m = new Uint8Array(c.length);
-  for (let i = 0; i < box.length; i++)
-    c[i + crypto_secretbox_BOXZEROBYTES] = box[i];
-  if (c.length < 32) return null;
-  if (crypto_secretbox_open(m, c, c.length, nonce, key) !== 0) return null;
-  return m.subarray(crypto_secretbox_ZEROBYTES);
-}
-
-export const secretbox_keyLength = crypto_secretbox_KEYBYTES;
-export const secretbox_nonceLength = crypto_secretbox_NONCEBYTES;
-export const secretbox_overheadLength = crypto_secretbox_BOXZEROBYTES;
-
-export function scalarMult(n: Uint8Array, p: Uint8Array) {
+export function scalarMult(n: Uint8Array, p: Uint8Array): Uint8Array {
   checkArrayTypes(n, p);
   if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error("bad n 
size");
   if (p.length !== crypto_scalarmult_BYTES) throw new Error("bad p size");
@@ -2865,7 +1734,7 @@ export function scalarMult(n: Uint8Array, p: Uint8Array) {
   return q;
 }
 
-export function scalarMult_base(n: Uint8Array) {
+export function scalarMult_base(n: Uint8Array): Uint8Array {
   checkArrayTypes(n);
   if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error("bad n 
size");
   const q = new Uint8Array(crypto_scalarmult_BYTES);
@@ -2876,61 +1745,7 @@ export function scalarMult_base(n: Uint8Array) {
 export const scalarMult_scalarLength = crypto_scalarmult_SCALARBYTES;
 export const scalarMult_groupElementLength = crypto_scalarmult_BYTES;
 
-export function box(
-  msg: Uint8Array,
-  nonce: Uint8Array,
-  publicKey: Uint8Array,
-  secretKey: Uint8Array,
-) {
-  const k = box_before(publicKey, secretKey);
-  return secretbox(msg, nonce, k);
-}
-
-export function box_before(publicKey: Uint8Array, secretKey: Uint8Array) {
-  checkArrayTypes(publicKey, secretKey);
-  checkBoxLengths(publicKey, secretKey);
-  const k = new Uint8Array(crypto_box_BEFORENMBYTES);
-  crypto_box_beforenm(k, publicKey, secretKey);
-  return k;
-}
-
-export const box_after = secretbox;
-
-export function box_open(
-  msg: Uint8Array,
-  nonce: Uint8Array,
-  publicKey: Uint8Array,
-  secretKey: Uint8Array,
-) {
-  const k = box_before(publicKey, secretKey);
-  return secretbox_open(msg, nonce, k);
-}
-
-export const box_open_after = secretbox_open;
-
-export function box_keyPair() {
-  const pk = new Uint8Array(crypto_box_PUBLICKEYBYTES);
-  const sk = new Uint8Array(crypto_box_SECRETKEYBYTES);
-  crypto_box_keypair(pk, sk);
-  return { publicKey: pk, secretKey: sk };
-}
-
-export function box_keyPair_fromSecretKey(secretKey: Uint8Array) {
-  checkArrayTypes(secretKey);
-  if (secretKey.length !== crypto_box_SECRETKEYBYTES)
-    throw new Error("bad secret key size");
-  const pk = new Uint8Array(crypto_box_PUBLICKEYBYTES);
-  crypto_scalarmult_base(pk, secretKey);
-  return { publicKey: pk, secretKey: new Uint8Array(secretKey) };
-}
-
-export const box_publicKeyLength = crypto_box_PUBLICKEYBYTES;
-export const box_secretKeyLength = crypto_box_SECRETKEYBYTES;
-export const box_sharedKeyLength = crypto_box_BEFORENMBYTES;
-export const box_nonceLength = crypto_box_NONCEBYTES;
-export const box_overheadLength = secretbox_overheadLength;
-
-export function sign(msg: Uint8Array, secretKey: Uint8Array) {
+export function sign(msg: Uint8Array, secretKey: Uint8Array): Uint8Array {
   checkArrayTypes(msg, secretKey);
   if (secretKey.length !== crypto_sign_SECRETKEYBYTES)
     throw new Error("bad secret key size");
@@ -2939,7 +1754,10 @@ export function sign(msg: Uint8Array, secretKey: 
Uint8Array) {
   return signedMsg;
 }
 
-export function sign_open(signedMsg: Uint8Array, publicKey: Uint8Array) {
+export function sign_open(
+  signedMsg: Uint8Array,
+  publicKey: Uint8Array,
+): Uint8Array | null {
   checkArrayTypes(signedMsg, publicKey);
   if (publicKey.length !== crypto_sign_PUBLICKEYBYTES)
     throw new Error("bad public key size");
@@ -2951,7 +1769,10 @@ export function sign_open(signedMsg: Uint8Array, 
publicKey: Uint8Array) {
   return m;
 }
 
-export function sign_detached(msg: Uint8Array, secretKey: Uint8Array) {
+export function sign_detached(
+  msg: Uint8Array,
+  secretKey: Uint8Array,
+): Uint8Array {
   const signedMsg = sign(msg, secretKey);
   const sig = new Uint8Array(crypto_sign_BYTES);
   for (let i = 0; i < sig.length; i++) sig[i] = signedMsg[i];
@@ -2962,7 +1783,7 @@ export function sign_detached_verify(
   msg: Uint8Array,
   sig: Uint8Array,
   publicKey: Uint8Array,
-) {
+): boolean {
   checkArrayTypes(msg, sig, publicKey);
   if (sig.length !== crypto_sign_BYTES) throw new Error("bad signature size");
   if (publicKey.length !== crypto_sign_PUBLICKEYBYTES)
@@ -2975,7 +1796,10 @@ export function sign_detached_verify(
   return crypto_sign_open(m, sm, sm.length, publicKey) >= 0;
 }
 
-export function sign_keyPair() {
+export function sign_keyPair(): {
+  publicKey: Uint8Array;
+  secretKey: Uint8Array;
+} {
   const pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES);
   const sk = new Uint8Array(crypto_sign_SECRETKEYBYTES);
   crypto_sign_keypair(pk, sk, false);
@@ -3005,7 +1829,12 @@ export function x25519_edwards_keyPair_fromSecretKey(
   return pk;
 }
 
-export function sign_keyPair_fromSecretKey(secretKey: Uint8Array) {
+export function sign_keyPair_fromSecretKey(
+  secretKey: Uint8Array,
+): {
+  publicKey: Uint8Array;
+  secretKey: Uint8Array;
+} {
   checkArrayTypes(secretKey);
   if (secretKey.length !== crypto_sign_SECRETKEYBYTES)
     throw new Error("bad secret key size");
@@ -3014,7 +1843,12 @@ export function sign_keyPair_fromSecretKey(secretKey: 
Uint8Array) {
   return { publicKey: pk, secretKey: new Uint8Array(secretKey) };
 }
 
-export function sign_keyPair_fromSeed(seed: Uint8Array) {
+export function sign_keyPair_fromSeed(
+  seed: Uint8Array,
+): {
+  publicKey: Uint8Array;
+  secretKey: Uint8Array;
+} {
   checkArrayTypes(seed);
   if (seed.length !== crypto_sign_SEEDBYTES) throw new Error("bad seed size");
   const pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES);
@@ -3029,7 +1863,7 @@ export const sign_secretKeyLength = 
crypto_sign_SECRETKEYBYTES;
 export const sign_seedLength = crypto_sign_SEEDBYTES;
 export const sign_signatureLength = crypto_sign_BYTES;
 
-export function hash(msg: Uint8Array) {
+export function hash(msg: Uint8Array): Uint8Array {
   checkArrayTypes(msg);
   const h = new Uint8Array(crypto_hash_BYTES);
   crypto_hash(h, msg, msg.length);
@@ -3038,7 +1872,7 @@ export function hash(msg: Uint8Array) {
 
 export const hash_hashLength = crypto_hash_BYTES;
 
-export function verify(x: Uint8Array, y: Uint8Array) {
+export function verify(x: Uint8Array, y: Uint8Array): boolean {
   checkArrayTypes(x, y);
   // Zero length arguments are considered not equal.
   if (x.length === 0 || y.length === 0) return false;
@@ -3046,7 +1880,7 @@ export function verify(x: Uint8Array, y: Uint8Array) {
   return vn(x, 0, y, 0, x.length) === 0 ? true : false;
 }
 
-export function setPRNG(fn: (x: Uint8Array, n: number) => void) {
+export function setPRNG(fn: (x: Uint8Array, n: number) => void): void {
   randombytes = fn;
 }
 
@@ -3084,8 +1918,8 @@ export function sign_ed25519_pk_to_curve25519(
     // Browsers.
     const QUOTA = 65536;
     setPRNG(function (x: Uint8Array, n: number) {
-      let i,
-        v = new Uint8Array(n);
+      let i;
+      const v = new Uint8Array(n);
       for (i = 0; i < n; i += QUOTA) {
         cr.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA)));
       }
@@ -3094,12 +1928,12 @@ export function sign_ed25519_pk_to_curve25519(
     });
   } else if (typeof require !== "undefined") {
     // Node.js.
+    // eslint-disable-next-line @typescript-eslint/no-var-requires
     const cr = require("crypto");
     if (cr && cr.randomBytes) {
       setPRNG(function (x: Uint8Array, n: number) {
-        let i,
-          v = cr.randomBytes(n);
-        for (i = 0; i < n; i++) x[i] = v[i];
+        const v = cr.randomBytes(n);
+        for (let i = 0; i < n; i++) x[i] = v[i];
         cleanup(v);
       });
     }
diff --git a/src/operations/pay.ts b/src/operations/pay.ts
index 3a629e9c..337068b5 100644
--- a/src/operations/pay.ts
+++ b/src/operations/pay.ts
@@ -620,7 +620,7 @@ export async function processDownloadProposal(
   proposalId: string,
   forceNow = false,
 ): Promise<void> {
-  const onOpErr = (err: OperationError) =>
+  const onOpErr = (err: OperationError): Promise<void> =>
     incrementProposalRetry(ws, proposalId, err);
   await guardOperationException(
     () => processDownloadProposalImpl(ws, proposalId, forceNow),
@@ -631,7 +631,7 @@ export async function processDownloadProposal(
 async function resetDownloadProposalRetry(
   ws: InternalWalletState,
   proposalId: string,
-) {
+): Promise<void> {
   await ws.db.mutate(Stores.proposals, proposalId, (x) => {
     if (x.retryInfo.active) {
       x.retryInfo = initRetryInfo();
@@ -1108,7 +1108,7 @@ export async function processPurchasePay(
   proposalId: string,
   forceNow = false,
 ): Promise<void> {
-  const onOpErr = (e: OperationError) =>
+  const onOpErr = (e: OperationError): Promise<void> =>
     incrementPurchasePayRetry(ws, proposalId, e);
   await guardOperationException(
     () => processPurchasePayImpl(ws, proposalId, forceNow),
@@ -1119,7 +1119,7 @@ export async function processPurchasePay(
 async function resetPurchasePayRetry(
   ws: InternalWalletState,
   proposalId: string,
-) {
+): Promise<void> {
   await ws.db.mutate(Stores.purchases, proposalId, (x) => {
     if (x.payRetryInfo.active) {
       x.payRetryInfo = initRetryInfo();
@@ -1150,7 +1150,7 @@ async function processPurchasePayImpl(
 export async function refuseProposal(
   ws: InternalWalletState,
   proposalId: string,
-) {
+): Promise<void> {
   const success = await ws.db.runWithWriteTransaction(
     [Stores.proposals],
     async (tx) => {
diff --git a/src/operations/refund.ts b/src/operations/refund.ts
index 74d4b848..af9a4889 100644
--- a/src/operations/refund.ts
+++ b/src/operations/refund.ts
@@ -302,7 +302,7 @@ export async function processPurchaseQueryRefund(
   proposalId: string,
   forceNow = false,
 ): Promise<void> {
-  const onOpErr = (e: OperationError) =>
+  const onOpErr = (e: OperationError): Promise<void> =>
     incrementPurchaseQueryRefundRetry(ws, proposalId, e);
   await guardOperationException(
     () => processPurchaseQueryRefundImpl(ws, proposalId, forceNow),
@@ -313,7 +313,7 @@ export async function processPurchaseQueryRefund(
 async function resetPurchaseQueryRefundRetry(
   ws: InternalWalletState,
   proposalId: string,
-) {
+): Promise<void> {
   await ws.db.mutate(Stores.purchases, proposalId, (x) => {
     if (x.refundStatusRetryInfo.active) {
       x.refundStatusRetryInfo = initRetryInfo();
@@ -368,7 +368,7 @@ export async function processPurchaseApplyRefund(
   proposalId: string,
   forceNow = false,
 ): Promise<void> {
-  const onOpErr = (e: OperationError) =>
+  const onOpErr = (e: OperationError): Promise<void> =>
     incrementPurchaseApplyRefundRetry(ws, proposalId, e);
   await guardOperationException(
     () => processPurchaseApplyRefundImpl(ws, proposalId, forceNow),
@@ -379,7 +379,7 @@ export async function processPurchaseApplyRefund(
 async function resetPurchaseApplyRefundRetry(
   ws: InternalWalletState,
   proposalId: string,
-) {
+): Promise<void> {
   await ws.db.mutate(Stores.purchases, proposalId, (x) => {
     if (x.refundApplyRetryInfo.active) {
       x.refundApplyRetryInfo = initRetryInfo();
@@ -435,11 +435,10 @@ async function processPurchaseApplyRefundImpl(
         // We're too late, refund is expired.
         newRefundsFailed[pk] = info;
         break;
-      default:
+      default: {
         let body: string | null = null;
-        try {
-          body = await resp.json();
-        } catch {}
+        // FIXME: error handling!
+        body = await resp.json();
         const m = "refund request (at exchange) failed";
         throw new OperationFailedError({
           message: m,
@@ -448,6 +447,7 @@ async function processPurchaseApplyRefundImpl(
             body,
           },
         });
+      }
     }
   }
   let allRefundsProcessed = false;
diff --git a/src/types/ReserveStatus.ts b/src/types/ReserveStatus.ts
index 8ab7225e..5a3011b3 100644
--- a/src/types/ReserveStatus.ts
+++ b/src/types/ReserveStatus.ts
@@ -23,11 +23,9 @@
  */
 import {
   codecForString,
-  typecheckedCodec,
   makeCodecForObject,
-  makeCodecForConstString,
-  makeCodecForUnion,
   makeCodecForList,
+  Codec,
 } from "../util/codec";
 import { AmountString } from "./talerTypes";
 import {
@@ -52,10 +50,8 @@ export interface ReserveStatus {
   history: ReserveTransaction[];
 }
 
-export const codecForReserveStatus = () =>
-  typecheckedCodec<ReserveStatus>(
+export const codecForReserveStatus = (): Codec<ReserveStatus> =>
     makeCodecForObject<ReserveStatus>()
       .property("balance", codecForString)
       .property("history", makeCodecForList(codecForReserveTransaction()))
-      .build("ReserveStatus"),
-  );
+      .build("ReserveStatus");
diff --git a/src/types/ReserveTransaction.ts b/src/types/ReserveTransaction.ts
index cebccd2d..acbd502e 100644
--- a/src/types/ReserveTransaction.ts
+++ b/src/types/ReserveTransaction.ts
@@ -23,10 +23,10 @@
  */
 import {
   codecForString,
-  typecheckedCodec,
   makeCodecForObject,
   makeCodecForConstString,
   makeCodecForUnion,
+  Codec,
 } from "../util/codec";
 import {
   AmountString,
@@ -179,8 +179,7 @@ export type ReserveTransaction =
   | ReserveClosingTransaction
   | ReserveRecoupTransaction;
 
-export const codecForReserveWithdrawTransaction = () =>
-  typecheckedCodec<ReserveWithdrawTransaction>(
+export const codecForReserveWithdrawTransaction = (): 
Codec<ReserveWithdrawTransaction> =>
     makeCodecForObject<ReserveWithdrawTransaction>()
       .property("amount", codecForString)
       .property("h_coin_envelope", codecForString)
@@ -191,22 +190,18 @@ export const codecForReserveWithdrawTransaction = () =>
         makeCodecForConstString(ReserveTransactionType.Withdraw),
       )
       .property("withdraw_fee", codecForString)
-      .build("ReserveWithdrawTransaction"),
-  );
+      .build("ReserveWithdrawTransaction");
 
-export const codecForReserveCreditTransaction = () =>
-  typecheckedCodec<ReserveCreditTransaction>(
+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"),
-  );
+      .build("ReserveCreditTransaction");
 
-export const codecForReserveClosingTransaction = () =>
-  typecheckedCodec<ReserveClosingTransaction>(
+export const codecForReserveClosingTransaction = (): 
Codec<ReserveClosingTransaction> =>
     makeCodecForObject<ReserveClosingTransaction>()
       .property("amount", codecForString)
       .property("closing_fee", codecForString)
@@ -216,11 +211,9 @@ export const codecForReserveClosingTransaction = () =>
       .property("timestamp", codecForTimestamp)
       .property("type", 
makeCodecForConstString(ReserveTransactionType.Closing))
       .property("wtid", codecForString)
-      .build("ReserveClosingTransaction"),
-  );
+      .build("ReserveClosingTransaction");
 
-export const codecForReserveRecoupTransaction = () =>
-  typecheckedCodec<ReserveRecoupTransaction>(
+export const codecForReserveRecoupTransaction = (): 
Codec<ReserveRecoupTransaction> =>
     makeCodecForObject<ReserveRecoupTransaction>()
       .property("amount", codecForString)
       .property("coin_pub", codecForString)
@@ -228,11 +221,9 @@ export const codecForReserveRecoupTransaction = () =>
       .property("exchange_sig", codecForString)
       .property("timestamp", codecForTimestamp)
       .property("type", makeCodecForConstString(ReserveTransactionType.Recoup))
-      .build("ReserveRecoupTransaction"),
-  );
+      .build("ReserveRecoupTransaction");
 
-export const codecForReserveTransaction = () =>
-  typecheckedCodec<ReserveTransaction>(
+export const codecForReserveTransaction = (): Codec<ReserveTransaction> =>
     makeCodecForUnion<ReserveTransaction>()
       .discriminateOn("type")
       .alternative(
@@ -251,5 +242,4 @@ export const codecForReserveTransaction = () =>
         ReserveTransactionType.Credit,
         codecForReserveCreditTransaction(),
       )
-      .build<ReserveTransaction>("ReserveTransaction"),
-  );
+      .build<ReserveTransaction>("ReserveTransaction");
diff --git a/src/types/talerTypes.ts b/src/types/talerTypes.ts
index 0f35f7ed..74157b18 100644
--- a/src/types/talerTypes.ts
+++ b/src/types/talerTypes.ts
@@ -28,7 +28,6 @@
  */
 
 import {
-  typecheckedCodec,
   makeCodecForObject,
   codecForString,
   makeCodecForList,
@@ -37,6 +36,7 @@ import {
   codecForNumber,
   codecForBoolean,
   makeCodecForMap,
+  Codec,
 } from "../util/codec";
 import {
   Timestamp,
@@ -786,222 +786,183 @@ export type EddsaSignatureString = string;
 export type EddsaPublicKeyString = string;
 export type CoinPublicKeyString = string;
 
-export const codecForDenomination = () =>
-  typecheckedCodec<Denomination>(
-    makeCodecForObject<Denomination>()
-      .property("value", codecForString)
-      .property("denom_pub", codecForString)
-      .property("fee_withdraw", codecForString)
-      .property("fee_deposit", codecForString)
-      .property("fee_refresh", codecForString)
-      .property("fee_refund", codecForString)
-      .property("stamp_start", codecForTimestamp)
-      .property("stamp_expire_withdraw", codecForTimestamp)
-      .property("stamp_expire_legal", codecForTimestamp)
-      .property("stamp_expire_deposit", codecForTimestamp)
-      .property("master_sig", codecForString)
-      .build("Denomination"),
-  );
-
-export const codecForAuditorDenomSig = () =>
-  typecheckedCodec<AuditorDenomSig>(
-    makeCodecForObject<AuditorDenomSig>()
-      .property("denom_pub_h", codecForString)
-      .property("auditor_sig", codecForString)
-      .build("AuditorDenomSig"),
-  );
-
-export const codecForAuditor = () =>
-  typecheckedCodec<Auditor>(
-    makeCodecForObject<Auditor>()
-      .property("auditor_pub", codecForString)
-      .property("auditor_url", codecForString)
-      .property(
-        "denomination_keys",
-        makeCodecForList(codecForAuditorDenomSig()),
-      )
-      .build("Auditor"),
-  );
-
-export const codecForExchangeHandle = () =>
-  typecheckedCodec<ExchangeHandle>(
-    makeCodecForObject<ExchangeHandle>()
-      .property("master_pub", codecForString)
-      .property("url", codecForString)
-      .build("ExchangeHandle"),
-  );
-
-export const codecForAuditorHandle = () =>
-  typecheckedCodec<AuditorHandle>(
-    makeCodecForObject<AuditorHandle>()
-      .property("name", codecForString)
-      .property("master_pub", codecForString)
-      .property("url", codecForString)
-      .build("AuditorHandle"),
-  );
-
-export const codecForContractTerms = () =>
-  typecheckedCodec<ContractTerms>(
-    makeCodecForObject<ContractTerms>()
-      .property("order_id", codecForString)
-      .property("fulfillment_url", codecForString)
-      .property("merchant_base_url", codecForString)
-      .property("h_wire", codecForString)
-      .property("auto_refund", makeCodecOptional(codecForDuration))
-      .property("wire_method", codecForString)
-      .property("summary", codecForString)
-      .property("nonce", codecForString)
-      .property("amount", codecForString)
-      .property("auditors", makeCodecForList(codecForAuditorHandle()))
-      .property("pay_deadline", codecForTimestamp)
-      .property("refund_deadline", codecForTimestamp)
-      .property("wire_transfer_deadline", codecForTimestamp)
-      .property("timestamp", codecForTimestamp)
-      .property("locations", codecForAny)
-      .property("max_fee", codecForString)
-      .property("max_wire_fee", makeCodecOptional(codecForString))
-      .property("merchant", codecForAny)
-      .property("merchant_pub", codecForString)
-      .property("exchanges", makeCodecForList(codecForExchangeHandle()))
-      .property("products", makeCodecOptional(makeCodecForList(codecForAny)))
-      .property("extra", codecForAny)
-      .build("ContractTerms"),
-  );
-
-export const codecForMerchantRefundPermission = () =>
-  typecheckedCodec<MerchantRefundPermission>(
-    makeCodecForObject<MerchantRefundPermission>()
-      .property("refund_amount", codecForString)
-      .property("refund_fee", codecForString)
-      .property("coin_pub", codecForString)
-      .property("rtransaction_id", codecForNumber)
-      .property("merchant_sig", codecForString)
-      .build("MerchantRefundPermission"),
-  );
-
-export const codecForMerchantRefundResponse = () =>
-  typecheckedCodec<MerchantRefundResponse>(
-    makeCodecForObject<MerchantRefundResponse>()
-      .property("merchant_pub", codecForString)
-      .property("h_contract_terms", codecForString)
-      .property(
-        "refund_permissions",
-        makeCodecForList(codecForMerchantRefundPermission()),
-      )
-      .build("MerchantRefundResponse"),
-  );
-
-export const codecForReserveSigSingleton = () =>
-  typecheckedCodec<ReserveSigSingleton>(
-    makeCodecForObject<ReserveSigSingleton>()
-      .property("reserve_sig", codecForString)
-      .build("ReserveSigSingleton"),
-  );
-
-export const codecForTipResponse = () =>
-  typecheckedCodec<TipResponse>(
-    makeCodecForObject<TipResponse>()
-      .property("reserve_pub", codecForString)
-      .property("reserve_sigs", 
makeCodecForList(codecForReserveSigSingleton()))
-      .build("TipResponse"),
-  );
-
-export const codecForRecoup = () =>
-  typecheckedCodec<Recoup>(
-    makeCodecForObject<Recoup>()
-      .property("h_denom_pub", codecForString)
-      .build("Payback"),
-  );
-
-export const codecForExchangeSigningKey = () =>
-  typecheckedCodec<ExchangeSignKeyJson>(
-    makeCodecForObject<ExchangeSignKeyJson>()
-      .property("key", codecForString)
-      .property("master_sig", codecForString)
-      .property("stamp_end", codecForTimestamp)
-      .property("stamp_start", codecForTimestamp)
-      .property("stamp_expire", codecForTimestamp)
-      .build("ExchangeSignKeyJson"),
-  );
-
-export const codecForExchangeKeysJson = () =>
-  typecheckedCodec<ExchangeKeysJson>(
-    makeCodecForObject<ExchangeKeysJson>()
-      .property("denoms", makeCodecForList(codecForDenomination()))
-      .property("master_public_key", codecForString)
-      .property("auditors", makeCodecForList(codecForAuditor()))
-      .property("list_issue_date", codecForTimestamp)
-      .property("recoup", 
makeCodecOptional(makeCodecForList(codecForRecoup())))
-      .property("signkeys", makeCodecForList(codecForExchangeSigningKey()))
-      .property("version", codecForString)
-      .build("KeysJson"),
-  );
-
-export const codecForWireFeesJson = () =>
-  typecheckedCodec<WireFeesJson>(
-    makeCodecForObject<WireFeesJson>()
-      .property("wire_fee", codecForString)
-      .property("closing_fee", codecForString)
-      .property("sig", codecForString)
-      .property("start_date", codecForTimestamp)
-      .property("end_date", codecForTimestamp)
-      .build("WireFeesJson"),
-  );
-
-export const codecForAccountInfo = () =>
-  typecheckedCodec<AccountInfo>(
-    makeCodecForObject<AccountInfo>()
-      .property("payto_uri", codecForString)
-      .property("master_sig", codecForString)
-      .build("AccountInfo"),
-  );
-
-export const codecForExchangeWireJson = () =>
-  typecheckedCodec<ExchangeWireJson>(
-    makeCodecForObject<ExchangeWireJson>()
-      .property("accounts", makeCodecForList(codecForAccountInfo()))
-      .property(
-        "fees",
-        makeCodecForMap(makeCodecForList(codecForWireFeesJson())),
-      )
-      .build("ExchangeWireJson"),
-  );
-
-export const codecForProposal = () =>
-  typecheckedCodec<Proposal>(
-    makeCodecForObject<Proposal>()
-      .property("contract_terms", codecForAny)
-      .property("sig", codecForString)
-      .build("Proposal"),
-  );
-
-export const codecForCheckPaymentResponse = () =>
-  typecheckedCodec<CheckPaymentResponse>(
-    makeCodecForObject<CheckPaymentResponse>()
-      .property("paid", codecForBoolean)
-      .property("refunded", makeCodecOptional(codecForBoolean))
-      .property("refunded_amount", makeCodecOptional(codecForString))
-      .property("contract_terms", makeCodecOptional(codecForAny))
-      .property("taler_pay_uri", makeCodecOptional(codecForString))
-      .property("contract_url", makeCodecOptional(codecForString))
-      .build("CheckPaymentResponse"),
-  );
-
-export const codecForWithdrawOperationStatusResponse = () =>
-  typecheckedCodec<WithdrawOperationStatusResponse>(
-    makeCodecForObject<WithdrawOperationStatusResponse>()
-      .property("selection_done", codecForBoolean)
-      .property("transfer_done", codecForBoolean)
-      .property("amount", codecForString)
-      .property("sender_wire", makeCodecOptional(codecForString))
-      .property("suggested_exchange", makeCodecOptional(codecForString))
-      .property("confirm_transfer_url", makeCodecOptional(codecForString))
-      .property("wire_types", makeCodecForList(codecForString))
-      .build("WithdrawOperationStatusResponse"),
-  );
-
-export const codecForTipPickupGetResponse = () =>
-  typecheckedCodec<TipPickupGetResponse>(
+export const codecForDenomination = (): Codec<Denomination> =>
+  makeCodecForObject<Denomination>()
+    .property("value", codecForString)
+    .property("denom_pub", codecForString)
+    .property("fee_withdraw", codecForString)
+    .property("fee_deposit", codecForString)
+    .property("fee_refresh", codecForString)
+    .property("fee_refund", codecForString)
+    .property("stamp_start", codecForTimestamp)
+    .property("stamp_expire_withdraw", codecForTimestamp)
+    .property("stamp_expire_legal", codecForTimestamp)
+    .property("stamp_expire_deposit", codecForTimestamp)
+    .property("master_sig", codecForString)
+    .build("Denomination");
+
+export const codecForAuditorDenomSig = (): Codec<AuditorDenomSig> =>
+  makeCodecForObject<AuditorDenomSig>()
+    .property("denom_pub_h", codecForString)
+    .property("auditor_sig", codecForString)
+    .build("AuditorDenomSig");
+
+export const codecForAuditor = (): Codec<Auditor> =>
+  makeCodecForObject<Auditor>()
+    .property("auditor_pub", codecForString)
+    .property("auditor_url", codecForString)
+    .property("denomination_keys", makeCodecForList(codecForAuditorDenomSig()))
+    .build("Auditor");
+
+export const codecForExchangeHandle = (): Codec<ExchangeHandle> =>
+  makeCodecForObject<ExchangeHandle>()
+    .property("master_pub", codecForString)
+    .property("url", codecForString)
+    .build("ExchangeHandle");
+
+export const codecForAuditorHandle = (): Codec<AuditorHandle> =>
+  makeCodecForObject<AuditorHandle>()
+    .property("name", codecForString)
+    .property("master_pub", codecForString)
+    .property("url", codecForString)
+    .build("AuditorHandle");
+
+export const codecForContractTerms = (): Codec<ContractTerms> =>
+  makeCodecForObject<ContractTerms>()
+    .property("order_id", codecForString)
+    .property("fulfillment_url", codecForString)
+    .property("merchant_base_url", codecForString)
+    .property("h_wire", codecForString)
+    .property("auto_refund", makeCodecOptional(codecForDuration))
+    .property("wire_method", codecForString)
+    .property("summary", codecForString)
+    .property("nonce", codecForString)
+    .property("amount", codecForString)
+    .property("auditors", makeCodecForList(codecForAuditorHandle()))
+    .property("pay_deadline", codecForTimestamp)
+    .property("refund_deadline", codecForTimestamp)
+    .property("wire_transfer_deadline", codecForTimestamp)
+    .property("timestamp", codecForTimestamp)
+    .property("locations", codecForAny)
+    .property("max_fee", codecForString)
+    .property("max_wire_fee", makeCodecOptional(codecForString))
+    .property("merchant", codecForAny)
+    .property("merchant_pub", codecForString)
+    .property("exchanges", makeCodecForList(codecForExchangeHandle()))
+    .property("products", makeCodecOptional(makeCodecForList(codecForAny)))
+    .property("extra", codecForAny)
+    .build("ContractTerms");
+
+export const codecForMerchantRefundPermission = (): Codec<
+  MerchantRefundPermission
+> =>
+  makeCodecForObject<MerchantRefundPermission>()
+    .property("refund_amount", codecForString)
+    .property("refund_fee", codecForString)
+    .property("coin_pub", codecForString)
+    .property("rtransaction_id", codecForNumber)
+    .property("merchant_sig", codecForString)
+    .build("MerchantRefundPermission");
+
+export const codecForMerchantRefundResponse = (): Codec<
+  MerchantRefundResponse
+> =>
+  makeCodecForObject<MerchantRefundResponse>()
+    .property("merchant_pub", codecForString)
+    .property("h_contract_terms", codecForString)
+    .property(
+      "refund_permissions",
+      makeCodecForList(codecForMerchantRefundPermission()),
+    )
+    .build("MerchantRefundResponse");
+
+export const codecForReserveSigSingleton = (): Codec<ReserveSigSingleton> =>
+  makeCodecForObject<ReserveSigSingleton>()
+    .property("reserve_sig", codecForString)
+    .build("ReserveSigSingleton");
+
+export const codecForTipResponse = (): Codec<TipResponse> =>
+  makeCodecForObject<TipResponse>()
+    .property("reserve_pub", codecForString)
+    .property("reserve_sigs", makeCodecForList(codecForReserveSigSingleton()))
+    .build("TipResponse");
+
+export const codecForRecoup = (): Codec<Recoup> =>
+  makeCodecForObject<Recoup>()
+    .property("h_denom_pub", codecForString)
+    .build("Recoup");
+
+export const codecForExchangeSigningKey = (): Codec<ExchangeSignKeyJson> =>
+  makeCodecForObject<ExchangeSignKeyJson>()
+    .property("key", codecForString)
+    .property("master_sig", codecForString)
+    .property("stamp_end", codecForTimestamp)
+    .property("stamp_start", codecForTimestamp)
+    .property("stamp_expire", codecForTimestamp)
+    .build("ExchangeSignKeyJson");
+
+export const codecForExchangeKeysJson = (): Codec<ExchangeKeysJson> =>
+  makeCodecForObject<ExchangeKeysJson>()
+    .property("denoms", makeCodecForList(codecForDenomination()))
+    .property("master_public_key", codecForString)
+    .property("auditors", makeCodecForList(codecForAuditor()))
+    .property("list_issue_date", codecForTimestamp)
+    .property("recoup", makeCodecOptional(makeCodecForList(codecForRecoup())))
+    .property("signkeys", makeCodecForList(codecForExchangeSigningKey()))
+    .property("version", codecForString)
+    .build("KeysJson");
+
+export const codecForWireFeesJson = (): Codec<WireFeesJson> =>
+  makeCodecForObject<WireFeesJson>()
+    .property("wire_fee", codecForString)
+    .property("closing_fee", codecForString)
+    .property("sig", codecForString)
+    .property("start_date", codecForTimestamp)
+    .property("end_date", codecForTimestamp)
+    .build("WireFeesJson");
+
+export const codecForAccountInfo = (): Codec<AccountInfo> =>
+  makeCodecForObject<AccountInfo>()
+    .property("payto_uri", codecForString)
+    .property("master_sig", codecForString)
+    .build("AccountInfo");
+
+export const codecForExchangeWireJson = (): Codec<ExchangeWireJson> =>
+  makeCodecForObject<ExchangeWireJson>()
+    .property("accounts", makeCodecForList(codecForAccountInfo()))
+    .property("fees", 
makeCodecForMap(makeCodecForList(codecForWireFeesJson())))
+    .build("ExchangeWireJson");
+
+export const codecForProposal = (): Codec<Proposal> =>
+  makeCodecForObject<Proposal>()
+    .property("contract_terms", codecForAny)
+    .property("sig", codecForString)
+    .build("Proposal");
+
+export const codecForCheckPaymentResponse = (): Codec<CheckPaymentResponse> =>
+  makeCodecForObject<CheckPaymentResponse>()
+    .property("paid", codecForBoolean)
+    .property("refunded", makeCodecOptional(codecForBoolean))
+    .property("refunded_amount", makeCodecOptional(codecForString))
+    .property("contract_terms", makeCodecOptional(codecForAny))
+    .property("taler_pay_uri", makeCodecOptional(codecForString))
+    .property("contract_url", makeCodecOptional(codecForString))
+    .build("CheckPaymentResponse");
+
+export const codecForWithdrawOperationStatusResponse = (): Codec<
+  WithdrawOperationStatusResponse
+> =>
+  makeCodecForObject<WithdrawOperationStatusResponse>()
+    .property("selection_done", codecForBoolean)
+    .property("transfer_done", codecForBoolean)
+    .property("amount", codecForString)
+    .property("sender_wire", makeCodecOptional(codecForString))
+    .property("suggested_exchange", makeCodecOptional(codecForString))
+    .property("confirm_transfer_url", makeCodecOptional(codecForString))
+    .property("wire_types", makeCodecForList(codecForString))
+    .build("WithdrawOperationStatusResponse");
+
+export const codecForTipPickupGetResponse = (): Codec<TipPickupGetResponse> =>
     makeCodecForObject<TipPickupGetResponse>()
       .property("extra", codecForAny)
       .property("amount", codecForString)
@@ -1009,20 +970,15 @@ export const codecForTipPickupGetResponse = () =>
       .property("exchange_url", codecForString)
       .property("stamp_expire", codecForTimestamp)
       .property("stamp_created", codecForTimestamp)
-      .build("TipPickupGetResponse"),
-  );
+      .build("TipPickupGetResponse");
 
-export const codecForRecoupConfirmation = () =>
-  typecheckedCodec<RecoupConfirmation>(
+export const codecForRecoupConfirmation = (): Codec<RecoupConfirmation> =>
     makeCodecForObject<RecoupConfirmation>()
       .property("reserve_pub", makeCodecOptional(codecForString))
       .property("old_coin_pub", makeCodecOptional(codecForString))
-      .build("RecoupConfirmation"),
-  );
+      .build("RecoupConfirmation");
 
-export const codecForWithdrawResponse = () =>
-  typecheckedCodec<WithdrawResponse>(
+export const codecForWithdrawResponse = (): Codec<WithdrawResponse> =>
     makeCodecForObject<WithdrawResponse>()
       .property("ev_sig", codecForString)
-      .build("WithdrawResponse"),
-  );
+      .build("WithdrawResponse");
diff --git a/src/types/walletTypes.ts b/src/types/walletTypes.ts
index 5d28c5ae..3d919c6f 100644
--- a/src/types/walletTypes.ts
+++ b/src/types/walletTypes.ts
@@ -30,18 +30,16 @@
 import { AmountJson, codecForAmountJson } from "../util/amounts";
 import * as LibtoolVersion from "../util/libtoolVersion";
 import {
-  CoinRecord,
   DenominationRecord,
   ExchangeRecord,
   ExchangeWireInfo,
 } from "./dbTypes";
-import { CoinDepositPermission, ContractTerms } from "./talerTypes";
 import { Timestamp } from "../util/time";
 import {
-  typecheckedCodec,
   makeCodecForObject,
   codecForString,
   makeCodecOptional,
+  Codec,
 } from "../util/codec";
 
 /**
@@ -261,16 +259,14 @@ export interface CreateReserveRequest {
   bankWithdrawStatusUrl?: string;
 }
 
-export const codecForCreateReserveRequest = () =>
-  typecheckedCodec<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"),
-  );
+      .build("CreateReserveRequest");
 
 /**
  * Request to mark a reserve as confirmed.
@@ -283,12 +279,10 @@ export interface ConfirmReserveRequest {
   reservePub: string;
 }
 
-export const codecForConfirmReserveRequest = () =>
-  typecheckedCodec<ConfirmReserveRequest>(
+export const codecForConfirmReserveRequest = (): Codec<ConfirmReserveRequest> 
=>
     makeCodecForObject<ConfirmReserveRequest>()
       .property("reservePub", codecForString)
-      .build("ConfirmReserveRequest"),
-  );
+      .build("ConfirmReserveRequest");
 
 /**
  * Wire coins to the user's own bank account.
diff --git a/src/util/amounts.ts b/src/util/amounts.ts
index f0a4f1d7..da1c1923 100644
--- a/src/util/amounts.ts
+++ b/src/util/amounts.ts
@@ -22,10 +22,10 @@
  * Imports.
  */
 import {
-  typecheckedCodec,
   makeCodecForObject,
   codecForString,
   codecForNumber,
+  Codec,
 } from "./codec";
 
 /**
@@ -66,14 +66,12 @@ export interface AmountJson {
   readonly currency: string;
 }
 
-export const codecForAmountJson = () =>
-  typecheckedCodec<AmountJson>(
+export const codecForAmountJson = (): Codec<AmountJson> =>
     makeCodecForObject<AmountJson>()
       .property("currency", codecForString)
       .property("value", codecForNumber)
       .property("fraction", codecForNumber)
-      .build("AmountJson"),
-  );
+      .build("AmountJson");
 
 /**
  * Result of a possibly overflowing operation.
@@ -100,7 +98,7 @@ export function getZero(currency: string): AmountJson {
   };
 }
 
-export function sum(amounts: AmountJson[]) {
+export function sum(amounts: AmountJson[]): Result {
   if (amounts.length <= 0) {
     throw Error("can't sum zero amounts");
   }
@@ -287,7 +285,7 @@ export function parseOrThrow(s: string): AmountJson {
  * Convert a float to a Taler amount.
  * Loss of precision possible.
  */
-export function fromFloat(floatVal: number, currency: string) {
+export function fromFloat(floatVal: number, currency: string): AmountJson {
   return {
     currency,
     fraction: Math.floor((floatVal - Math.floor(floatVal)) * fractionalBase),
diff --git a/src/util/asyncMemo.ts b/src/util/asyncMemo.ts
index 84fe6b80..6e88081b 100644
--- a/src/util/asyncMemo.ts
+++ b/src/util/asyncMemo.ts
@@ -24,7 +24,7 @@ export class AsyncOpMemoMap<T> {
   private n = 0;
   private memoMap: { [k: string]: MemoEntry<T> } = {};
 
-  private cleanUp(key: string, n: number) {
+  private cleanUp(key: string, n: number): void {
     const r = this.memoMap[key];
     if (r && r.n === n) {
       delete this.memoMap[key];
@@ -48,7 +48,7 @@ export class AsyncOpMemoMap<T> {
       this.cleanUp(key, n);
     });
   }
-  clear() {
+  clear(): void {
     this.memoMap = {};
   }
 }
@@ -57,7 +57,7 @@ export class AsyncOpMemoSingle<T> {
   private n = 0;
   private memoEntry: MemoEntry<T> | undefined;
 
-  private cleanUp(n: number) {
+  private cleanUp(n: number): void {
     if (this.memoEntry && this.memoEntry.n === n) {
       this.memoEntry = undefined;
     }
@@ -81,7 +81,7 @@ export class AsyncOpMemoSingle<T> {
     };
     return p;
   }
-  clear() {
+  clear(): void {
     this.memoEntry = undefined;
   }
 }
diff --git a/src/util/codec.ts b/src/util/codec.ts
index a8f49523..480e1eec 100644
--- a/src/util/codec.ts
+++ b/src/util/codec.ts
@@ -346,8 +346,4 @@ export function makeCodecOptional<V>(
       return innerCodec.decode(x, c);
     },
   };
-}
-
-export function typecheckedCodec<T = undefined>(c: Codec<T>): Codec<T> {
-  return c;
-}
+}
\ No newline at end of file
diff --git a/src/util/http.ts b/src/util/http.ts
index 1a5cb85f..3842347d 100644
--- a/src/util/http.ts
+++ b/src/util/http.ts
@@ -116,7 +116,7 @@ export class BrowserHttpLib implements HttpRequestLibrary {
             );
             return;
           }
-          const makeJson = async () => {
+          const makeJson = async (): Promise<any> => {
             let responseJson;
             try {
               responseJson = JSON.parse(myRequest.responseText);
@@ -152,15 +152,15 @@ export class BrowserHttpLib implements HttpRequestLibrary 
{
     });
   }
 
-  get(url: string, opt?: HttpRequestOptions) {
+  get(url: string, opt?: HttpRequestOptions): Promise<HttpResponse> {
     return this.req("get", url, undefined, opt);
   }
 
-  postJson(url: string, body: any, opt?: HttpRequestOptions) {
+  postJson(url: string, body: any, opt?: HttpRequestOptions): 
Promise<HttpResponse> {
     return this.req("post", url, JSON.stringify(body), opt);
   }
 
-  stop() {
+  stop(): void {
     // Nothing to do
   }
 }
diff --git a/src/util/logging.ts b/src/util/logging.ts
index 80ba344d..83e8d219 100644
--- a/src/util/logging.ts
+++ b/src/util/logging.ts
@@ -24,7 +24,7 @@ function writeNodeLog(
   tag: string,
   level: string,
   args: any[],
-) {
+): void {
   process.stderr.write(`${new Date().toISOString()} ${tag} ${level} `);
   process.stderr.write(message);
   if (args.length != 0) {
@@ -41,7 +41,7 @@ function writeNodeLog(
 export class Logger {
   constructor(private tag: string) {}
 
-  info(message: string, ...args: any[]) {
+  info(message: string, ...args: any[]): void {
     if (isNode()) {
       writeNodeLog(message, this.tag, "INFO", args);
     } else {
@@ -52,7 +52,7 @@ export class Logger {
     }
   }
 
-  warn(message: string, ...args: any[]) {
+  warn(message: string, ...args: any[]): void {
     if (isNode()) {
       writeNodeLog(message, this.tag, "WARN", args);
     } else {
@@ -63,7 +63,7 @@ export class Logger {
     }
   }
 
-  error(message: string, ...args: any[]) {
+  error(message: string, ...args: any[]): void {
     if (isNode()) {
       writeNodeLog(message, this.tag, "ERROR", args);
     } else {
@@ -74,7 +74,7 @@ export class Logger {
     }
   }
 
-  trace(message: any, ...args: any[]) {
+  trace(message: any, ...args: any[]): void {
     if (isNode()) {
       writeNodeLog(message, this.tag, "TRACE", args);
     } else {
diff --git a/src/util/query.ts b/src/util/query.ts
index 44f66865..d11b79a9 100644
--- a/src/util/query.ts
+++ b/src/util/query.ts
@@ -25,6 +25,11 @@
  */
 import { openPromise } from "./promiseUtils";
 
+/**
+ * Exception that should be thrown by client code to abort a transaction.
+ */
+export const TransactionAbort = Symbol("transaction_abort");
+
 /**
  * Definition of an object store.
  */
@@ -430,11 +435,6 @@ export function openDatabase(
   });
 }
 
-/**
- * Exception that should be thrown by client code to abort a transaction.
- */
-export const TransactionAbort = Symbol("transaction_abort");
-
 export class Database {
   constructor(private db: IDBDatabase) {}
 
diff --git a/src/util/time.ts b/src/util/time.ts
index 05188b6d..ea4f8ca8 100644
--- a/src/util/time.ts
+++ b/src/util/time.ts
@@ -36,7 +36,7 @@ export interface Duration {
 
 let timeshift = 0;
 
-export function setDangerousTimetravel(dt: number) {
+export function setDangerousTimetravel(dt: number): void {
   timeshift = dt;
 }
 
@@ -121,7 +121,7 @@ export function timestampSubtractDuraction(
   return { t_ms: Math.max(0, t1.t_ms - d.d_ms) };
 }
 
-export function stringifyTimestamp(t: Timestamp) {
+export function stringifyTimestamp(t: Timestamp): string {
   if (t.t_ms === "never") {
     return "never";
   }
@@ -142,7 +142,7 @@ export function timestampIsBetween(
   t: Timestamp,
   start: Timestamp,
   end: Timestamp,
-) {
+): boolean {
   if (timestampCmp(t, start) < 0) {
     return false;
   }
diff --git a/src/wallet-test.ts b/src/wallet-test.ts
index d1551b09..42252366 100644
--- a/src/wallet-test.ts
+++ b/src/wallet-test.ts
@@ -16,9 +16,6 @@
 
 import test from "ava";
 
-import * as dbTypes from "./types/dbTypes";
-import * as types from "./types/walletTypes";
-
 import { AmountJson } from "./util/amounts";
 import * as Amounts from "./util/amounts";
 import { selectPayCoins, AvailableCoinInfo } from "./operations/pay";
diff --git a/src/wallet.ts b/src/wallet.ts
index 063a259d..02450523 100644
--- a/src/wallet.ts
+++ b/src/wallet.ts
@@ -47,7 +47,6 @@ import {
   CurrencyRecord,
   DenominationRecord,
   ExchangeRecord,
-  ProposalRecord,
   PurchaseRecord,
   ReserveRecord,
   Stores,
@@ -155,7 +154,7 @@ export class Wallet {
     this.ws = new InternalWalletState(db, http, cryptoWorkerFactory);
   }
 
-  getExchangePaytoUri(exchangeBaseUrl: string, supportedTargetTypes: string[]) 
{
+  getExchangePaytoUri(exchangeBaseUrl: string, supportedTargetTypes: 
string[]): Promise<string> {
     return getExchangePaytoUri(this.ws, exchangeBaseUrl, supportedTargetTypes);
   }
 
@@ -371,7 +370,7 @@ export class Wallet {
    * auditors into the database, unless these defaults have
    * already been applied.
    */
-  async fillDefaults() {
+  async fillDefaults(): Promise<void> {
     await this.db.runWithWriteTransaction(
       [Stores.config, Stores.currencies],
       async (tx) => {
@@ -549,7 +548,7 @@ export class Wallet {
   async acceptExchangeTermsOfService(
     exchangeBaseUrl: string,
     etag: string | undefined,
-  ) {
+  ): Promise<void> {
     return acceptExchangeTermsOfService(this.ws, exchangeBaseUrl, etag);
   }
 
@@ -596,7 +595,7 @@ export class Wallet {
   /**
    * Stop ongoing processing.
    */
-  stop() {
+  stop(): void {
     this.stopped = true;
     this.timerGroup.stopCurrentAndFutureTimers();
     this.ws.cryptoApi.stop();
@@ -685,7 +684,7 @@ export class Wallet {
    * Inform the wallet that the status of a reserve has changed (e.g. due to a
    * confirmation from the bank.).
    */
-  public async handleNotifyReserve() {
+  public async handleNotifyReserve(): Promise<void> {
     const reserves = await this.db.iter(Stores.reserves).toArray();
     for (const r of reserves) {
       if (r.reserveStatus === ReserveRecordStatus.WAIT_CONFIRM_BANK) {
@@ -702,7 +701,7 @@ export class Wallet {
    * Remove unreferenced / expired data from the wallet's database
    * based on the current system time.
    */
-  async collectGarbage() {
+  async collectGarbage(): Promise<void> {
     // FIXME(#5845)
     // We currently do not garbage-collect the wallet database.  This might 
change
     // after the feature has been properly re-designed, and we have come up 
with a
diff --git a/src/webex/chromeBadge.ts b/src/webex/chromeBadge.ts
index 330388ca..7bc5d368 100644
--- a/src/webex/chromeBadge.ts
+++ b/src/webex/chromeBadge.ts
@@ -20,7 +20,7 @@ import { isFirefox } from "./compat";
  * Polyfill for requestAnimationFrame, which
  * doesn't work from a background page.
  */
-function rAF(cb: (ts: number) => void) {
+function rAF(cb: (ts: number) => void): void {
   window.setTimeout(() => {
     cb(performance.now());
   }, 100 /* 100 ms delay between frames */);
@@ -99,14 +99,18 @@ export class ChromeBadge {
     // size in draw() as well!
     this.canvas.width = 32;
     this.canvas.height = 32;
-    this.ctx = this.canvas.getContext("2d")!;
+    const ctx = this.canvas.getContext("2d");
+    if (!ctx) {
+      throw Error("unable to get canvas context");
+    }
+    this.ctx = ctx;
     this.draw();
   }
 
   /**
    * Draw the badge based on the current state.
    */
-  private draw() {
+  private draw(): void {
     this.ctx.setTransform(1, 0, 0, 1, 0, 0);
     this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
 
@@ -202,7 +206,7 @@ export class ChromeBadge {
     }
   }
 
-  private animate() {
+  private animate(): void {
     if (this.animationRunning) {
       return;
     }
@@ -212,7 +216,7 @@ export class ChromeBadge {
     }
     this.animationRunning = true;
     let start: number | undefined;
-    const step = (timestamp: number) => {
+    const step = (timestamp: number): void => {
       if (!this.animationRunning) {
         return;
       }
@@ -257,7 +261,7 @@ export class ChromeBadge {
    * Draw the badge such that it shows the
    * user that something happened (balance changed).
    */
-  showNotification() {
+  showNotification(): void {
     this.hasNotification = true;
     this.draw();
   }
@@ -265,12 +269,12 @@ export class ChromeBadge {
   /**
    * Draw the badge without the notification mark.
    */
-  clearNotification() {
+  clearNotification(): void {
     this.hasNotification = false;
     this.draw();
   }
 
-  startBusy() {
+  startBusy(): void {
     if (this.isBusy) {
       return;
     }
@@ -278,7 +282,7 @@ export class ChromeBadge {
     this.animate();
   }
 
-  stopBusy() {
+  stopBusy(): void {
     this.isBusy = false;
   }
 }
diff --git a/src/webex/notify.ts b/src/webex/notify.ts
index 887658ef..9fb0529d 100644
--- a/src/webex/notify.ts
+++ b/src/webex/notify.ts
@@ -47,7 +47,7 @@ const handlers: Handler[] = [];
 
 let sheet: CSSStyleSheet | null;
 
-function initStyle() {
+function initStyle(): void {
   logVerbose && console.log("taking over styles");
   const name = "taler-presence-stylesheet";
   const content = "/* Taler stylesheet controlled by JS */";
@@ -78,7 +78,7 @@ function initStyle() {
   }
 }
 
-function setStyles(installed: boolean) {
+function setStyles(installed: boolean): void {
   if (!sheet || !sheet.cssRules) {
     return;
   }
@@ -93,7 +93,7 @@ function setStyles(installed: boolean) {
   }
 }
 
-function onceOnComplete(cb: () => void) {
+function onceOnComplete(cb: () => void): void {
   if (document.readyState === "complete") {
     cb();
   } else {
@@ -105,7 +105,7 @@ function onceOnComplete(cb: () => void) {
   }
 }
 
-function init() {
+function init(): void {
   onceOnComplete(() => {
     if (document.documentElement.getAttribute("data-taler-nojs")) {
       initStyle();
@@ -129,13 +129,13 @@ function init() {
 
 type HandlerFn = (detail: any, sendResponse: (msg: any) => void) => void;
 
-function registerHandlers() {
+function registerHandlers(): void {
   /**
    * Add a handler for a DOM event, which automatically
    * handles adding sequence numbers to responses.
    */
-  function addHandler(type: string, handler: HandlerFn) {
-    const handlerWrap = (e: Event) => {
+  function addHandler(type: string, handler: HandlerFn): void {
+    const handlerWrap = (e: Event): void => {
       if (!(e instanceof Event)) {
         console.log("unexpected event", e);
         throw Error(`invariant violated`);
@@ -154,7 +154,7 @@ function registerHandlers() {
         callId = e.detail.callId;
         detail = e.detail;
       }
-      const responder = (msg?: any) => {
+      const responder = (msg?: any): void => {
         const fullMsg = Object.assign({}, msg, { callId });
         let opts = { detail: fullMsg };
         if ("function" === typeof cloneInto) {
diff --git a/src/webex/pages/add-auditor.tsx b/src/webex/pages/add-auditor.tsx
index dbe84cde..4e3f8615 100644
--- a/src/webex/pages/add-auditor.tsx
+++ b/src/webex/pages/add-auditor.tsx
@@ -31,10 +31,10 @@ interface ConfirmAuditorProps {
   expirationStamp: number;
 }
 
-function ConfirmAuditor(props: ConfirmAuditorProps) {
+function ConfirmAuditor(props: ConfirmAuditorProps): JSX.Element {
   const [addDone, setAddDone] = useState(false);
 
-  const add = async () => {
+  const add = async (): Promise<void> => {
     const currencies = await getCurrencies();
     let currency: CurrencyRecord | undefined;
 
diff --git a/src/webex/pages/benchmark.tsx b/src/webex/pages/benchmark.tsx
index bf4c4b04..eb7193e0 100644
--- a/src/webex/pages/benchmark.tsx
+++ b/src/webex/pages/benchmark.tsx
@@ -34,7 +34,7 @@ interface BenchmarkRunnerState {
   running: boolean;
 }
 
-function BenchmarkDisplay(props: BenchmarkRunnerState) {
+function BenchmarkDisplay(props: BenchmarkRunnerState): JSX.Element {
   const result = props.result;
   if (!result) {
     if (props.running) {
@@ -55,7 +55,7 @@ function BenchmarkDisplay(props: BenchmarkRunnerState) {
           {Object.keys(result.time)
             .sort()
             .map((k) => (
-              <tr>
+              <tr key={k}>
                 <td>{k}</td>
                 <td>{result.time[k] / result.repetitions}</td>
               </tr>
@@ -75,13 +75,13 @@ class BenchmarkRunner extends React.Component<any, 
BenchmarkRunnerState> {
     };
   }
 
-  async run() {
+  async run(): Promise<void> {
     this.setState({ result: undefined, running: true });
     const result = await wxApi.benchmarkCrypto(this.state.repetitions);
     this.setState({ result, running: false });
   }
 
-  render() {
+  render(): JSX.Element {
     return (
       <div>
         <label>Repetitions:</label>
@@ -99,6 +99,6 @@ class BenchmarkRunner extends React.Component<any, 
BenchmarkRunnerState> {
   }
 }
 
-export function makeBenchmarkPage() {
+export function makeBenchmarkPage(): JSX.Element {
   return <BenchmarkRunner />;
 }
diff --git a/src/webex/pages/pay.tsx b/src/webex/pages/pay.tsx
index 09aa595c..e3dd630b 100644
--- a/src/webex/pages/pay.tsx
+++ b/src/webex/pages/pay.tsx
@@ -34,7 +34,7 @@ import React, { useState, useEffect } from "react";
 import * as Amounts from "../../util/amounts";
 import { codecForContractTerms, ContractTerms } from "../../types/talerTypes";
 
-function TalerPayDialog({ talerPayUri }: { talerPayUri: string }) {
+function TalerPayDialog({ talerPayUri }: { talerPayUri: string }): JSX.Element 
{
   const [payStatus, setPayStatus] = useState<PreparePayResult | undefined>();
   const [payErrMsg, setPayErrMsg] = useState<string | undefined>("");
   const [numTries, setNumTries] = useState(0);
@@ -42,7 +42,7 @@ function TalerPayDialog({ talerPayUri }: { talerPayUri: 
string }) {
   let totalFees: Amounts.AmountJson | undefined = undefined;
 
   useEffect(() => {
-    const doFetch = async () => {
+    const doFetch = async (): Promise<void> => {
       const p = await wxApi.preparePay(talerPayUri);
       setPayStatus(p);
     };
@@ -108,7 +108,7 @@ function TalerPayDialog({ talerPayUri }: { talerPayUri: 
string }) {
     <strong>{renderAmount(Amounts.parseOrThrow(contractTerms.amount))}</strong>
   );
 
-  const doPayment = async () => {
+  const doPayment = async (): Promise<void> => {
     if (payStatus.status !== "payment-possible") {
       throw Error(`invalid state: ${payStatus.status}`);
     }
@@ -178,11 +178,11 @@ function TalerPayDialog({ talerPayUri }: { talerPayUri: 
string }) {
   );
 }
 
-export function makePayPage() {
+export function makePayPage(): JSX.Element {
   const url = new URL(document.location.href);
   const talerPayUri = url.searchParams.get("talerPayUri");
   if (!talerPayUri) {
     throw Error("invalid parameter");
   }
   return <TalerPayDialog talerPayUri={talerPayUri} />;
-}
\ No newline at end of file
+}
diff --git a/src/webex/pages/popup.tsx b/src/webex/pages/popup.tsx
index 6cd7242f..c2f050e2 100644
--- a/src/webex/pages/popup.tsx
+++ b/src/webex/pages/popup.tsx
@@ -46,7 +46,7 @@ import { Timestamp } from "../../util/time";
 
 function onUpdateNotification(f: () => void): () => void {
   const port = chrome.runtime.connect({ name: "notifications" });
-  const listener = () => {
+  const listener = (): void => {
     f();
   };
   port.onMessage.addListener(listener);
@@ -75,7 +75,7 @@ class Router extends React.Component<any, any> {
 
   private static routeHandlers: any[] = [];
 
-  componentWillMount() {
+  componentWillMount(): void {
     console.log("router mounted");
     window.onhashchange = () => {
       this.setState({});
@@ -85,10 +85,6 @@ class Router extends React.Component<any, any> {
     };
   }
 
-  componentWillUnmount() {
-    console.log("router unmounted");
-  }
-
   render(): JSX.Element {
     const route = window.location.hash.substring(1);
     console.log("rendering route", route);
@@ -120,12 +116,12 @@ interface TabProps {
   children?: React.ReactNode;
 }
 
-function Tab(props: TabProps) {
+function Tab(props: TabProps): JSX.Element {
   let cssClass = "";
   if (props.target === Router.getRoute()) {
     cssClass = "active";
   }
-  const onClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
+  const onClick = (e: React.MouseEvent<HTMLAnchorElement>): void => {
     Router.setRoute(props.target);
     e.preventDefault();
   };
@@ -139,19 +135,19 @@ function Tab(props: TabProps) {
 class WalletNavBar extends React.Component<any, any> {
   private cancelSubscription: any;
 
-  componentWillMount() {
+  componentWillMount(): void {
     this.cancelSubscription = Router.onRoute(() => {
       this.setState({});
     });
   }
 
-  componentWillUnmount() {
+  componentWillUnmount(): void {
     if (this.cancelSubscription) {
       this.cancelSubscription();
     }
   }
 
-  render() {
+  render(): JSX.Element {
     console.log("rendering nav bar");
     return (
       <div className="nav" id="header">
@@ -163,20 +159,6 @@ class WalletNavBar extends React.Component<any, any> {
   }
 }
 
-function ExtensionLink(props: any) {
-  const onClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
-    chrome.tabs.create({
-      url: chrome.extension.getURL(props.target),
-    });
-    e.preventDefault();
-  };
-  return (
-    <a onClick={onClick} href={props.target}>
-      {props.children}
-    </a>
-  );
-}
-
 /**
  * Render an amount as a large number with a small currency symbol.
  */
@@ -190,7 +172,7 @@ function bigAmount(amount: AmountJson): JSX.Element {
   );
 }
 
-function EmptyBalanceView() {
+function EmptyBalanceView(): JSX.Element {
   return (
     <i18n.Translate wrap="p">
       You have no balance to show. Need some{" "}
@@ -205,12 +187,12 @@ class WalletBalanceView extends React.Component<any, any> 
{
   private canceler: (() => void) | undefined = undefined;
   private unmount = false;
 
-  componentWillMount() {
+  componentWillMount(): void {
     this.canceler = onUpdateNotification(() => this.updateBalance());
     this.updateBalance();
   }
 
-  componentWillUnmount() {
+  componentWillUnmount(): void {
     console.log("component WalletBalanceView will unmount");
     if (this.canceler) {
       this.canceler();
@@ -218,7 +200,7 @@ class WalletBalanceView extends React.Component<any, any> {
     this.unmount = true;
   }
 
-  async updateBalance() {
+  async updateBalance(): Promise<void> {
     let balance: WalletBalance;
     try {
       balance = await wxApi.getBalance();
@@ -325,11 +307,11 @@ class WalletBalanceView extends React.Component<any, any> 
{
   }
 }
 
-function Icon({ l }: { l: string }) {
+function Icon({ l }: { l: string }): JSX.Element {
   return <div className={"icon"}>{l}</div>;
 }
 
-function formatAndCapitalize(text: string) {
+function formatAndCapitalize(text: string): string {
   text = text.replace("-", " ");
   text = text.replace(/^./, text[0].toUpperCase());
   return text;
@@ -357,8 +339,8 @@ function HistoryItem({
   timestamp,
   icon,
   negative = false,
-}: HistoryItemProps) {
-  function formatDate(timestamp: number | "never") {
+}: HistoryItemProps): JSX.Element {
+  function formatDate(timestamp: number | "never"): string | null {
     if (timestamp !== "never") {
       const itemDate = moment(timestamp);
       if (itemDate.isBetween(moment().subtract(2, "days"), moment())) {
@@ -444,7 +426,7 @@ function parseSummary(summary: string) {
   };
 }
 
-function formatHistoryItem(historyItem: HistoryEvent) {
+function formatHistoryItem(historyItem: HistoryEvent): JSX.Element {
   switch (historyItem.type) {
     case "refreshed": {
       return (
@@ -637,7 +619,7 @@ function formatHistoryItem(historyItem: HistoryEvent) {
   }
 }
 
-const HistoryComponent = (props: any) => {
+const HistoryComponent = (props: any): JSX.Element => {
   const record = props.record;
   return formatHistoryItem(record);
 };
@@ -655,18 +637,18 @@ class WalletHistory extends React.Component<any, any> {
     "exchange-added",
   ];
 
-  componentWillMount() {
+  componentWillMount(): void {
     this.update();
     this.setState({ filter: true });
     onUpdateNotification(() => this.update());
   }
 
-  componentWillUnmount() {
+  componentWillUnmount(): void {
     console.log("history component unmounted");
     this.unmounted = true;
   }
 
-  update() {
+  update(): void {
     chrome.runtime.sendMessage({ type: "get-history" }, (resp) => {
       if (this.unmounted) {
         return;
@@ -727,7 +709,7 @@ class WalletHistory extends React.Component<any, any> {
   }
 }
 
-function reload() {
+function reload(): void {
   try {
     chrome.runtime.reload();
     window.close();
@@ -736,7 +718,7 @@ function reload() {
   }
 }
 
-function confirmReset() {
+function confirmReset(): void {
   if (
     confirm(
       "Do you want to IRREVOCABLY DESTROY everything inside your" +
@@ -748,7 +730,7 @@ function confirmReset() {
   }
 }
 
-function WalletDebug(props: any) {
+function WalletDebug(props: any): JSX.Element {
   return (
     <div>
       <p>Debug tools:</p>
@@ -791,7 +773,7 @@ function openTab(page: string) {
   };
 }
 
-function WalletPopup() {
+function WalletPopup(): JSX.Element {
   return (
     <div>
       <WalletNavBar />
@@ -806,7 +788,7 @@ function WalletPopup() {
   );
 }
 
-export function createPopup() {
+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 8263ceac..4a13317c 100644
--- a/src/webex/pages/refund.tsx
+++ b/src/webex/pages/refund.tsx
@@ -21,13 +21,12 @@
  */
 
 import React, { useEffect, useState } from "react";
-import ReactDOM from "react-dom";
 
 import * as wxApi from "../wxApi";
 import { PurchaseDetails } from "../../types/walletTypes";
 import { AmountView } from "../renderHtml";
 
-function RefundStatusView(props: { talerRefundUri: string }) {
+function RefundStatusView(props: { talerRefundUri: string }): JSX.Element {
   const [applied, setApplied] = useState(false);
   const [purchaseDetails, setPurchaseDetails] = useState<
     PurchaseDetails | undefined
@@ -35,7 +34,7 @@ function RefundStatusView(props: { talerRefundUri: string }) {
   const [errMsg, setErrMsg] = useState<string | undefined>(undefined);
 
   useEffect(() => {
-    const doFetch = async () => {
+    const doFetch = async (): Promise<void> => {
       try {
         const hc = await wxApi.applyRefund(props.talerRefundUri);
         setApplied(true);
@@ -73,19 +72,17 @@ function RefundStatusView(props: { talerRefundUri: string 
}) {
   );
 }
 
-export function createRefundPage() {
+export function createRefundPage(): JSX.Element {
   const url = new URL(document.location.href);
 
   const container = document.getElementById("container");
   if (!container) {
-    console.error("fatal: can't mount component, container missing");
-    return;
+    throw Error("fatal: can't mount component, container missing")
   }
 
   const talerRefundUri = url.searchParams.get("talerRefundUri");
   if (!talerRefundUri) {
-    console.error("taler refund URI requred");
-    return;
+    throw Error("taler refund URI requred");
   }
 
   return <RefundStatusView talerRefundUri={talerRefundUri} />;
diff --git a/src/webex/pages/return-coins.tsx b/src/webex/pages/return-coins.tsx
index 06a3ba16..7d759705 100644
--- a/src/webex/pages/return-coins.tsx
+++ b/src/webex/pages/return-coins.tsx
@@ -38,7 +38,6 @@ import { getBalance, getSenderWireInfos, returnCoins } from 
"../wxApi";
 import { renderAmount } from "../renderHtml";
 
 import * as React from "react";
-import * as ReactDOM from "react-dom";
 
 interface ReturnSelectionItemProps extends ReturnSelectionListProps {
   exchangeUrl: string;
@@ -129,7 +128,7 @@ class ReturnSelectionItem extends React.Component<
     );
   }
 
-  select() {
+  select(): void {
     let val: number;
     let selectedWire: number;
     try {
@@ -188,7 +187,7 @@ interface ReturnConfirmationProps {
 }
 
 class ReturnConfirmation extends React.Component<ReturnConfirmationProps, {}> {
-  render() {
+  render(): JSX.Element {
     return (
       <div>
         <p>
@@ -238,7 +237,7 @@ class ReturnCoins extends React.Component<{}, 
ReturnCoinsState> {
     this.state = {} as any;
   }
 
-  async update() {
+  async update(): Promise<void> {
     const balance = await getBalance();
     const senderWireInfos = await getSenderWireInfos();
     console.log("got swi", senderWireInfos);
@@ -246,11 +245,11 @@ class ReturnCoins extends React.Component<{}, 
ReturnCoinsState> {
     this.setState({ balance, senderWireInfos });
   }
 
-  selectDetail(d: SelectedDetail) {
+  selectDetail(d: SelectedDetail): void {
     this.setState({ selectedReturn: d });
   }
 
-  async confirm() {
+  async confirm(): Promise<void> {
     const selectedReturn = this.state.selectedReturn;
     if (!selectedReturn) {
       return;
@@ -263,14 +262,14 @@ class ReturnCoins extends React.Component<{}, 
ReturnCoinsState> {
     });
   }
 
-  async cancel() {
+  async cancel(): Promise<void> {
     this.setState({
       selectedReturn: undefined,
       lastConfirmedDetail: undefined,
     });
   }
 
-  render() {
+  render(): JSX.Element {
     const balance = this.state.balance;
     const senderWireInfos = this.state.senderWireInfos;
     if (!balance || !senderWireInfos) {
@@ -310,6 +309,6 @@ class ReturnCoins extends React.Component<{}, 
ReturnCoinsState> {
   }
 }
 
-export function createReturnCoinsPage() {
+export function createReturnCoinsPage(): JSX.Element {
   return <ReturnCoins />;
 }
diff --git a/src/webex/pages/tip.tsx b/src/webex/pages/tip.tsx
index 10e12d59..9c797f50 100644
--- a/src/webex/pages/tip.tsx
+++ b/src/webex/pages/tip.tsx
@@ -22,30 +22,25 @@
  */
 
 import * as React from "react";
-import * as ReactDOM from "react-dom";
 
-import * as i18n from "../i18n";
-
-import { acceptTip, getReserveCreationInfo, getTipStatus } from "../wxApi";
+import { acceptTip, getTipStatus } from "../wxApi";
 
 import {
-  WithdrawDetailView,
   renderAmount,
   ProgressButton,
 } from "../renderHtml";
 
-import * as Amounts from "../../util/amounts";
 import { useState, useEffect } from "react";
 import { TipStatus } from "../../types/walletTypes";
 
-function TipDisplay(props: { talerTipUri: string }) {
+function TipDisplay(props: { talerTipUri: string }): JSX.Element {
   const [tipStatus, setTipStatus] = useState<TipStatus | undefined>(undefined);
   const [discarded, setDiscarded] = useState(false);
   const [loading, setLoading] = useState(false);
   const [finished, setFinished] = useState(false);
 
   useEffect(() => {
-    const doFetch = async () => {
+    const doFetch = async (): Promise<void> => {
       const ts = await getTipStatus(props.talerTipUri);
       setTipStatus(ts);
     };
@@ -53,7 +48,7 @@ function TipDisplay(props: { talerTipUri: string }) {
   }, []);
 
   if (discarded) {
-    return <span>You've discarded the tip.</span>;
+    return <span>You&apos;ve discarded the tip.</span>;
   }
 
   if (finished) {
@@ -64,11 +59,11 @@ function TipDisplay(props: { talerTipUri: string }) {
     return <span>Loading ...</span>;
   }
 
-  const discard = () => {
+  const discard = (): void => {
     setDiscarded(true);
   };
 
-  const accept = async () => {
+  const accept = async (): Promise<void> => {
     setLoading(true);
     await acceptTip(tipStatus.tipId);
     setFinished(true);
@@ -100,7 +95,7 @@ function TipDisplay(props: { talerTipUri: string }) {
   );
 }
 
-export function createTipPage() {
+export function createTipPage(): JSX.Element {
     const url = new URL(document.location.href);
     const talerTipUri = url.searchParams.get("talerTipUri");
     if (typeof talerTipUri !== "string") {
diff --git a/src/webex/pages/welcome.tsx b/src/webex/pages/welcome.tsx
index 8510ad38..a99cadb0 100644
--- a/src/webex/pages/welcome.tsx
+++ b/src/webex/pages/welcome.tsx
@@ -25,7 +25,7 @@ import { getDiagnostics } from "../wxApi";
 import { PageLink } from "../renderHtml";
 import { WalletDiagnostics } from "../../types/walletTypes";
 
-function Diagnostics() {
+function Diagnostics(): JSX.Element {
   const [timedOut, setTimedOut] = useState(false);
   const [diagnostics, setDiagnostics] = useState<WalletDiagnostics | 
undefined>(
     undefined,
@@ -39,7 +39,7 @@ function Diagnostics() {
         setTimedOut(true);
       }
     }, 1000);
-    const doFetch = async () => {
+    const doFetch = async (): Promise<void> => {
       const d = await getDiagnostics();
       console.log("got diagnostics", d);
       gotDiagnostics = true;
@@ -95,7 +95,7 @@ function Diagnostics() {
   return <p>Running diagnostics ...</p>;
 }
 
-function Welcome() {
+function Welcome(): JSX.Element {
   return (
     <>
       <p>Thank you for installing the wallet.</p>
@@ -110,6 +110,6 @@ function Welcome() {
   );
 }
 
-export function createWelcomePage() {
+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 e071dc8b..9020ddb0 100644
--- a/src/webex/pages/withdraw.tsx
+++ b/src/webex/pages/withdraw.tsx
@@ -28,10 +28,9 @@ import { WithdrawDetails } from "../../types/walletTypes";
 import { WithdrawDetailView, renderAmount } from "../renderHtml";
 
 import React, { useState, useEffect } from "react";
-import * as ReactDOM from "react-dom";
 import { getWithdrawDetails, acceptWithdrawal } from "../wxApi";
 
-function NewExchangeSelection(props: { talerWithdrawUri: string }) {
+function NewExchangeSelection(props: { talerWithdrawUri: string }): 
JSX.Element {
   const [details, setDetails] = useState<WithdrawDetails | undefined>();
   const [selectedExchange, setSelectedExchange] = useState<
     string | undefined
@@ -43,7 +42,7 @@ function NewExchangeSelection(props: { talerWithdrawUri: 
string }) {
   const [errMsg, setErrMsg] = useState<string | undefined>("");
 
   useEffect(() => {
-    const fetchData = async () => {
+    const fetchData = async (): Promise<void> => {
       console.log("getting from", talerWithdrawUri);
       let d: WithdrawDetails | undefined = undefined;
       try {
@@ -145,7 +144,7 @@ function NewExchangeSelection(props: { talerWithdrawUri: 
string }) {
     );
   }
 
-  const accept = async () => {
+  const accept = async (): Promise<void> => {
     console.log("accepting exchange", selectedExchange);
     const res = await acceptWithdrawal(talerWithdrawUri, selectedExchange!);
     console.log("accept withdrawal response", res);
@@ -197,27 +196,7 @@ function NewExchangeSelection(props: { talerWithdrawUri: 
string }) {
   );
 }
 
-async function main() {
-  try {
-    const url = new URL(document.location.href);
-    const talerWithdrawUri = url.searchParams.get("talerWithdrawUri");
-    if (!talerWithdrawUri) {
-      throw Error("withdraw URI required");
-    }
-
-    ReactDOM.render(
-      <NewExchangeSelection talerWithdrawUri={talerWithdrawUri} />,
-      document.getElementById("exchange-selection")!,
-    );
-  } catch (e) {
-    // TODO: provide more context information, maybe factor it out into a
-    // TODO:generic error reporting function or component.
-    document.body.innerText = i18n.str`Fatal error: "${e.message}".`;
-    console.error("got error", e);
-  }
-}
-
-export function createWithdrawPage() {
+export function createWithdrawPage(): JSX.Element {
   const url = new URL(document.location.href);
     const talerWithdrawUri = url.searchParams.get("talerWithdrawUri");
     if (!talerWithdrawUri) {
diff --git a/src/webex/renderHtml.tsx b/src/webex/renderHtml.tsx
index b6ff1248..8fc6a6a6 100644
--- a/src/webex/renderHtml.tsx
+++ b/src/webex/renderHtml.tsx
@@ -29,14 +29,13 @@ import { DenominationRecord } from "../types/dbTypes";
 import { ExchangeWithdrawDetails } from "../types/walletTypes";
 import * as i18n from "./i18n";
 import React from "react";
-import ReactDOM from "react-dom";
 import { stringifyTimestamp } from "../util/time";
 
 /**
  * Render amount as HTML, which non-breaking space between
  * decimal value and currency.
  */
-export function renderAmount(amount: AmountJson | string) {
+export function renderAmount(amount: AmountJson | string): JSX.Element {
   let a;
   if (typeof amount === "string") {
     a = Amounts.parse(amount);
@@ -54,14 +53,17 @@ export function renderAmount(amount: AmountJson | string) {
   );
 }
 
-export const AmountView = ({ amount }: { amount: AmountJson | string }) =>
-  renderAmount(amount);
+export const AmountView = ({
+  amount,
+}: {
+  amount: AmountJson | string;
+}): JSX.Element => renderAmount(amount);
 
 /**
  * Abbreviate a string to a given length, and show the full
  * string on hover as a tooltip.
  */
-export function abbrev(s: string, n = 5) {
+export function abbrev(s: string, n = 5): JSX.Element {
   let sAbbrev = s;
   if (s.length > n) {
     sAbbrev = s.slice(0, n) + "..";
@@ -94,12 +96,12 @@ export class Collapsible extends React.Component<
     super(props);
     this.state = { collapsed: props.initiallyCollapsed };
   }
-  render() {
-    const doOpen = (e: any) => {
+  render(): JSX.Element {
+    const doOpen = (e: any): void => {
       this.setState({ collapsed: false });
       e.preventDefault();
     };
-    const doClose = (e: any) => {
+    const doClose = (e: any): void => {
       this.setState({ collapsed: true });
       e.preventDefault();
     };
@@ -188,7 +190,7 @@ function FeeDetailsView(props: {
     countByPub[x.denomPub] = c;
   });
 
-  function row(denom: DenominationRecord) {
+  function row(denom: DenominationRecord): JSX.Element {
     return (
       <tr>
         <td>{countByPub[denom.denomPub] + "x"}</td>
@@ -296,7 +298,7 @@ interface ExpanderTextProps {
 /**
  * Show a heading with a toggle to show/hide the expandable content.
  */
-export function ExpanderText({ text }: ExpanderTextProps) {
+export function ExpanderText({ text }: ExpanderTextProps): JSX.Element {
   return <span>{text}</span>;
 }
 
@@ -310,7 +312,7 @@ export function ProgressButton(
       React.ButtonHTMLAttributes<HTMLButtonElement>,
       HTMLButtonElement
     >,
-) {
+): JSX.Element {
   return (
     <button
       className="pure-button pure-button-primary"
@@ -330,7 +332,9 @@ export function ProgressButton(
   );
 }
 
-export function PageLink(props: React.PropsWithChildren<{ pageName: string }>) 
{
+export function PageLink(
+  props: React.PropsWithChildren<{ pageName: string }>,
+): JSX.Element {
   const url = chrome.extension.getURL(`/src/webex/pages/${props.pageName}`);
   return (
     <a className="actionLink" href={url} target="_blank">
diff --git a/src/webex/wxApi.ts b/src/webex/wxApi.ts
index a530b750..07b223c8 100644
--- a/src/webex/wxApi.ts
+++ b/src/webex/wxApi.ts
@@ -38,6 +38,9 @@ import {
   WalletBalance,
   PurchaseDetails,
   WalletDiagnostics,
+  WithdrawDetails,
+  PreparePayResult,
+  AcceptWithdrawalResponse,
 } from "../types/walletTypes";
 
 import { MessageMap, MessageType } from "./messages";
@@ -271,7 +274,7 @@ export function applyRefund(refundUrl: string): 
Promise<string> {
 /**
  * Abort a failed payment and try to get a refund.
  */
-export function abortFailedPayment(contractTermsHash: string) {
+export function abortFailedPayment(contractTermsHash: string): Promise<void> {
   return callBackend("abort-failed-payment", { contractTermsHash });
 }
 
@@ -288,7 +291,7 @@ export function benchmarkCrypto(repetitions: number): 
Promise<BenchmarkResult> {
 export function getWithdrawDetails(
   talerWithdrawUri: string,
   maybeSelectedExchange: string | undefined,
-) {
+): Promise<WithdrawDetails> {
   return callBackend("get-withdraw-details", {
     talerWithdrawUri,
     maybeSelectedExchange,
@@ -298,7 +301,7 @@ export function getWithdrawDetails(
 /**
  * Get details about a pay operation.
  */
-export function preparePay(talerPayUri: string) {
+export function preparePay(talerPayUri: string): Promise<PreparePayResult> {
   return callBackend("prepare-pay", { talerPayUri });
 }
 
@@ -308,7 +311,7 @@ export function preparePay(talerPayUri: string) {
 export function acceptWithdrawal(
   talerWithdrawUri: string,
   selectedExchange: string,
-) {
+): Promise<AcceptWithdrawalResponse> {
   return callBackend("accept-withdrawal", {
     talerWithdrawUri,
     selectedExchange,
diff --git a/src/webex/wxBackend.ts b/src/webex/wxBackend.ts
index ef4715dc..f26c14d3 100644
--- a/src/webex/wxBackend.ts
+++ b/src/webex/wxBackend.ts
@@ -40,7 +40,6 @@ import { BrowserHttpLib } from "../util/http";
 import { OpenedPromise, openPromise } from "../util/promiseUtils";
 import { classifyTalerUri, TalerUriType } from "../util/taleruri";
 import { Wallet } from "../wallet";
-import { ChromeBadge } from "./chromeBadge";
 import { isFirefox } from "./compat";
 import { MessageType } from "./messages";
 import * as wxApi from "./wxApi";
@@ -49,6 +48,21 @@ import { Database } from "../util/query";
 
 const NeedsWallet = Symbol("NeedsWallet");
 
+/**
+ * Currently active wallet instance.  Might be unloaded and
+ * re-instantiated when the database is reset.
+ */
+let currentWallet: Wallet | undefined;
+
+let currentDatabase: IDBDatabase | undefined;
+
+/**
+ * Last version if an outdated DB, if applicable.
+ */
+let outdatedDbVersion: number | undefined;
+
+const walletInit: OpenedPromise<void> = openPromise<void>();
+
 async function handleMessage(
   sender: MessageSender,
   type: MessageType,
@@ -57,14 +71,12 @@ async function handleMessage(
   function assertNotFound(t: never): never {
     console.error(`Request type ${t as string} unknown`);
     console.error(`Request detail was ${detail}`);
-    return (
-      {
-        error: {
-          message: `request type ${t as string} unknown`,
-          requestType: type,
-        },
-      } as never
-    );
+    return {
+      error: {
+        message: `request type ${t as string} unknown`,
+        requestType: type,
+      },
+    } as never;
   }
   function needsWallet(): Wallet {
     if (!currentWallet) {
@@ -320,7 +332,7 @@ function getTab(tabId: number): Promise<chrome.tabs.Tab> {
   });
 }
 
-function setBadgeText(options: chrome.browserAction.BadgeTextDetails) {
+function setBadgeText(options: chrome.browserAction.BadgeTextDetails): void {
   // not supported by all browsers ...
   if (chrome && chrome.browserAction && chrome.browserAction.setBadgeText) {
     chrome.browserAction.setBadgeText(options);
@@ -331,9 +343,12 @@ function setBadgeText(options: 
chrome.browserAction.BadgeTextDetails) {
 
 function waitMs(timeoutMs: number): Promise<void> {
   return new Promise((resolve, reject) => {
-    chrome.extension
-      .getBackgroundPage()!
-      .setTimeout(() => resolve(), timeoutMs);
+    const bgPage = chrome.extension.getBackgroundPage();
+    if (!bgPage) {
+      reject("fatal: no background page");
+      return;
+    }
+    bgPage.setTimeout(() => resolve(), timeoutMs);
   });
 }
 
@@ -359,7 +374,7 @@ function makeSyncWalletRedirect(
   if (isFirefox()) {
     // Some platforms don't support the sync redirect (yet), so fall back to
     // async redirect after a timeout.
-    const doit = async () => {
+    const doit = async (): Promise<void> => {
       await waitMs(150);
       const tab = await getTab(tabId);
       if (tab.url === oldUrl) {
@@ -371,29 +386,13 @@ function makeSyncWalletRedirect(
   return { redirectUrl: outerUrl.href };
 }
 
-/**
- * Currently active wallet instance.  Might be unloaded and
- * re-instantiated when the database is reset.
- */
-let currentWallet: Wallet | undefined;
-
-let currentDatabase: IDBDatabase | undefined;
-
-/**
- * Last version if an outdated DB, if applicable.
- */
-let outdatedDbVersion: number | undefined;
-
-const walletInit: OpenedPromise<void> = openPromise<void>();
-
-async function reinitWallet() {
+async function reinitWallet(): Promise<void> {
   if (currentWallet) {
     currentWallet.stop();
     currentWallet = undefined;
   }
   currentDatabase = undefined;
   setBadgeText({ text: "" });
-  const badge = new ChromeBadge();
   try {
     currentDatabase = await openTalerDatabase(indexedDB, reinitWallet);
   } catch (e) {
@@ -461,7 +460,7 @@ try {
  *
  * Sets up all event handlers and other machinery.
  */
-export async function wxMain() {
+export async function wxMain(): Promise<void> {
   // Explicitly unload the extension page as soon as an update is available,
   // so the update gets installed as soon as possible.
   chrome.runtime.onUpdateAvailable.addListener((details) => {
@@ -505,8 +504,13 @@ export async function wxMain() {
 
   chrome.tabs.onRemoved.addListener((tabId, changeInfo) => {
     const tt = tabTimers[tabId] || [];
+    const bgPage = chrome.extension.getBackgroundPage();
+    if (!bgPage) {
+      console.error("background page unavailable");
+      return;
+    }
     for (const t of tt) {
-      chrome.extension.getBackgroundPage()!.clearTimeout(t);
+      bgPage.clearTimeout(t);
     }
   });
   chrome.tabs.onUpdated.addListener((tabId, changeInfo) => {
@@ -515,12 +519,7 @@ export async function wxMain() {
     }
     const timers: number[] = [];
 
-    const addRun = (dt: number) => {
-      const id = chrome.extension.getBackgroundPage()!.setTimeout(run, dt);
-      timers.push(id);
-    };
-
-    const run = () => {
+    const run = (): void => {
       timers.shift();
       chrome.tabs.get(tabId, (tab) => {
         if (chrome.runtime.lastError) {
@@ -538,10 +537,20 @@ export async function wxMain() {
             document.dispatchEvent(new Event("taler-probe-result"));
           }
         `;
-        injectScript(tab.id!, { code, runAt: "document_start" }, uri.href);
+        injectScript(tab.id, { code, runAt: "document_start" }, uri.href);
       });
     };
 
+    const addRun = (dt: number): void => {
+      const bgPage = chrome.extension.getBackgroundPage();
+      if (!bgPage) {
+        console.error("no background page");
+        return;
+      }
+      const id = bgPage.setTimeout(run, dt);
+      timers.push(id);
+    };
+
     addRun(0);
     addRun(50);
     addRun(300);

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]