diff options
32 files changed, 528 insertions, 1780 deletions
diff --git a/.eslintrc.js b/.eslintrc.js index acc5305f4..c3e588250 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 }, + ], + }, }; @@ -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 1defe1ad0..8d4aaeb63 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 3a629e9c2..337068b55 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 74d4b848e..af9a48895 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 8ab7225e8..5a3011b37 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 cebccd2dc..acbd502ea 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 0f35f7ede..74157b18b 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 5d28c5ae7..3d919c6f1 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 f0a4f1d72..da1c19233 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 84fe6b802..6e88081b6 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 a8f495238..480e1eec7 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 1a5cb85fa..3842347dc 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 80ba344d5..83e8d2192 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 44f668658..d11b79a96 100644 --- a/src/util/query.ts +++ b/src/util/query.ts @@ -26,6 +26,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. */ export class Store<T> { @@ -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 05188b6d2..ea4f8ca8d 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 d1551b09f..422523665 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 063a259d6..02450523e 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 330388ca0..7bc5d368d 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 887658ef9..9fb0529db 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 dbe84cde4..4e3f8615c 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 bf4c4b04d..eb7193e0c 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 09aa595c3..e3dd630b6 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 6cd7242ff..c2f050e2a 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 8263ceace..4a13317cd 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 06a3ba169..7d759705f 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 10e12d590..9c797f50d 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'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 8510ad383..a99cadb05 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 e071dc8ba..9020ddb0b 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 b6ff1248c..8fc6a6a63 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 a530b7506..07b223c87 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 ef4715dce..f26c14d37 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); |