gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] branch master updated: add anastasis skeleton, put c


From: gnunet
Subject: [taler-wallet-core] branch master updated: add anastasis skeleton, put crypto in taler-util
Date: Thu, 07 Oct 2021 12:01:45 +0200

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

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

The following commit(s) were added to refs/heads/master by this push:
     new e2fe2d6d add anastasis skeleton, put crypto in taler-util
e2fe2d6d is described below

commit e2fe2d6db16b422ee6d69ef03f1393e1f0f42749
Author: Florian Dold <florian@dold.me>
AuthorDate: Thu Oct 7 12:01:40 2021 +0200

    add anastasis skeleton, put crypto in taler-util
---
 packages/anastasis-core/package.json               |  30 +
 packages/anastasis-core/src/anastasis-data.ts      | 742 +++++++++++++++++++++
 packages/anastasis-core/src/crypto.test.ts         |  16 +
 packages/anastasis-core/src/crypto.ts              |  21 +
 packages/anastasis-core/src/index.ts               |  14 +
 packages/anastasis-core/tsconfig.json              |  30 +
 packages/idb-bridge/src/bridge-idb.ts              |   6 +-
 .../idb-bridge/src/idb-wpt-ported/wptsupport.ts    |   2 +-
 packages/taler-util/package.json                   |  17 +-
 packages/taler-util/src/index.browser.ts           |  39 +-
 packages/taler-util/src/index.node.ts              |  23 +
 packages/taler-util/src/index.ts                   |  28 +-
 packages/taler-util/src/kdf.d.ts                   |   5 +
 packages/taler-util/src/kdf.js                     |  76 +++
 packages/taler-util/src/kdf.js.map                 |   1 +
 .../crypto/primitives => taler-util/src}/kdf.ts    |   0
 .../primitives => taler-util/src}/nacl-fast.ts     |   0
 packages/taler-util/src/prng-browser.ts            |  19 +
 packages/taler-util/src/prng-node.ts               |  30 +
 .../crypto/primitives => taler-util/src}/sha256.ts |   0
 .../src/talerCrypto.test.ts}                       |   7 +-
 .../src/crypto => taler-util/src}/talerCrypto.ts   |   7 +-
 packages/taler-wallet-cli/src/index.ts             |   8 +-
 .../src/integrationtests/harness.ts                |  26 +-
 .../src/integrationtests/test-bank-api.ts          |   2 +-
 .../test-merchant-spec-public-orders.ts            |  15 +-
 packages/taler-wallet-cli/src/lint.ts              |   2 +-
 .../src/crypto/workers/cryptoImplementation.ts     |   6 +-
 .../taler-wallet-core/src/headless/NodeHttpLib.ts  |   5 +-
 packages/taler-wallet-core/src/headless/helpers.ts |   2 +-
 packages/taler-wallet-core/src/index.browser.ts    |  55 --
 packages/taler-wallet-core/src/index.node.ts       |  18 -
 packages/taler-wallet-core/src/index.ts            |   1 -
 .../src/operations/backup/export.ts                |   8 +-
 .../src/operations/backup/index.ts                 |   6 +-
 .../src/operations/backup/state.ts                 |   2 +-
 .../taler-wallet-core/src/operations/deposits.ts   |   4 +-
 .../taler-wallet-core/src/operations/exchanges.ts  |   2 +-
 packages/taler-wallet-core/src/operations/pay.ts   |   2 +-
 .../taler-wallet-core/src/operations/recoup.ts     |   2 +-
 .../taler-wallet-core/src/operations/refresh.ts    |   2 +-
 .../taler-wallet-core/src/operations/reserves.ts   |   4 +-
 packages/taler-wallet-core/src/operations/tip.ts   |   2 +-
 .../taler-wallet-core/src/util/contractTerms.ts    |   4 +-
 packages/taler-wallet-core/src/util/http.ts        |   2 +-
 .../src/popup/ProviderAddPage.tsx                  | 280 +++++---
 .../src/wallet/ProviderAddPage.tsx                 | 280 +++++---
 pnpm-lock.yaml                                     |  25 +
 48 files changed, 1502 insertions(+), 376 deletions(-)

diff --git a/packages/anastasis-core/package.json 
b/packages/anastasis-core/package.json
new file mode 100644
index 00000000..acc46f7c
--- /dev/null
+++ b/packages/anastasis-core/package.json
@@ -0,0 +1,30 @@
+{
+  "name": "anastasis-core",
+  "version": "0.0.1",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "prepare": "tsc",
+    "compile": "tsc",
+    "pretty": "prettier --write src",
+    "test": "tsc && ava",
+    "coverage": "tsc && nyc ava",
+    "clean": "rimraf dist lib tsconfig.tsbuildinfo"
+  },
+  "author": "Florian Dold <dold@taler.net>",
+  "license": "AGPL-3-or-later",
+  "type": "module",
+  "devDependencies": {
+    "ava": "^3.15.0",
+    "typescript": "^4.4.3"
+  },
+  "dependencies": {
+    "@gnu-taler/taler-util": "workspace:^0.8.3",
+    "hash-wasm": "^4.9.0"
+  },
+  "ava": {
+    "files": [
+      "lib/**/*test.*"
+    ]
+  }
+}
diff --git a/packages/anastasis-core/src/anastasis-data.ts 
b/packages/anastasis-core/src/anastasis-data.ts
new file mode 100644
index 00000000..4946e9df
--- /dev/null
+++ b/packages/anastasis-core/src/anastasis-data.ts
@@ -0,0 +1,742 @@
+// This file is auto-generated, do not modify.
+// Generated from v0.2.0-4-g61ea83c on Tue, 05 Oct 2021 10:40:32 +0200
+// To re-generate, run contrib/gen-ts.sh from the main anastasis code base.
+
+export const anastasisData = {
+  providersList: {
+    license: "GPLv3+",
+    "SPDX-License-Identifier": "GPL3.0-or-later",
+    anastasis_provider: [
+      {
+        url: "https://anastasis.demo.taler.net/";,
+        currency: "KUDOS",
+      },
+      {
+        url: "https://kudos.demo.anastasis.lu/";,
+        currency: "KUDOS",
+      },
+      {
+        url: "http://localhost:8086/";,
+        currency: "TESTKUDOS",
+      },
+      {
+        url: "http://localhost:8087/";,
+        currency: "TESTKUDOS",
+      },
+      {
+        url: "http://localhost:8088/";,
+        currency: "TESTKUDOS",
+      },
+      {
+        url: "http://localhost:8089/";,
+        currency: "TESTKUDOS",
+      },
+    ],
+  },
+  countriesList: {
+    license: "GPLv3+",
+    "SPDX-License-Identifier": "GPL3.0-or-later",
+    countries: [
+      {
+        code: "al",
+        name: "Albania",
+        continent: "Europe",
+        name_i18n: {
+          de_DE: "Albanien",
+          en_UK: "Albania",
+        },
+        currency: "ALL",
+        call_code: "+355",
+      },
+      {
+        code: "be",
+        name: "Belgium",
+        continent: "Europe",
+        name_i18n: {
+          de_DE: "Belgien",
+          en_UK: "Belgium",
+        },
+        currency: "EUR",
+        call_code: "+32",
+      },
+      {
+        code: "ch",
+        name: "Switzerland",
+        continent: "Europe",
+        name_i18n: {
+          de_DE: "Schweiz",
+          de_CH: "Schwiiz",
+          fr_FR: "Suisse",
+          en_UK: "Swiss",
+        },
+        currency: "CHF",
+        call_code: "+41",
+      },
+      {
+        code: "cz",
+        name: "Czech Republic",
+        continent: "Europe",
+        name_i18n: {
+          en_UK: "Czech Republic",
+        },
+        currency: "CZK",
+        call_code: "+420",
+      },
+      {
+        code: "de",
+        name: "Germany",
+        continent: "Europe",
+        continent_i18n: { de_DE: "Europa" },
+        name_i18n: {
+          de_DE: "Deutschland",
+          de_CH: "Deutschland",
+          fr_FR: "Allemagne",
+          en_UK: "Germany",
+        },
+        currency: "EUR",
+        call_code: "+49",
+      },
+      {
+        code: "dk",
+        name: "Denmark",
+        continent: "Europe",
+        continent_i18n: { de_DE: "Europa" },
+        name_i18n: {
+          en_UK: "Denmark",
+        },
+        currency: "DKK",
+        call_code: "+45",
+      },
+      {
+        code: "es",
+        name: "Spain",
+        continent: "Europe",
+        continent_i18n: { es_ES: "Europa" },
+        name_i18n: {
+          es_ES: "España",
+        },
+        currency: "EUR",
+        call_code: "+44",
+      },
+      {
+        code: "in",
+        name: "India",
+        continent: "India",
+        continent_i18n: { en_EN: "India" },
+        name_i18n: {
+          de_DE: "Indien",
+          de_CH: "Indien",
+          fr_FR: "l'Inde",
+          en_UK: "India",
+        },
+        currency: "INR",
+        call_code: "+91",
+      },
+      {
+        code: "it",
+        name: "Italy",
+        continent: "Europe",
+        name_i18n: {
+          de_DE: "Italien",
+          en_UK: "Italy",
+        },
+        currency: "EUR",
+        call_code: "+39",
+      },
+      {
+        code: "jp",
+        name: "Japan",
+        continent: "Asia",
+        continent_i18n: { en_EN: "Japan" },
+        name_i18n: {
+          de_DE: "Japan",
+          de_CH: "Japan",
+          en_UK: "Japan",
+        },
+        currency: "JPY",
+        call_code: "+81",
+      },
+      {
+        code: "sl",
+        name: "Slovakia",
+        continent: "Europe",
+        name_i18n: {
+          en_UK: "Slovakia",
+        },
+        currency: "EUR",
+        call_code: "+421",
+      },
+      {
+        code: "us",
+        name: "United States of America (USA)",
+        continent: "North America",
+        continent_i18n: { de_DE: "Nordamerika" },
+        name_i18n: {
+          de_DE: "Vereinigte Staaten von Amerika (USA)",
+          de_CH: "Vereinigte Staaten von Amerika (USA)",
+          fr_FR: "États-Unis d'Amérique (USA)",
+          en_UK: "United States of America (USA)",
+        },
+        currency: "USD",
+        call_code: "+1",
+      },
+      {
+        code: "xx",
+        name: "Testland",
+        continent: "Testcontinent",
+        continent_i18n: { de_DE: "Testkontinent" },
+        name_i18n: {
+          de_DE: "Testlandt",
+          de_CH: "Testlandi",
+          fr_FR: "Testpais",
+          en_UK: "Testland",
+        },
+        currency: "TESTKUDOS",
+        call_code: "+00",
+      },
+      {
+        code: "xy",
+        name: "Demoland",
+        continent: "Testcontinent",
+        continent_i18n: { de_DE: "Testkontinent" },
+        name_i18n: {
+          de_DE: "Demolandt",
+          de_CH: "Demolandi",
+          fr_FR: "Demopais",
+          en_UK: "Demoland",
+        },
+        currency: "KUDOS",
+        call_code: "+01",
+      },
+    ],
+  },
+  countryDetails: {
+    al: {
+      license: "GPLv3+",
+      "SPDX-License-Identifier": "GPL3.0-or-later",
+      required_attributes: [
+        {
+          type: "string",
+          name: "full_name",
+          label: "Full name",
+          widget: "anastasis_gtk_ia_full_name",
+          uuid: "9e8f463f-575f-42cb-85f3-759559997331",
+        },
+        {
+          type: "string",
+          name: "birthplace",
+          label: "Birthplace",
+          widget: "anastasis_gtk_ia_birthplace",
+          uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f",
+        },
+        {
+          type: "string",
+          name: "nid_number",
+          label: "Numri i Identitetit",
+          label_i18n: {
+            en: "Identity Number",
+            al: "Numri i Identitetit",
+          },
+          widget: "anastasis_gtk_ia_nid_al",
+          uuid: "256e5d30-d65e-481b-9ac4-55f5ac03b24a",
+          "validation-regex":
+            "^[0-9A-T][0-9](((0|5)[0-9])|10|11|51|52)[0-9]{3}[A-W]$",
+          "validation-logic": "AL_NID_check",
+        },
+      ],
+    },
+    be: {
+      license: "GPLv3+",
+      "SPDX-License-Identifier": "GPL3.0-or-later",
+      required_attributes: [
+        {
+          type: "string",
+          name: "full_name",
+          label: "Full name",
+          widget: "anastasis_gtk_ia_full_name",
+          uuid: "9e8f463f-575f-42cb-85f3-759559997331",
+        },
+        {
+          type: "date",
+          name: "birthdate",
+          label: "Birthdate",
+          widget: "anastasis_gtk_ia_birthdate",
+          uuid: "83d655c7-bdb6-484d-904e-80c1058c8854",
+        },
+        {
+          type: "string",
+          name: "birthplace",
+          label: "Birthplace",
+          widget: "anastasis_gtk_ia_birthplace",
+          uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f",
+        },
+        {
+          type: "string",
+          name: "nrn_number",
+          label: "National Register Number",
+          label_i18n: {
+            en: "National Register Number",
+          },
+          widget: "anastasis_gtk_ia_nid_be",
+          uuid: "0452f99a-06f7-48bd-8ac0-2e4ed9a24560",
+          "validation-regex": "^[0-9]{11}$",
+          "validation-logic": "BE_NRN_check",
+        },
+      ],
+    },
+    ch: {
+      license: "GPLv3+",
+      "SPDX-License-Identifier": "GPL3.0-or-later",
+      required_attributes: [
+        {
+          type: "string",
+          name: "full_name",
+          label: "Full name",
+          widget: "anastasis_gtk_ia_full_name",
+          uuid: "9e8f463f-575f-42cb-85f3-759559997331",
+        },
+        {
+          type: "date",
+          name: "birthdate",
+          label: "Birthdate",
+          widget: "anastasis_gtk_ia_birthdate",
+          uuid: "83d655c7-bdb6-484d-904e-80c1058c8854",
+        },
+        {
+          type: "string",
+          name: "birthplace",
+          label: "Birthplace",
+          widget: "anastasis_gtk_ia_birthplace",
+          uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f",
+        },
+        {
+          type: "string",
+          name: "ahv_number",
+          label: "AHV number",
+          label_i18n: {
+            de_DE: "AHV-Nummer",
+            de_CH: "AHV-Nummer",
+          },
+          widget: "anastasis_gtk_ia_ahv",
+          uuid: "1da87570-ba16-4f62-8a7e-cbda92f51591",
+          "validation-regex":
+            "^(756).[0-9]{4}.[0-9]{4}.[0-9]{2}|(756)[0-9]{10}$",
+          "validation-logic": "CH_AHV_check",
+        },
+      ],
+    },
+    cz: {
+      license: "GPLv3+",
+      "SPDX-License-Identifier": "GPL3.0-or-later",
+      required_attributes: [
+        {
+          type: "string",
+          name: "full_name",
+          label: "Full name",
+          widget: "anastasis_gtk_ia_full_name",
+          uuid: "9e8f463f-575f-42cb-85f3-759559997331",
+        },
+        {
+          type: "string",
+          name: "birthplace",
+          label: "Birthplace",
+          widget: "anastasis_gtk_ia_birthplace",
+          uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f",
+        },
+        {
+          type: "string",
+          name: "birth_number",
+          label: "Birth Number",
+          label_i18n: {
+            en: "Birth Number",
+            cz: "rodné číslo",
+          },
+          widget: "anastasis_gtk_ia_birthnumber_cz",
+          uuid: "03e3a05b-1192-44f1-ac36-7425512eee1a",
+          "validation-regex":
+            
"^[0-9]{2}(((0|2|5|7)[0-9])|10|11|31|32|51|52|81|82)/[0-9]{3}[0-9]?$",
+          "validation-logic": "CZ_BN_check",
+        },
+      ],
+    },
+    de: {
+      license: "GPLv3+",
+      "SPDX-License-Identifier": "GPL3.0-or-later",
+      required_attributes: [
+        {
+          type: "string",
+          name: "full_name",
+          label: "Full name",
+          widget: "anastasis_gtk_ia_full_name",
+          uuid: "9e8f463f-575f-42cb-85f3-759559997331",
+        },
+        {
+          type: "date",
+          name: "birthdate",
+          label: "Birthdate",
+          widget: "anastasis_gtk_ia_birthdate",
+          uuid: "83d655c7-bdb6-484d-904e-80c1058c8854",
+        },
+        {
+          type: "string",
+          name: "birthplace",
+          label: "Birthplace",
+          widget: "anastasis_gtk_ia_birthplace",
+          uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f",
+        },
+        {
+          type: "string",
+          name: "tax_number",
+          label: "Taxpayer identification number",
+          label_i18n: {
+            de_DE: "Steuerliche Identifikationsnummer",
+            en: "German taxpayer identification number",
+          },
+          widget: "anastasis_gtk_ia_tax_de",
+          uuid: "dae48f85-e3ff-47a4-a4a3-ed981ed8c3c6",
+          "validation-regex": "^[0-9]{11}$",
+          "validation-logic": "DE_TIN_check",
+        },
+        {
+          type: "string",
+          name: "social_security_number",
+          label: "Social security number",
+          label_i18n: {
+            de_DE: "Deutsche Sozialversicherungsnummer",
+            en: "German Social security number",
+          },
+          widget: "anastasis_gtk_ia_ssn_de",
+          uuid: "d5e2aa79-1c88-4cf4-a4d2-252508b38e05",
+          "validation-regex": "^[0-9]{8}[[:upper:]][0-9]{3}$",
+          "validation-logic": "DE_SVN_check",
+          optional: true,
+        },
+      ],
+    },
+    dk: {
+      license: "GPLv3+",
+      "SPDX-License-Identifier": "GPL3.0-or-later",
+      required_attributes: [
+        {
+          type: "string",
+          name: "full_name",
+          label: "Full name",
+          widget: "anastasis_gtk_ia_full_name",
+          uuid: "9e8f463f-575f-42cb-85f3-759559997331",
+        },
+        {
+          type: "string",
+          name: "birthplace",
+          label: "Birthplace",
+          widget: "anastasis_gtk_ia_birthplace",
+          uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f",
+        },
+        {
+          type: "string",
+          name: "cpr_number",
+          label: "CPR-nummer",
+          label_i18n: {
+            en: "CPR Number",
+            dk: "CPR-nummer",
+          },
+          widget: "anastasis_gtk_ia_cpr_dk",
+          uuid: "38f13a4d-4302-4ada-ada1-c3ff4a8ff689",
+          "validation-regex":
+            
"^(0[1-9]|[1-2][0-9]|30|31)((0[1-9]|10|11|12))[0-9]{2}-[0-9A-Z]{4}$",
+        },
+      ],
+    },
+    es: {
+      license: "GPLv3+",
+      "SPDX-License-Identifier": "GPL3.0-or-later",
+      required_attributes: [
+        {
+          type: "string",
+          name: "full_name",
+          label: "Full name",
+          widget: "anastasis_gtk_ia_full_name",
+          uuid: "9e8f463f-575f-42cb-85f3-759559997331",
+        },
+        {
+          type: "date",
+          name: "birthdate",
+          label: "Birthdate",
+          widget: "anastasis_gtk_ia_birthdate",
+          uuid: "83d655c7-bdb6-484d-904e-80c1058c8854",
+        },
+        {
+          type: "string",
+          name: "birthplace",
+          label: "Birthplace",
+          widget: "anastasis_gtk_ia_birthplace",
+          uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f",
+        },
+        {
+          type: "string",
+          name: "tax_number",
+          label: "Tax number",
+          label_i18n: {
+            es_ES: "Número de Identificación Fiscal (DNI, NIE)",
+          },
+          widget: "anastasis_gtk_ia_es_dni",
+          uuid: "ac8bd865-6be8-445c-b650-6a18eef16a49",
+          "validation-regex": "^[0-9MXYZ][0-9]{7}[TRWAGMYFPDXBNJZSQVHLCKE]$",
+          "validation-logic": "ES_DNI_check",
+        },
+        {
+          type: "string",
+          name: "ssn_number",
+          label: "Social security number",
+          label_i18n: {
+            es_ES: "Número de Seguridad Social",
+          },
+          widget: "anastasis_gtk_ia_es_ssn",
+          uuid: "22396a19-f3bb-497e-b63a-961fd639140e",
+          "validation-regex": "^[0-9]{11}$",
+        },
+      ],
+    },
+    in: {
+      license: "GPLv3+",
+      "SPDX-License-Identifier": "GPL3.0-or-later",
+      required_attributes: [
+        {
+          type: "string",
+          name: "full_name",
+          label: "Full name",
+          widget: "anastasis_gtk_ia_full_name",
+          uuid: "9e8f463f-575f-42cb-85f3-759559997331",
+        },
+        {
+          type: "date",
+          name: "birthdate",
+          label: "Birthdate",
+          widget: "anastasis_gtk_ia_birthdate",
+          uuid: "83d655c7-bdb6-484d-904e-80c1058c8854",
+        },
+        {
+          type: "string",
+          name: "birthplace",
+          label: "Birthplace",
+          widget: "anastasis_gtk_ia_birthplace",
+          uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f",
+        },
+        {
+          type: "string",
+          name: "aadhar_number",
+          label: "Aadhar number",
+          label_i18n: {
+            en: "Aadhar number",
+          },
+          widget: "anastasis_gtk_ia_aadhar_in",
+          uuid: "55afe97a-98bc-48d1-bb37-a9658be3fdc9",
+          "validation-regex": "^[2-9]{1}[0-9]{3}\\s[0-9]{4}\\s[0-9]{4}$",
+          "validation-logic": "IN_AADHAR_check",
+        },
+      ],
+    },
+    it: {
+      license: "GPLv3+",
+      "SPDX-License-Identifier": "GPL3.0-or-later",
+      required_attributes: [
+        {
+          type: "string",
+          name: "full_name",
+          label: "Full name",
+          widget: "anastasis_gtk_ia_full_name",
+          uuid: "9e8f463f-575f-42cb-85f3-759559997331",
+        },
+        {
+          type: "string",
+          name: "birthplace",
+          label: "Birthplace",
+          widget: "anastasis_gtk_ia_birthplace",
+          uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f",
+        },
+        {
+          type: "string",
+          name: "fiscal_code",
+          label: "Codice fiscale",
+          label_i18n: {
+            it: "Codice fiscale",
+            en: "Fiscal code",
+          },
+          widget: "anastasis_gtk_ia_cf_it",
+          uuid: "88f53c51-52ad-4d63-a163-ec042589f925",
+          "validation-regex":
+            
"^[[:upper:]]{6}[0-9]{2}[A-EHLMPRT](([0-24-6][0-9])|(30|31|70|71))[A-MZ][0-9]{3}[A-Z]$",
+          "validation-logic": "IT_CF_check",
+        },
+      ],
+    },
+    jp: {
+      license: "GPLv3+",
+      "SPDX-License-Identifier": "GPL3.0-or-later",
+      required_attributes: [
+        {
+          type: "string",
+          name: "full_name",
+          label: "Full name",
+          widget: "anastasis_gtk_ia_full_name",
+          uuid: "9e8f463f-575f-42cb-85f3-759559997331",
+        },
+        {
+          type: "date",
+          name: "birthdate",
+          label: "Birthdate",
+          widget: "anastasis_gtk_ia_birthdate",
+          uuid: "83d655c7-bdb6-484d-904e-80c1058c8854",
+        },
+        {
+          type: "string",
+          name: "birthplace",
+          label: "Birthplace",
+          widget: "anastasis_gtk_ia_birthplace",
+          uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f",
+        },
+        {
+          type: "string",
+          name: "my_number",
+          label: "My number",
+          label_i18n: {
+            en: "My number",
+            jp: "マイナンバー",
+          },
+          widget: "anastasis_gtk_ia_my_jp",
+          uuid: "90848f42-a83e-4226-8186-329696c14152",
+          "validation-regex": "^[0-9]{12}$",
+        },
+      ],
+    },
+    sk: {
+      license: "GPLv3+",
+      "SPDX-License-Identifier": "GPL3.0-or-later",
+      required_attributes: [
+        {
+          type: "string",
+          name: "full_name",
+          label: "Full name",
+          widget: "anastasis_gtk_ia_full_name",
+          uuid: "9e8f463f-575f-42cb-85f3-759559997331",
+        },
+        {
+          type: "string",
+          name: "birthplace",
+          label: "Birthplace",
+          widget: "anastasis_gtk_ia_birthplace",
+          uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f",
+        },
+        {
+          type: "string",
+          name: "birth_number",
+          label: "Birth Number",
+          label_i18n: {
+            en: "Birth Number",
+            sk: "rodné číslo",
+          },
+          widget: "anastasis_gtk_ia_birthnumber_sk",
+          uuid: "1cd372fe-2cea-4928-9f29-66f2bdd8555c",
+          "validation-regex":
+            
"^[0-9]{2}(((0|2|5|7)[0-9])|10|11|31|32|51|52|81|82)/[0-9]{3}[0-9]?$",
+          "validation-logic": "CZ_BN_check",
+        },
+      ],
+    },
+    us: {
+      license: "GPLv3+",
+      "SPDX-License-Identifier": "GPL3.0-or-later",
+      required_attributes: [
+        {
+          type: "string",
+          name: "full_name",
+          label: "Full name",
+          widget: "anastasis_gtk_ia_full_name",
+          uuid: "9e8f463f-575f-42cb-85f3-759559997331",
+        },
+        {
+          type: "date",
+          name: "birthdate",
+          label: "Birthdate",
+          widget: "anastasis_gtk_ia_birthdate",
+          uuid: "83d655c7-bdb6-484d-904e-80c1058c8854",
+        },
+        {
+          type: "string",
+          name: "birthplace",
+          label: "Birthplace",
+          widget: "anastasis_gtk_ia_birthplace",
+          uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f",
+        },
+        {
+          type: "string",
+          name: "social_security_number",
+          label: "Social security number",
+          label_i18n: {
+            en: "US Social security number",
+          },
+          widget: "anastasis_gtk_ia_ssn_us",
+          uuid: "310a138c-b0b7-4985-b8b8-d00e765e9f9b",
+          "validation-regex": "^d{3}-d{2}-d{4}$",
+        },
+      ],
+    },
+    xx: {
+      license: "GPLv3+",
+      "SPDX-License-Identifier": "GPL3.0-or-later",
+      required_attributes: [
+        {
+          type: "string",
+          name: "full_name",
+          label: "Full name",
+          widget: "anastasis_gtk_ia_full_name",
+          uuid: "9e8f463f-575f-42cb-85f3-759559997331",
+        },
+        {
+          type: "date",
+          name: "birthdate",
+          label: "Birthdate",
+          widget: "anastasis_gtk_ia_birthdate",
+          uuid: "83d655c7-bdb6-484d-904e-80c1058c8854",
+        },
+        {
+          type: "string",
+          name: "sq_number",
+          label: "Square number",
+          widget: "anastasis_gtk_xx_square",
+          uuid: "ed790bca-89bf-11eb-96f2-233996cf644e",
+          "validation-regex": "^[0-9]+$",
+          "validation-logic": "XX_SQUARE_check",
+        },
+      ],
+    },
+    xy: {
+      license: "GPLv3+",
+      "SPDX-License-Identifier": "GPL3.0-or-later",
+      required_attributes: [
+        {
+          type: "string",
+          name: "full_name",
+          label: "Full name",
+          widget: "anastasis_gtk_ia_full_name",
+          uuid: "9e8f463f-575f-42cb-85f3-759559997331",
+        },
+        {
+          type: "date",
+          name: "birthdate",
+          label: "Birthdate",
+          widget: "anastasis_gtk_ia_birthdate",
+          uuid: "83d655c7-bdb6-484d-904e-80c1058c8854",
+        },
+        {
+          type: "string",
+          name: "prime_number",
+          label: "Prime number",
+          widget: "anastasis_gtk_xx_prime",
+          uuid: "39190a95-cacb-4412-8bae-1f7da3f980b4",
+          "validation-regex": "^[0-9]+$",
+          "validation-logic": "XY_PRIME_check",
+        },
+      ],
+    },
+  },
+};
diff --git a/packages/anastasis-core/src/crypto.test.ts 
b/packages/anastasis-core/src/crypto.test.ts
new file mode 100644
index 00000000..346806fa
--- /dev/null
+++ b/packages/anastasis-core/src/crypto.test.ts
@@ -0,0 +1,16 @@
+import test from "ava";
+
+// Vector generated with taler-anastasis-tvg
+const userIdVector = {
+  input_id_data: {
+    name: "Fleabag",
+    ssn: "AB123",
+  },
+  input_server_salt: "FZ48EFS7WS3R2ZR4V53A3GFFY4",
+  output_id:
+    
"YS45R6CGJV84K1NN7T14ZBCPVTZ6H15XJSM1FV0R748MHPV82SM0126EBZKBAAGCR34Q9AFKPEW1HRT2Q9GQ5JRA3642AB571DKZS18",
+};
+
+test("user ID derivation", async (t) => {
+  t.fail();
+});
diff --git a/packages/anastasis-core/src/crypto.ts 
b/packages/anastasis-core/src/crypto.ts
new file mode 100644
index 00000000..54f27b64
--- /dev/null
+++ b/packages/anastasis-core/src/crypto.ts
@@ -0,0 +1,21 @@
+import { argon2id } from "hash-wasm";
+
+async function userIdentifierDerive(
+  idData: any,
+  serverSalt: string,
+): Promise<string> {
+  throw Error("not implemented");
+}
+
+// interface Keypair {
+//   pub: string;
+//   priv: string;
+// }
+
+// async function accountKeypairDerive(): Promise<Keypair> {}
+
+// async function secureAnswerHash(
+//   answer: string,
+//   truthUuid: string,
+//   questionSalt: string,
+// ): Promise<string> {}
diff --git a/packages/anastasis-core/src/index.ts 
b/packages/anastasis-core/src/index.ts
new file mode 100644
index 00000000..7a14440a
--- /dev/null
+++ b/packages/anastasis-core/src/index.ts
@@ -0,0 +1,14 @@
+import { md5, sha1, sha512, sha3 } from 'hash-wasm';
+
+async function run() {
+  console.log('MD5:', await md5('demo'));
+
+  const int8Buffer = new Uint8Array([0, 1, 2, 3]);
+  console.log('SHA1:', await sha1(int8Buffer));
+  console.log('SHA512:', await sha512(int8Buffer));
+
+  const int32Buffer = new Uint32Array([1056, 641]);
+  console.log('SHA3-256:', await sha3(int32Buffer, 256));
+}
+
+run();
\ No newline at end of file
diff --git a/packages/anastasis-core/tsconfig.json 
b/packages/anastasis-core/tsconfig.json
new file mode 100644
index 00000000..34027c4a
--- /dev/null
+++ b/packages/anastasis-core/tsconfig.json
@@ -0,0 +1,30 @@
+{
+  "compileOnSave": true,
+  "compilerOptions": {
+    "composite": true,
+    "target": "ES2018",
+    "module": "ESNext",
+    "moduleResolution": "node",
+    "sourceMap": true,
+    "lib": ["es6"],
+    "noImplicitReturns": true,
+    "noFallthroughCasesInSwitch": true,
+    "strict": true,
+    "strictPropertyInitialization": false,
+    "outDir": "lib",
+    "noImplicitAny": true,
+    "noImplicitThis": true,
+    "incremental": true,
+    "esModuleInterop": true,
+    "importHelpers": true,
+    "rootDir": "src",
+    "baseUrl": "./src",
+    "typeRoots": ["./node_modules/@types"]
+  },
+  "include": ["src/**/*"],
+  "references": [
+    {
+      "path": "../taler-util/"
+    }
+  ]
+}
diff --git a/packages/idb-bridge/src/bridge-idb.ts 
b/packages/idb-bridge/src/bridge-idb.ts
index ecabfbc7..f015d2a9 100644
--- a/packages/idb-bridge/src/bridge-idb.ts
+++ b/packages/idb-bridge/src/bridge-idb.ts
@@ -805,7 +805,7 @@ export class BridgeIDBFactory {
           oldVersion,
         });
         request.dispatchEvent(event2);
-      } catch (err) {
+      } catch (err: any) {
         request.error = new Error();
         request.error.name = err.name;
         request.readyState = "done";
@@ -846,7 +846,7 @@ export class BridgeIDBFactory {
         if (BridgeIDBFactory.enableTracing) {
           console.log("TRACE: connected!");
         }
-      } catch (err) {
+      } catch (err: any) {
         if (BridgeIDBFactory.enableTracing) {
           console.log(
             "TRACE: caught exception while trying to connect with backend",
@@ -2704,7 +2704,7 @@ export class BridgeIDBTransaction
             this._active = false;
             throw err;
           }
-        } catch (err) {
+        } catch (err: any) {
           if (BridgeIDBFactory.enableTracing) {
             console.log("TRACING: error during operation: ", err);
           }
diff --git a/packages/idb-bridge/src/idb-wpt-ported/wptsupport.ts 
b/packages/idb-bridge/src/idb-wpt-ported/wptsupport.ts
index d6c0b011..38b44bbe 100644
--- a/packages/idb-bridge/src/idb-wpt-ported/wptsupport.ts
+++ b/packages/idb-bridge/src/idb-wpt-ported/wptsupport.ts
@@ -542,7 +542,7 @@ export function is_transaction_active(
       e.stopPropagation();
     };
     return true;
-  } catch (ex) {
+  } catch (ex: any) {
     console.log(ex.stack);
     t.deepEqual(
       ex.name,
diff --git a/packages/taler-util/package.json b/packages/taler-util/package.json
index 4cbd829b..33942abf 100644
--- a/packages/taler-util/package.json
+++ b/packages/taler-util/package.json
@@ -3,19 +3,17 @@
   "version": "0.8.3",
   "description": "Generic helper functionality for GNU Taler",
   "exports": {
-    ".": "./lib/index.js"
-  },
-  "module": "./lib/index.js",
-  "main": "./lib/index.js",
-  "browser": {
-    "./lib/index.js": "./lib/index.browser.js"
+    ".": "./lib/index.node.js"
   },
+  "module": "./lib/index.node.js",
+  "main": "./lib/index.node.js",
+  "browser": "./lib/index.browser.js",
   "type": "module",
-  "types": "./lib/index.d.ts",
+  "types": "./lib/index.node.d.ts",
   "typesVersions": {
     "*": {
-      "lib/index.d.ts": [
-        "lib/index.d.ts"
+      "lib/index.node.d.ts": [
+        "lib/index.node.d.ts"
       ],
       "src/*": [],
       "*": []
@@ -40,6 +38,7 @@
     "typescript": "^4.2.3"
   },
   "dependencies": {
+    "big-integer": "^1.6.48",
     "jed": "^1.1.1",
     "tslib": "^2.1.0"
   },
diff --git a/packages/taler-util/src/index.browser.ts 
b/packages/taler-util/src/index.browser.ts
index 1c379bd9..3b8e194b 100644
--- a/packages/taler-util/src/index.browser.ts
+++ b/packages/taler-util/src/index.browser.ts
@@ -1,22 +1,21 @@
-import { TalerErrorCode } from "./taler-error-codes.js";
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
 
-export { TalerErrorCode };
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
 
-export * from "./amounts.js";
-export * from "./backupTypes.js";
-export * from "./codec.js";
-export * from "./helpers.js";
-export * from "./libtool-version.js";
-export * from "./notifications.js";
-export * from "./payto.js";
-export * from "./ReserveStatus.js";
-export * from "./ReserveTransaction.js";
-export * from "./talerTypes.js";
-export * from "./taleruri.js";
-export * from "./time.js";
-export * from "./transactionsTypes.js";
-export * from "./walletTypes.js";
-export * from "./i18n.js";
-export * from "./logging.js";
-export * from "./url.js";
-export { fnutil } from "./fnutils.js";
\ No newline at end of file
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+// Entry point for the browser.
+
+import { loadBrowserPrng } from "./prng-browser.js";
+loadBrowserPrng();
+export * from "./index.js";
diff --git a/packages/taler-util/src/index.node.ts 
b/packages/taler-util/src/index.node.ts
new file mode 100644
index 00000000..018b4767
--- /dev/null
+++ b/packages/taler-util/src/index.node.ts
@@ -0,0 +1,23 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+// Entry point for nodejs.
+
+import { initNodePrng } from "./prng-node.js";
+initNodePrng();
+export * from "./index.js";
+export * from "./talerconfig.js";
+export * from "./globbing/minimatch.js";
diff --git a/packages/taler-util/src/index.ts b/packages/taler-util/src/index.ts
index 06951231..ccb917f6 100644
--- a/packages/taler-util/src/index.ts
+++ b/packages/taler-util/src/index.ts
@@ -1,3 +1,25 @@
-export * from "./index.browser.js";
-export * from "./talerconfig.js";
-export * from "./globbing/minimatch.js";
+import { TalerErrorCode } from "./taler-error-codes.js";
+
+export { TalerErrorCode };
+
+export * from "./amounts.js";
+export * from "./backupTypes.js";
+export * from "./codec.js";
+export * from "./helpers.js";
+export * from "./libtool-version.js";
+export * from "./notifications.js";
+export * from "./payto.js";
+export * from "./ReserveStatus.js";
+export * from "./ReserveTransaction.js";
+export * from "./talerTypes.js";
+export * from "./taleruri.js";
+export * from "./time.js";
+export * from "./transactionsTypes.js";
+export * from "./walletTypes.js";
+export * from "./i18n.js";
+export * from "./logging.js";
+export * from "./url.js";
+export { fnutil } from "./fnutils.js";
+export * from "./kdf.js";
+export * from "./talerCrypto.js";
+export { randomBytes, secretbox, secretbox_open } from "./nacl-fast.js";
diff --git a/packages/taler-util/src/kdf.d.ts b/packages/taler-util/src/kdf.d.ts
new file mode 100644
index 00000000..80a6da41
--- /dev/null
+++ b/packages/taler-util/src/kdf.d.ts
@@ -0,0 +1,5 @@
+export declare function sha512(data: Uint8Array): Uint8Array;
+export declare function hmac(digest: (d: Uint8Array) => Uint8Array, blockSize: 
number, key: Uint8Array, message: Uint8Array): Uint8Array;
+export declare function hmacSha512(key: Uint8Array, message: Uint8Array): 
Uint8Array;
+export declare function hmacSha256(key: Uint8Array, message: Uint8Array): 
Uint8Array;
+export declare function kdf(outputLength: number, ikm: Uint8Array, salt: 
Uint8Array, info: Uint8Array): Uint8Array;
diff --git a/packages/taler-util/src/kdf.js b/packages/taler-util/src/kdf.js
new file mode 100644
index 00000000..32f17bea
--- /dev/null
+++ b/packages/taler-util/src/kdf.js
@@ -0,0 +1,76 @@
+/*
+ This file is part of GNU Taler
+ (C) 2019 GNUnet e.V.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import * as nacl from "./nacl-fast.js";
+import { sha256 } from "./sha256.js";
+export function sha512(data) {
+    return nacl.hash(data);
+}
+export function hmac(digest, blockSize, key, message) {
+    if (key.byteLength > blockSize) {
+        key = digest(key);
+    }
+    if (key.byteLength < blockSize) {
+        const k = key;
+        key = new Uint8Array(blockSize);
+        key.set(k, 0);
+    }
+    const okp = new Uint8Array(blockSize);
+    const ikp = new Uint8Array(blockSize);
+    for (let i = 0; i < blockSize; i++) {
+        ikp[i] = key[i] ^ 0x36;
+        okp[i] = key[i] ^ 0x5c;
+    }
+    const b1 = new Uint8Array(blockSize + message.byteLength);
+    b1.set(ikp, 0);
+    b1.set(message, blockSize);
+    const h0 = digest(b1);
+    const b2 = new Uint8Array(blockSize + h0.length);
+    b2.set(okp, 0);
+    b2.set(h0, blockSize);
+    return digest(b2);
+}
+export function hmacSha512(key, message) {
+    return hmac(sha512, 128, key, message);
+}
+export function hmacSha256(key, message) {
+    return hmac(sha256, 64, key, message);
+}
+export function kdf(outputLength, ikm, salt, info) {
+    // extract
+    const prk = hmacSha512(salt, ikm);
+    // expand
+    const N = Math.ceil(outputLength / 32);
+    const output = new Uint8Array(N * 32);
+    for (let i = 0; i < N; i++) {
+        let buf;
+        if (i == 0) {
+            buf = new Uint8Array(info.byteLength + 1);
+            buf.set(info, 0);
+        }
+        else {
+            buf = new Uint8Array(info.byteLength + 1 + 32);
+            for (let j = 0; j < 32; j++) {
+                buf[j] = output[(i - 1) * 32 + j];
+            }
+            buf.set(info, 32);
+        }
+        buf[buf.length - 1] = i + 1;
+        const chunk = hmacSha256(prk, buf);
+        output.set(chunk, i * 32);
+    }
+    return output.slice(0, outputLength);
+}
+//# sourceMappingURL=kdf.js.map
\ No newline at end of file
diff --git a/packages/taler-util/src/kdf.js.map 
b/packages/taler-util/src/kdf.js.map
new file mode 100644
index 00000000..be357dd9
--- /dev/null
+++ b/packages/taler-util/src/kdf.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"kdf.js","sourceRoot":"","sources":["kdf.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,IAAI,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,UAAU,MAAM,CAAC,IAAgB;IACrC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,IAAI,CAClB,MAAqC,EACrC,SAAiB,EACjB,GAAe,EACf,OAAmB;IAEnB,IAAI,GAAG,CAAC,UAAU,GAAG,SAAS,EAAE;QAC9B,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;KACnB;IACD,IAAI,GAAG,CAAC,UAAU,GAAG,SAAS,EAAE;QAC9B,MAAM,CAAC,GAA
 [...]
\ No newline at end of file
diff --git a/packages/taler-wallet-core/src/crypto/primitives/kdf.ts 
b/packages/taler-util/src/kdf.ts
similarity index 100%
rename from packages/taler-wallet-core/src/crypto/primitives/kdf.ts
rename to packages/taler-util/src/kdf.ts
diff --git a/packages/taler-wallet-core/src/crypto/primitives/nacl-fast.ts 
b/packages/taler-util/src/nacl-fast.ts
similarity index 100%
rename from packages/taler-wallet-core/src/crypto/primitives/nacl-fast.ts
rename to packages/taler-util/src/nacl-fast.ts
diff --git a/packages/taler-util/src/prng-browser.ts 
b/packages/taler-util/src/prng-browser.ts
new file mode 100644
index 00000000..79d399e0
--- /dev/null
+++ b/packages/taler-util/src/prng-browser.ts
@@ -0,0 +1,19 @@
+import { setPRNG } from "./nacl-fast.js";
+
+export function loadBrowserPrng() {
+  // Initialize PRNG if environment provides CSPRNG.
+  // If not, methods calling randombytes will throw.
+  // @ts-ignore-error
+  const cr = typeof self !== "undefined" ? self.crypto || self.msCrypto : null;
+
+  const QUOTA = 65536;
+  setPRNG(function (x: Uint8Array, n: number) {
+    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)));
+    }
+    for (i = 0; i < n; i++) x[i] = v[i];
+    for (i = 0; i < v.length; i++) v[i] = 0;
+  });
+}
diff --git a/packages/taler-util/src/prng-node.ts 
b/packages/taler-util/src/prng-node.ts
new file mode 100644
index 00000000..226923b8
--- /dev/null
+++ b/packages/taler-util/src/prng-node.ts
@@ -0,0 +1,30 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { setPRNG } from "./nacl-fast.js";
+import cr from "crypto";
+
+export function initNodePrng() {
+  // Initialize PRNG if environment provides CSPRNG.
+  // If not, methods calling randombytes will throw.
+  if (cr && cr.randomBytes) {
+    setPRNG(function (x: Uint8Array, n: number) {
+      const v = cr.randomBytes(n);
+      for (let i = 0; i < n; i++) x[i] = v[i];
+      for (let i = 0; i < v.length; i++) v[i] = 0;
+    });
+  }
+}
diff --git a/packages/taler-wallet-core/src/crypto/primitives/sha256.ts 
b/packages/taler-util/src/sha256.ts
similarity index 100%
rename from packages/taler-wallet-core/src/crypto/primitives/sha256.ts
rename to packages/taler-util/src/sha256.ts
diff --git a/packages/taler-wallet-core/src/crypto/talerCrypto-test.ts 
b/packages/taler-util/src/talerCrypto.test.ts
similarity index 97%
rename from packages/taler-wallet-core/src/crypto/talerCrypto-test.ts
rename to packages/taler-util/src/talerCrypto.test.ts
index 3718290d..ffd1d25c 100644
--- a/packages/taler-wallet-core/src/crypto/talerCrypto-test.ts
+++ b/packages/taler-util/src/talerCrypto.test.ts
@@ -25,14 +25,11 @@ import {
   eddsaGetPublic,
   keyExchangeEddsaEcdhe,
   keyExchangeEcdheEddsa,
-  rsaBlind,
-  rsaUnblind,
   stringToBytes,
   bytesToString,
-  rsaVerify,
 } from "./talerCrypto.js";
-import { sha512, kdf } from "./primitives/kdf.js";
-import * as nacl from "./primitives/nacl-fast.js";
+import { sha512, kdf } from "./kdf.js";
+import * as nacl from "./nacl-fast.js";
 
 test("encoding", (t) => {
   const s = "Hello, World";
diff --git a/packages/taler-wallet-core/src/crypto/talerCrypto.ts 
b/packages/taler-util/src/talerCrypto.ts
similarity index 98%
rename from packages/taler-wallet-core/src/crypto/talerCrypto.ts
rename to packages/taler-util/src/talerCrypto.ts
index 71a804f9..aab7571a 100644
--- a/packages/taler-wallet-core/src/crypto/talerCrypto.ts
+++ b/packages/taler-util/src/talerCrypto.ts
@@ -21,9 +21,12 @@
 /**
  * Imports.
  */
-import * as nacl from "./primitives/nacl-fast.js";
+import * as nacl from "./nacl-fast.js";
+import { kdf } from "./kdf.js";
 import bigint from "big-integer";
-import { kdf } from "./primitives/kdf.js";
+import { initNodePrng } from "./prng-node.js";
+
+initNodePrng();
 
 export function getRandomBytes(n: number): Uint8Array {
   return nacl.randomBytes(n);
diff --git a/packages/taler-wallet-cli/src/index.ts 
b/packages/taler-wallet-cli/src/index.ts
index 2d50e226..0985ba88 100644
--- a/packages/taler-wallet-cli/src/index.ts
+++ b/packages/taler-wallet-cli/src/index.ts
@@ -40,14 +40,14 @@ import {
   codecForString,
   Logger,
   Configuration,
+  decodeCrock,
+  rsaBlind,
 } from "@gnu-taler/taler-util";
 import {
   NodeHttpLib,
   getDefaultNodeWallet,
   OperationFailedAndReportedError,
   OperationFailedError,
-  decodeCrock,
-  rsaBlind,
   NodeThreadCryptoWorkerFactory,
   CryptoApi,
   walletCoreDebugFlags,
@@ -810,7 +810,7 @@ advancedCli
         coinPubList = coinPubListCodec.decode(
           JSON.parse(args.suspendCoins.coinPubSpec),
         );
-      } catch (e) {
+      } catch (e: any) {
         console.log("could not parse coin list:", e.message);
         process.exit(1);
       }
@@ -835,7 +835,7 @@ advancedCli
         coinPubList = coinPubListCodec.decode(
           JSON.parse(args.unsuspendCoins.coinPubSpec),
         );
-      } catch (e) {
+      } catch (e: any) {
         console.log("could not parse coin list:", e.message);
         process.exit(1);
       }
diff --git a/packages/taler-wallet-cli/src/integrationtests/harness.ts 
b/packages/taler-wallet-cli/src/integrationtests/harness.ts
index d47dfe09..a3a6e9e1 100644
--- a/packages/taler-wallet-cli/src/integrationtests/harness.ts
+++ b/packages/taler-wallet-cli/src/integrationtests/harness.ts
@@ -44,11 +44,6 @@ import {
   MerchantInstancesResponse,
 } from "./merchantApiTypes";
 import {
-  createEddsaKeyPair,
-  eddsaGetPublic,
-  EddsaKeyPair,
-  encodeCrock,
-  getRandomBytes,
   openPromise,
   OperationFailedError,
   WalletCoreApiClient,
@@ -64,6 +59,11 @@ import {
   Duration,
   parsePaytoUri,
   CoreApiResponse,
+  createEddsaKeyPair,
+  eddsaGetPublic,
+  EddsaKeyPair,
+  encodeCrock,
+  getRandomBytes,
 } from "@gnu-taler/taler-util";
 import { CoinConfig } from "./denomStructures.js";
 
@@ -441,7 +441,7 @@ export async function pingProc(
       const resp = await axios.get(url);
       console.log(`service ${serviceName} available`);
       return;
-    } catch (e) {
+    } catch (e: any) {
       console.log(`service ${serviceName} not ready:`, e.toString());
       await delayMs(1000);
     }
@@ -1074,8 +1074,12 @@ export class ExchangeService implements 
ExchangeServiceInterface {
 
   async purgeSecmodKeys(): Promise<void> {
     const cfg = Configuration.load(this.configFilename);
-    const rsaKeydir = cfg.getPath("taler-exchange-secmod-rsa", 
"KEY_DIR").required();
-    const eddsaKeydir = cfg.getPath("taler-exchange-secmod-eddsa", 
"KEY_DIR").required();
+    const rsaKeydir = cfg
+      .getPath("taler-exchange-secmod-rsa", "KEY_DIR")
+      .required();
+    const eddsaKeydir = cfg
+      .getPath("taler-exchange-secmod-eddsa", "KEY_DIR")
+      .required();
     // Be *VERY* careful when changing this, or you will accidentally delete 
user data.
     await sh(this.globalState, "rm-secmod-keys", `rm -rf ${rsaKeydir}/COIN_*`);
     await sh(this.globalState, "rm-secmod-keys", `rm ${eddsaKeydir}/*`);
@@ -1119,11 +1123,7 @@ export class ExchangeService implements 
ExchangeServiceInterface {
 
     this.exchangeHttpProc = this.globalState.spawnService(
       "taler-exchange-httpd",
-      [
-        "-c",
-        this.configFilename,
-        ...this.timetravelArgArr,
-      ],
+      ["-c", this.configFilename, ...this.timetravelArgArr],
       `exchange-httpd-${this.name}`,
     );
 
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-bank-api.ts 
b/packages/taler-wallet-cli/src/integrationtests/test-bank-api.ts
index 6a09de77..d6d0e2dc 100644
--- a/packages/taler-wallet-cli/src/integrationtests/test-bank-api.ts
+++ b/packages/taler-wallet-cli/src/integrationtests/test-bank-api.ts
@@ -28,7 +28,7 @@ import {
   BankAccessApi,
   CreditDebitIndicator,
 } from "./harness";
-import { createEddsaKeyPair, encodeCrock } from "@gnu-taler/taler-wallet-core";
+import { createEddsaKeyPair, encodeCrock } from "@gnu-taler/taler-util";
 import { defaultCoinConfig } from "./denomStructures";
 
 /**
diff --git 
a/packages/taler-wallet-cli/src/integrationtests/test-merchant-spec-public-orders.ts
 
b/packages/taler-wallet-cli/src/integrationtests/test-merchant-spec-public-orders.ts
index ab7bf1ac..867af99d 100644
--- 
a/packages/taler-wallet-cli/src/integrationtests/test-merchant-spec-public-orders.ts
+++ 
b/packages/taler-wallet-cli/src/integrationtests/test-merchant-spec-public-orders.ts
@@ -21,13 +21,10 @@ import {
   ConfirmPayResultType,
   PreparePayResultType,
   URL,
-} from "@gnu-taler/taler-util";
-import {
   encodeCrock,
   getRandomBytes,
-  NodeHttpLib,
-  WalletApiOperation,
-} from "@gnu-taler/taler-wallet-core";
+} from "@gnu-taler/taler-util";
+import { NodeHttpLib, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import {
   BankService,
   ExchangeService,
@@ -566,11 +563,9 @@ async function testWithoutClaimToken(
  * specification of the endpoint.
  */
 export async function runMerchantSpecPublicOrdersTest(t: GlobalTestState) {
-  const {
-    bank,
-    exchange,
-    merchant,
-  } = await createSimpleTestkudosEnvironment(t);
+  const { bank, exchange, merchant } = await createSimpleTestkudosEnvironment(
+    t,
+  );
 
   // Base URL for the default instance.
   const merchantBaseUrl = merchant.makeInstanceBaseUrl();
diff --git a/packages/taler-wallet-cli/src/lint.ts 
b/packages/taler-wallet-cli/src/lint.ts
index 4b963387..0fed68c3 100644
--- a/packages/taler-wallet-cli/src/lint.ts
+++ b/packages/taler-wallet-cli/src/lint.ts
@@ -35,9 +35,9 @@ import {
   codecForExchangeKeysJson,
   codecForKeysManagementResponse,
   Configuration,
+  decodeCrock,
 } from "@gnu-taler/taler-util";
 import {
-  decodeCrock,
   NodeHttpLib,
   readSuccessResponseJsonOrThrow,
 } from "@gnu-taler/taler-wallet-core";
diff --git 
a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts 
b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts
index 7112964d..4ca0576b 100644
--- a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts
+++ b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts
@@ -63,9 +63,9 @@ import {
   setupTipPlanchet,
   setupWithdrawPlanchet,
   eddsaGetPublic,
-} from "../talerCrypto.js";
-import { randomBytes } from "../primitives/nacl-fast.js";
-import { kdf } from "../primitives/kdf.js";
+} from "@gnu-taler/taler-util";
+import { randomBytes } from "@gnu-taler/taler-util";
+import { kdf } from "@gnu-taler/taler-util";
 import { Timestamp, timestampTruncateToSecond } from "@gnu-taler/taler-util";
 
 import { Logger } from "@gnu-taler/taler-util";
diff --git a/packages/taler-wallet-core/src/headless/NodeHttpLib.ts 
b/packages/taler-wallet-core/src/headless/NodeHttpLib.ts
index 9655d363..5a90994b 100644
--- a/packages/taler-wallet-core/src/headless/NodeHttpLib.ts
+++ b/packages/taler-wallet-core/src/headless/NodeHttpLib.ts
@@ -28,8 +28,7 @@ import {
 import { RequestThrottler } from "../util/RequestThrottler.js";
 import Axios, { AxiosResponse } from "axios";
 import { OperationFailedError, makeErrorDetails } from "../errors.js";
-import { Logger } from "@gnu-taler/taler-util";
-import { bytesToString } from "../crypto/talerCrypto.js";
+import { Logger, bytesToString } from "@gnu-taler/taler-util";
 import { TalerErrorCode, URL } from "@gnu-taler/taler-util";
 
 const logger = new Logger("NodeHttpLib.ts");
@@ -83,7 +82,7 @@ export class NodeHttpLib implements HttpRequestLibrary {
         timeout,
         maxRedirects: 0,
       });
-    } catch (e) {
+    } catch (e: any) {
       throw OperationFailedError.fromCode(
         TalerErrorCode.WALLET_NETWORK_ERROR,
         `${e.message}`,
diff --git a/packages/taler-wallet-core/src/headless/helpers.ts 
b/packages/taler-wallet-core/src/headless/helpers.ts
index 1867fab6..f2285e14 100644
--- a/packages/taler-wallet-core/src/headless/helpers.ts
+++ b/packages/taler-wallet-core/src/headless/helpers.ts
@@ -92,7 +92,7 @@ export async function getDefaultNodeWallet(
       });
       const dbContent = JSON.parse(dbContentStr);
       myBackend.importDump(dbContent);
-    } catch (e) {
+    } catch (e: any) {
       const code: string = e.code;
       if (code === "ENOENT") {
         logger.trace("wallet file doesn't exist yet");
diff --git a/packages/taler-wallet-core/src/index.browser.ts 
b/packages/taler-wallet-core/src/index.browser.ts
index d0b82d3e..88ea5247 100644
--- a/packages/taler-wallet-core/src/index.browser.ts
+++ b/packages/taler-wallet-core/src/index.browser.ts
@@ -15,58 +15,3 @@
  */
 
 export * from "./index.js";
-
-import { setPRNG } from './crypto/primitives/nacl-fast.js';
-// export default API;
-
-function cleanup(arr: Uint8Array): void {
-  for (let i = 0; i < arr.length; i++) arr[i] = 0;
-}
-
-// Initialize PRNG if environment provides CSPRNG.
-// If not, methods calling randombytes will throw.
-// @ts-ignore-error
-const cr = typeof self !== "undefined" ? self.crypto || self.msCrypto : null;
-
-const QUOTA = 65536;
-setPRNG(function (x: Uint8Array, n: number) {
-  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)));
-  }
-  for (i = 0; i < n; i++) x[i] = v[i];
-  cleanup(v);
-});
-// function initPRNG() {
-//   // Initialize PRNG if environment provides CSPRNG.
-//   // If not, methods calling randombytes will throw.
-//   // @ts-ignore-error
-//   const cr = typeof self !== "undefined" ? self.crypto || self.msCrypto : 
null;
-//   if (cr && cr.getRandomValues) {
-//     // Browsers.
-//     const QUOTA = 65536;
-//     setPRNG(function (x: Uint8Array, n: number) {
-//       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)));
-//       }
-//       for (i = 0; i < n; i++) x[i] = v[i];
-//       cleanup(v);
-//     });
-//   } 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) {
-//         const v = cr.randomBytes(n);
-//         for (let i = 0; i < n; i++) x[i] = v[i];
-//         cleanup(v);
-//       });
-//     }
-//   }
-// }
-
-// initPRNG();
\ No newline at end of file
diff --git a/packages/taler-wallet-core/src/index.node.ts 
b/packages/taler-wallet-core/src/index.node.ts
index a3be6b5f..0860ccc2 100644
--- a/packages/taler-wallet-core/src/index.node.ts
+++ b/packages/taler-wallet-core/src/index.node.ts
@@ -22,22 +22,4 @@ export {
   getDefaultNodeWallet,
   DefaultNodeWalletArgs,
 } from "./headless/helpers.js";
-
-import { setPRNG } from './crypto/primitives/nacl-fast.js';
-import cr from 'crypto';
-
-function cleanup(arr: Uint8Array): void {
-  for (let i = 0; i < arr.length; i++) arr[i] = 0;
-}
-
-// Initialize PRNG if environment provides CSPRNG.
-// If not, methods calling randombytes will throw.
-if (cr && cr.randomBytes) {
-  setPRNG(function (x: Uint8Array, n: number) {
-    const v = cr.randomBytes(n);
-    for (let i = 0; i < n; i++) x[i] = v[i];
-    cleanup(v);
-  });
-}
-
 export * from "./crypto/workers/nodeThreadWorker.js";
diff --git a/packages/taler-wallet-core/src/index.ts 
b/packages/taler-wallet-core/src/index.ts
index 035edc76..0b360a24 100644
--- a/packages/taler-wallet-core/src/index.ts
+++ b/packages/taler-wallet-core/src/index.ts
@@ -36,7 +36,6 @@ export * from "./db-utils.js";
 export { CryptoImplementation } from 
"./crypto/workers/cryptoImplementation.js";
 export type { CryptoWorker } from "./crypto/workers/cryptoWorker.js";
 export { CryptoWorkerFactory, CryptoApi } from "./crypto/workers/cryptoApi.js";
-export * from "./crypto/talerCrypto.js";
 
 export * from "./pending-types.js";
 
diff --git a/packages/taler-wallet-core/src/operations/backup/export.ts 
b/packages/taler-wallet-core/src/operations/backup/export.ts
index 0410ab3a..a66bc2e8 100644
--- a/packages/taler-wallet-core/src/operations/backup/export.ts
+++ b/packages/taler-wallet-core/src/operations/backup/export.ts
@@ -53,14 +53,12 @@ import {
   Logger,
   timestampToIsoString,
   WalletBackupContentV1,
-} from "@gnu-taler/taler-util";
-import { InternalWalletState } from "../../common.js";
-import { hash } from "../../crypto/primitives/nacl-fast.js";
-import {
+  hash,
   encodeCrock,
   getRandomBytes,
   stringToBytes,
-} from "../../crypto/talerCrypto.js";
+} from "@gnu-taler/taler-util";
+import { InternalWalletState } from "../../common.js";
 import {
   AbortStatus,
   CoinSourceType,
diff --git a/packages/taler-wallet-core/src/operations/backup/index.ts 
b/packages/taler-wallet-core/src/operations/backup/index.ts
index b3b98fe1..913ffcb2 100644
--- a/packages/taler-wallet-core/src/operations/backup/index.ts
+++ b/packages/taler-wallet-core/src/operations/backup/index.ts
@@ -55,11 +55,11 @@ import {
 } from "@gnu-taler/taler-util";
 import { gunzipSync, gzipSync } from "fflate";
 import { InternalWalletState } from "../../common.js";
-import { kdf } from "../../crypto/primitives/kdf.js";
+import { kdf } from "@gnu-taler/taler-util";
 import {
   secretbox,
   secretbox_open,
-} from "../../crypto/primitives/nacl-fast.js";
+} from "@gnu-taler/taler-util";
 import {
   bytesToString,
   decodeCrock,
@@ -70,7 +70,7 @@ import {
   hash,
   rsaBlind,
   stringToBytes,
-} from "../../crypto/talerCrypto.js";
+} from "@gnu-taler/taler-util";
 import { CryptoApi } from "../../crypto/workers/cryptoApi.js";
 import {
   BackupProviderRecord,
diff --git a/packages/taler-wallet-core/src/operations/backup/state.ts 
b/packages/taler-wallet-core/src/operations/backup/state.ts
index 3a7311d1..dc89c3d9 100644
--- a/packages/taler-wallet-core/src/operations/backup/state.ts
+++ b/packages/taler-wallet-core/src/operations/backup/state.ts
@@ -14,7 +14,7 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-import { encodeCrock, getRandomBytes } from "../../crypto/talerCrypto.js";
+import { encodeCrock, getRandomBytes } from "@gnu-taler/taler-util";
 import {
   ConfigRecord,
   WalletBackupConfState,
diff --git a/packages/taler-wallet-core/src/operations/deposits.ts 
b/packages/taler-wallet-core/src/operations/deposits.ts
index c6c80ce9..74024205 100644
--- a/packages/taler-wallet-core/src/operations/deposits.ts
+++ b/packages/taler-wallet-core/src/operations/deposits.ts
@@ -39,12 +39,12 @@ import {
   URL,
 } from "@gnu-taler/taler-util";
 import { InternalWalletState } from "../common.js";
-import { kdf } from "../crypto/primitives/kdf.js";
+import { kdf } from "@gnu-taler/taler-util";
 import {
   encodeCrock,
   getRandomBytes,
   stringToBytes,
-} from "../crypto/talerCrypto.js";
+} from "@gnu-taler/taler-util";
 import { DepositGroupRecord } from "../db.js";
 import { guardOperationException } from "../errors.js";
 import { selectPayCoins } from "../util/coinSelection.js";
diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts 
b/packages/taler-wallet-core/src/operations/exchanges.ts
index 9cd20c67..fc776c81 100644
--- a/packages/taler-wallet-core/src/operations/exchanges.ts
+++ b/packages/taler-wallet-core/src/operations/exchanges.ts
@@ -40,7 +40,7 @@ import {
   TalerErrorDetails,
   Timestamp,
 } from "@gnu-taler/taler-util";
-import { decodeCrock, encodeCrock, hash } from "../crypto/talerCrypto.js";
+import { decodeCrock, encodeCrock, hash } from "@gnu-taler/taler-util";
 import { CryptoApi } from "../crypto/workers/cryptoApi.js";
 import {
   DenominationRecord,
diff --git a/packages/taler-wallet-core/src/operations/pay.ts 
b/packages/taler-wallet-core/src/operations/pay.ts
index 91268400..079ffcd9 100644
--- a/packages/taler-wallet-core/src/operations/pay.ts
+++ b/packages/taler-wallet-core/src/operations/pay.ts
@@ -54,7 +54,7 @@ import {
   URL,
   getDurationRemaining,
 } from "@gnu-taler/taler-util";
-import { encodeCrock, getRandomBytes } from "../crypto/talerCrypto.js";
+import { encodeCrock, getRandomBytes } from "@gnu-taler/taler-util";
 import {
   PayCoinSelection,
   CoinCandidateSelection,
diff --git a/packages/taler-wallet-core/src/operations/recoup.ts 
b/packages/taler-wallet-core/src/operations/recoup.ts
index 63446992..b1f46e4b 100644
--- a/packages/taler-wallet-core/src/operations/recoup.ts
+++ b/packages/taler-wallet-core/src/operations/recoup.ts
@@ -32,7 +32,7 @@ import {
   RefreshReason,
   TalerErrorDetails,
 } from "@gnu-taler/taler-util";
-import { encodeCrock, getRandomBytes } from "../crypto/talerCrypto.js";
+import { encodeCrock, getRandomBytes } from "@gnu-taler/taler-util";
 import {
   CoinRecord,
   CoinSourceType,
diff --git a/packages/taler-wallet-core/src/operations/refresh.ts 
b/packages/taler-wallet-core/src/operations/refresh.ts
index a7b64f5d..85de813d 100644
--- a/packages/taler-wallet-core/src/operations/refresh.ts
+++ b/packages/taler-wallet-core/src/operations/refresh.ts
@@ -14,7 +14,7 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-import { encodeCrock, getRandomBytes } from "../crypto/talerCrypto.js";
+import { encodeCrock, getRandomBytes } from "@gnu-taler/taler-util";
 import {
   CoinRecord,
   CoinSourceType,
diff --git a/packages/taler-wallet-core/src/operations/reserves.ts 
b/packages/taler-wallet-core/src/operations/reserves.ts
index 4cbb9b9b..4b5862be 100644
--- a/packages/taler-wallet-core/src/operations/reserves.ts
+++ b/packages/taler-wallet-core/src/operations/reserves.ts
@@ -32,7 +32,7 @@ import {
   TalerErrorCode,
   addPaytoQueryParams,
 } from "@gnu-taler/taler-util";
-import { randomBytes } from "../crypto/primitives/nacl-fast.js";
+import { randomBytes } from "@gnu-taler/taler-util";
 import {
   ReserveRecordStatus,
   ReserveBankInfo,
@@ -63,7 +63,7 @@ import {
   processWithdrawGroup,
   getBankWithdrawalInfo,
 } from "./withdraw.js";
-import { encodeCrock, getRandomBytes } from "../crypto/talerCrypto.js";
+import { encodeCrock, getRandomBytes } from "@gnu-taler/taler-util";
 import { Logger, URL } from "@gnu-taler/taler-util";
 import {
   readSuccessResponseJsonOrErrorCode,
diff --git a/packages/taler-wallet-core/src/operations/tip.ts 
b/packages/taler-wallet-core/src/operations/tip.ts
index 29eeb8d5..a90e5270 100644
--- a/packages/taler-wallet-core/src/operations/tip.ts
+++ b/packages/taler-wallet-core/src/operations/tip.ts
@@ -55,7 +55,7 @@ import {
   getHttpResponseErrorDetails,
   readSuccessResponseJsonOrThrow,
 } from "../util/http.js";
-import { encodeCrock, getRandomBytes } from "../crypto/talerCrypto.js";
+import { encodeCrock, getRandomBytes } from "@gnu-taler/taler-util";
 
 const logger = new Logger("operations/tip.ts");
 
diff --git a/packages/taler-wallet-core/src/util/contractTerms.ts 
b/packages/taler-wallet-core/src/util/contractTerms.ts
index e5280244..652ef707 100644
--- a/packages/taler-wallet-core/src/util/contractTerms.ts
+++ b/packages/taler-wallet-core/src/util/contractTerms.ts
@@ -15,14 +15,14 @@
  */
 
 import { canonicalJson } from "@gnu-taler/taler-util";
-import { kdf } from "../crypto/primitives/kdf.js";
+import { kdf } from "@gnu-taler/taler-util";
 import {
   decodeCrock,
   encodeCrock,
   getRandomBytes,
   hash,
   stringToBytes,
-} from "../crypto/talerCrypto.js";
+} from "@gnu-taler/taler-util";
 
 export namespace ContractTermsUtil {
   export type PathPredicate = (path: string[]) => boolean;
diff --git a/packages/taler-wallet-core/src/util/http.ts 
b/packages/taler-wallet-core/src/util/http.ts
index e056ffce..d01f2ee4 100644
--- a/packages/taler-wallet-core/src/util/http.ts
+++ b/packages/taler-wallet-core/src/util/http.ts
@@ -198,7 +198,7 @@ export async function readSuccessResponseJsonOrErrorCode<T>(
   let parsedResponse: T;
   try {
     parsedResponse = codec.decode(respJson);
-  } catch (e) {
+  } catch (e: any) {
     throw OperationFailedError.fromCode(
       TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
       "Response invalid",
diff --git a/packages/taler-wallet-webextension/src/popup/ProviderAddPage.tsx 
b/packages/taler-wallet-webextension/src/popup/ProviderAddPage.tsx
index 6b6e8f5c..55686ee9 100644
--- a/packages/taler-wallet-webextension/src/popup/ProviderAddPage.tsx
+++ b/packages/taler-wallet-webextension/src/popup/ProviderAddPage.tsx
@@ -14,13 +14,24 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-import { Amounts, BackupBackupProviderTerms, canonicalizeBaseUrl, i18n } from 
"@gnu-taler/taler-util";
-import { verify } from 
"@gnu-taler/taler-wallet-core/src/crypto/primitives/nacl-fast";
+import {
+  Amounts,
+  BackupBackupProviderTerms,
+  canonicalizeBaseUrl,
+  i18n,
+} from "@gnu-taler/taler-util";
 import { VNode, h } from "preact";
 import { useEffect, useState } from "preact/hooks";
 import { Checkbox } from "../components/Checkbox";
 import { ErrorMessage } from "../components/ErrorMessage";
-import { Button, ButtonPrimary, Input, LightText, PopupBox, SmallLightText } 
from "../components/styled/index";
+import {
+  Button,
+  ButtonPrimary,
+  Input,
+  LightText,
+  PopupBox,
+  SmallLightText,
+} from "../components/styled/index";
 import * as wxApi from "../wxApi";
 
 interface Props {
@@ -30,52 +41,65 @@ interface Props {
 
 function getJsonIfOk(r: Response) {
   if (r.ok) {
-    return r.json()
+    return r.json();
   } else {
     if (r.status >= 400 && r.status < 500) {
-      throw new Error(`URL may not be right: (${r.status}) ${r.statusText}`)
+      throw new Error(`URL may not be right: (${r.status}) ${r.statusText}`);
     } else {
-      throw new Error(`Try another server: (${r.status}) ${r.statusText || 
'internal server error'}`)
+      throw new Error(
+        `Try another server: (${r.status}) ${
+          r.statusText || "internal server error"
+        }`,
+      );
     }
   }
 }
 
-
 export function ProviderAddPage({ onBack }: Props): VNode {
-  const [verifying, setVerifying] = useState<{ url: string, name: string, 
provider: BackupBackupProviderTerms } | undefined>(undefined)
-
-  async function getProviderInfo(url: string): 
Promise<BackupBackupProviderTerms> {
+  const [verifying, setVerifying] = useState<
+    | { url: string; name: string; provider: BackupBackupProviderTerms }
+    | undefined
+  >(undefined);
+
+  async function getProviderInfo(
+    url: string,
+  ): Promise<BackupBackupProviderTerms> {
     return fetch(`${url}config`)
-      .catch(e => { throw new Error(`Network error`) })
-      .then(getJsonIfOk)
+      .catch((e) => {
+        throw new Error(`Network error`);
+      })
+      .then(getJsonIfOk);
   }
 
   if (!verifying) {
-    return <SetUrlView
-      onCancel={onBack}
-      onVerify={(url) => getProviderInfo(url)}
-      onConfirm={(url, name) => getProviderInfo(url)
-        .then((provider) => {
-          setVerifying({ url, name, provider });
-        })
-        .catch(e => e.message)
-      }
-    />
+    return (
+      <SetUrlView
+        onCancel={onBack}
+        onVerify={(url) => getProviderInfo(url)}
+        onConfirm={(url, name) =>
+          getProviderInfo(url)
+            .then((provider) => {
+              setVerifying({ url, name, provider });
+            })
+            .catch((e) => e.message)
+        }
+      />
+    );
   }
-  return <ConfirmProviderView
-    provider={verifying.provider}
-    url={verifying.url}
-    onCancel={() => {
-      setVerifying(undefined);
-    }}
-    onConfirm={() => {
-      wxApi.addBackupProvider(verifying.url, verifying.name).then(onBack)
-    }}
-
-  />
+  return (
+    <ConfirmProviderView
+      provider={verifying.provider}
+      url={verifying.url}
+      onCancel={() => {
+        setVerifying(undefined);
+      }}
+      onConfirm={() => {
+        wxApi.addBackupProvider(verifying.url, verifying.name).then(onBack);
+      }}
+    />
+  );
 }
 
-
 export interface SetUrlViewProps {
   initialValue?: string;
   onCancel: () => void;
@@ -84,83 +108,137 @@ export interface SetUrlViewProps {
   withError?: string;
 }
 
-export function SetUrlView({ initialValue, onCancel, onVerify, onConfirm, 
withError }: SetUrlViewProps) {
-  const [value, setValue] = useState<string>(initialValue || "")
-  const [urlError, setUrlError] = useState(false)
-  const [name, setName] = useState<string|undefined>(undefined)
-  const [error, setError] = useState<string | undefined>(withError)
+export function SetUrlView({
+  initialValue,
+  onCancel,
+  onVerify,
+  onConfirm,
+  withError,
+}: SetUrlViewProps) {
+  const [value, setValue] = useState<string>(initialValue || "");
+  const [urlError, setUrlError] = useState(false);
+  const [name, setName] = useState<string | undefined>(undefined);
+  const [error, setError] = useState<string | undefined>(withError);
   useEffect(() => {
     try {
-      const url = canonicalizeBaseUrl(value)
-      onVerify(url).then(r => {
-        setUrlError(false)
-        setName(new URL(url).hostname)
-      }).catch(() => {
-        setUrlError(true)
-        setName(undefined)
-      })
+      const url = canonicalizeBaseUrl(value);
+      onVerify(url)
+        .then((r) => {
+          setUrlError(false);
+          setName(new URL(url).hostname);
+        })
+        .catch(() => {
+          setUrlError(true);
+          setName(undefined);
+        });
     } catch {
-      setUrlError(true)
-      setName(undefined)
+      setUrlError(true);
+      setName(undefined);
     }
-  }, [value])
-  return <PopupBox>
-    <section>
-      <h1> Add backup provider</h1>
-      <ErrorMessage title={error && "Could not get provider information"} 
description={error} />
-      <LightText> Backup providers may charge for their service</LightText>
-      <p>
-        <Input invalid={urlError}>
-          <label>URL</label>
-          <input type="text" placeholder="https://"; value={value} 
onChange={(e) => setValue(e.currentTarget.value)} />
-        </Input>
-        <Input>
-          <label>Name</label>
-          <input type="text" disabled={name === undefined} value={name} 
onChange={e => setName(e.currentTarget.value)}/>
-        </Input>
-      </p>
-    </section>
-    <footer>
-      <Button onClick={onCancel}><i18n.Translate> &lt; 
Back</i18n.Translate></Button>
-      <ButtonPrimary
-        disabled={!value && !urlError}
-        onClick={() => {
-          const url = canonicalizeBaseUrl(value)
-          return onConfirm(url, name!).then(r => r ? setError(r) : undefined)
-        }}><i18n.Translate>Next</i18n.Translate></ButtonPrimary>
-    </footer>
-  </PopupBox>
+  }, [value]);
+  return (
+    <PopupBox>
+      <section>
+        <h1> Add backup provider</h1>
+        <ErrorMessage
+          title={error && "Could not get provider information"}
+          description={error}
+        />
+        <LightText> Backup providers may charge for their service</LightText>
+        <p>
+          <Input invalid={urlError}>
+            <label>URL</label>
+            <input
+              type="text"
+              placeholder="https://";
+              value={value}
+              onChange={(e) => setValue(e.currentTarget.value)}
+            />
+          </Input>
+          <Input>
+            <label>Name</label>
+            <input
+              type="text"
+              disabled={name === undefined}
+              value={name}
+              onChange={(e) => setName(e.currentTarget.value)}
+            />
+          </Input>
+        </p>
+      </section>
+      <footer>
+        <Button onClick={onCancel}>
+          <i18n.Translate> &lt; Back</i18n.Translate>
+        </Button>
+        <ButtonPrimary
+          disabled={!value && !urlError}
+          onClick={() => {
+            const url = canonicalizeBaseUrl(value);
+            return onConfirm(url, name!).then((r) =>
+              r ? setError(r) : undefined,
+            );
+          }}
+        >
+          <i18n.Translate>Next</i18n.Translate>
+        </ButtonPrimary>
+      </footer>
+    </PopupBox>
+  );
 }
 
 export interface ConfirmProviderViewProps {
-  provider: BackupBackupProviderTerms,
-  url: string,
+  provider: BackupBackupProviderTerms;
+  url: string;
   onCancel: () => void;
   onConfirm: () => void;
 }
-export function ConfirmProviderView({ url, provider, onCancel, onConfirm }: 
ConfirmProviderViewProps) {
+export function ConfirmProviderView({
+  url,
+  provider,
+  onCancel,
+  onConfirm,
+}: ConfirmProviderViewProps) {
   const [accepted, setAccepted] = useState(false);
 
-  return <PopupBox>
-    <section>
-      <h1>Review terms of service</h1>
-      <div>Provider URL: <a href={url} target="_blank">{url}</a></div>
-      <SmallLightText>Please review and accept this provider's terms of 
service</SmallLightText>
-      <h2>1. Pricing</h2>
-      <p>
-        {Amounts.isZero(provider.annual_fee) ? 'free of charge' : 
`${provider.annual_fee} per year of service`}
-      </p>
-      <h2>2. Storage</h2>
-      <p>
-        {provider.storage_limit_in_megabytes} megabytes of storage per year of 
service
-      </p>
-      <Checkbox label="Accept terms of service" name="terms" onToggle={() => 
setAccepted(old => !old)} enabled={accepted} />
-    </section>
-    <footer>
-      <Button onClick={onCancel}><i18n.Translate> &lt; 
Back</i18n.Translate></Button>
-      <ButtonPrimary
-        disabled={!accepted}
-        onClick={onConfirm}><i18n.Translate>Add 
provider</i18n.Translate></ButtonPrimary>
-    </footer>
-  </PopupBox>
+  return (
+    <PopupBox>
+      <section>
+        <h1>Review terms of service</h1>
+        <div>
+          Provider URL:{" "}
+          <a href={url} target="_blank">
+            {url}
+          </a>
+        </div>
+        <SmallLightText>
+          Please review and accept this provider's terms of service
+        </SmallLightText>
+        <h2>1. Pricing</h2>
+        <p>
+          {Amounts.isZero(provider.annual_fee)
+            ? "free of charge"
+            : `${provider.annual_fee} per year of service`}
+        </p>
+        <h2>2. Storage</h2>
+        <p>
+          {provider.storage_limit_in_megabytes} megabytes of storage per year 
of
+          service
+        </p>
+        <Checkbox
+          label="Accept terms of service"
+          name="terms"
+          onToggle={() => setAccepted((old) => !old)}
+          enabled={accepted}
+        />
+      </section>
+      <footer>
+        <Button onClick={onCancel}>
+          <i18n.Translate> &lt; Back</i18n.Translate>
+        </Button>
+        <ButtonPrimary disabled={!accepted} onClick={onConfirm}>
+          <i18n.Translate>Add provider</i18n.Translate>
+        </ButtonPrimary>
+      </footer>
+    </PopupBox>
+  );
 }
diff --git a/packages/taler-wallet-webextension/src/wallet/ProviderAddPage.tsx 
b/packages/taler-wallet-webextension/src/wallet/ProviderAddPage.tsx
index 14384f23..1c7fdc82 100644
--- a/packages/taler-wallet-webextension/src/wallet/ProviderAddPage.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/ProviderAddPage.tsx
@@ -14,13 +14,24 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-import { Amounts, BackupBackupProviderTerms, canonicalizeBaseUrl, i18n } from 
"@gnu-taler/taler-util";
-import { verify } from 
"@gnu-taler/taler-wallet-core/src/crypto/primitives/nacl-fast";
+import {
+  Amounts,
+  BackupBackupProviderTerms,
+  canonicalizeBaseUrl,
+  i18n,
+} from "@gnu-taler/taler-util";
 import { VNode, h } from "preact";
 import { useEffect, useState } from "preact/hooks";
 import { Checkbox } from "../components/Checkbox";
 import { ErrorMessage } from "../components/ErrorMessage";
-import { Button, ButtonPrimary, Input, LightText, WalletBox, SmallLightText } 
from "../components/styled/index";
+import {
+  Button,
+  ButtonPrimary,
+  Input,
+  LightText,
+  WalletBox,
+  SmallLightText,
+} from "../components/styled/index";
 import * as wxApi from "../wxApi";
 
 interface Props {
@@ -30,52 +41,65 @@ interface Props {
 
 function getJsonIfOk(r: Response) {
   if (r.ok) {
-    return r.json()
+    return r.json();
   } else {
     if (r.status >= 400 && r.status < 500) {
-      throw new Error(`URL may not be right: (${r.status}) ${r.statusText}`)
+      throw new Error(`URL may not be right: (${r.status}) ${r.statusText}`);
     } else {
-      throw new Error(`Try another server: (${r.status}) ${r.statusText || 
'internal server error'}`)
+      throw new Error(
+        `Try another server: (${r.status}) ${
+          r.statusText || "internal server error"
+        }`,
+      );
     }
   }
 }
 
-
 export function ProviderAddPage({ onBack }: Props): VNode {
-  const [verifying, setVerifying] = useState<{ url: string, name: string, 
provider: BackupBackupProviderTerms } | undefined>(undefined)
-
-  async function getProviderInfo(url: string): 
Promise<BackupBackupProviderTerms> {
+  const [verifying, setVerifying] = useState<
+    | { url: string; name: string; provider: BackupBackupProviderTerms }
+    | undefined
+  >(undefined);
+
+  async function getProviderInfo(
+    url: string,
+  ): Promise<BackupBackupProviderTerms> {
     return fetch(`${url}config`)
-      .catch(e => { throw new Error(`Network error`) })
-      .then(getJsonIfOk)
+      .catch((e) => {
+        throw new Error(`Network error`);
+      })
+      .then(getJsonIfOk);
   }
 
   if (!verifying) {
-    return <SetUrlView
-      onCancel={onBack}
-      onVerify={(url) => getProviderInfo(url)}
-      onConfirm={(url, name) => getProviderInfo(url)
-        .then((provider) => {
-          setVerifying({ url, name, provider });
-        })
-        .catch(e => e.message)
-      }
-    />
+    return (
+      <SetUrlView
+        onCancel={onBack}
+        onVerify={(url) => getProviderInfo(url)}
+        onConfirm={(url, name) =>
+          getProviderInfo(url)
+            .then((provider) => {
+              setVerifying({ url, name, provider });
+            })
+            .catch((e) => e.message)
+        }
+      />
+    );
   }
-  return <ConfirmProviderView
-    provider={verifying.provider}
-    url={verifying.url}
-    onCancel={() => {
-      setVerifying(undefined);
-    }}
-    onConfirm={() => {
-      wxApi.addBackupProvider(verifying.url, verifying.name).then(onBack)
-    }}
-
-  />
+  return (
+    <ConfirmProviderView
+      provider={verifying.provider}
+      url={verifying.url}
+      onCancel={() => {
+        setVerifying(undefined);
+      }}
+      onConfirm={() => {
+        wxApi.addBackupProvider(verifying.url, verifying.name).then(onBack);
+      }}
+    />
+  );
 }
 
-
 export interface SetUrlViewProps {
   initialValue?: string;
   onCancel: () => void;
@@ -84,83 +108,137 @@ export interface SetUrlViewProps {
   withError?: string;
 }
 
-export function SetUrlView({ initialValue, onCancel, onVerify, onConfirm, 
withError }: SetUrlViewProps) {
-  const [value, setValue] = useState<string>(initialValue || "")
-  const [urlError, setUrlError] = useState(false)
-  const [name, setName] = useState<string|undefined>(undefined)
-  const [error, setError] = useState<string | undefined>(withError)
+export function SetUrlView({
+  initialValue,
+  onCancel,
+  onVerify,
+  onConfirm,
+  withError,
+}: SetUrlViewProps) {
+  const [value, setValue] = useState<string>(initialValue || "");
+  const [urlError, setUrlError] = useState(false);
+  const [name, setName] = useState<string | undefined>(undefined);
+  const [error, setError] = useState<string | undefined>(withError);
   useEffect(() => {
     try {
-      const url = canonicalizeBaseUrl(value)
-      onVerify(url).then(r => {
-        setUrlError(false)
-        setName(new URL(url).hostname)
-      }).catch(() => {
-        setUrlError(true)
-        setName(undefined)
-      })
+      const url = canonicalizeBaseUrl(value);
+      onVerify(url)
+        .then((r) => {
+          setUrlError(false);
+          setName(new URL(url).hostname);
+        })
+        .catch(() => {
+          setUrlError(true);
+          setName(undefined);
+        });
     } catch {
-      setUrlError(true)
-      setName(undefined)
+      setUrlError(true);
+      setName(undefined);
     }
-  }, [value])
-  return <WalletBox>
-    <section>
-      <h1> Add backup provider</h1>
-      <ErrorMessage title={error && "Could not get provider information"} 
description={error} />
-      <LightText> Backup providers may charge for their service</LightText>
-      <p>
-        <Input invalid={urlError}>
-          <label>URL</label>
-          <input type="text" placeholder="https://"; value={value} 
onChange={(e) => setValue(e.currentTarget.value)} />
-        </Input>
-        <Input>
-          <label>Name</label>
-          <input type="text" disabled={name === undefined} value={name} 
onChange={e => setName(e.currentTarget.value)}/>
-        </Input>
-      </p>
-    </section>
-    <footer>
-      <Button onClick={onCancel}><i18n.Translate> &lt; 
Back</i18n.Translate></Button>
-      <ButtonPrimary
-        disabled={!value && !urlError}
-        onClick={() => {
-          const url = canonicalizeBaseUrl(value)
-          return onConfirm(url, name!).then(r => r ? setError(r) : undefined)
-        }}><i18n.Translate>Next</i18n.Translate></ButtonPrimary>
-    </footer>
-  </WalletBox>
+  }, [value]);
+  return (
+    <WalletBox>
+      <section>
+        <h1> Add backup provider</h1>
+        <ErrorMessage
+          title={error && "Could not get provider information"}
+          description={error}
+        />
+        <LightText> Backup providers may charge for their service</LightText>
+        <p>
+          <Input invalid={urlError}>
+            <label>URL</label>
+            <input
+              type="text"
+              placeholder="https://";
+              value={value}
+              onChange={(e) => setValue(e.currentTarget.value)}
+            />
+          </Input>
+          <Input>
+            <label>Name</label>
+            <input
+              type="text"
+              disabled={name === undefined}
+              value={name}
+              onChange={(e) => setName(e.currentTarget.value)}
+            />
+          </Input>
+        </p>
+      </section>
+      <footer>
+        <Button onClick={onCancel}>
+          <i18n.Translate> &lt; Back</i18n.Translate>
+        </Button>
+        <ButtonPrimary
+          disabled={!value && !urlError}
+          onClick={() => {
+            const url = canonicalizeBaseUrl(value);
+            return onConfirm(url, name!).then((r) =>
+              r ? setError(r) : undefined,
+            );
+          }}
+        >
+          <i18n.Translate>Next</i18n.Translate>
+        </ButtonPrimary>
+      </footer>
+    </WalletBox>
+  );
 }
 
 export interface ConfirmProviderViewProps {
-  provider: BackupBackupProviderTerms,
-  url: string,
+  provider: BackupBackupProviderTerms;
+  url: string;
   onCancel: () => void;
   onConfirm: () => void;
 }
-export function ConfirmProviderView({ url, provider, onCancel, onConfirm }: 
ConfirmProviderViewProps) {
+export function ConfirmProviderView({
+  url,
+  provider,
+  onCancel,
+  onConfirm,
+}: ConfirmProviderViewProps) {
   const [accepted, setAccepted] = useState(false);
 
-  return <WalletBox>
-    <section>
-      <h1>Review terms of service</h1>
-      <div>Provider URL: <a href={url} target="_blank">{url}</a></div>
-      <SmallLightText>Please review and accept this provider's terms of 
service</SmallLightText>
-      <h2>1. Pricing</h2>
-      <p>
-        {Amounts.isZero(provider.annual_fee) ? 'free of charge' : 
`${provider.annual_fee} per year of service`}
-      </p>
-      <h2>2. Storage</h2>
-      <p>
-        {provider.storage_limit_in_megabytes} megabytes of storage per year of 
service
-      </p>
-      <Checkbox label="Accept terms of service" name="terms" onToggle={() => 
setAccepted(old => !old)} enabled={accepted} />
-    </section>
-    <footer>
-      <Button onClick={onCancel}><i18n.Translate> &lt; 
Back</i18n.Translate></Button>
-      <ButtonPrimary
-        disabled={!accepted}
-        onClick={onConfirm}><i18n.Translate>Add 
provider</i18n.Translate></ButtonPrimary>
-    </footer>
-  </WalletBox>
+  return (
+    <WalletBox>
+      <section>
+        <h1>Review terms of service</h1>
+        <div>
+          Provider URL:{" "}
+          <a href={url} target="_blank">
+            {url}
+          </a>
+        </div>
+        <SmallLightText>
+          Please review and accept this provider's terms of service
+        </SmallLightText>
+        <h2>1. Pricing</h2>
+        <p>
+          {Amounts.isZero(provider.annual_fee)
+            ? "free of charge"
+            : `${provider.annual_fee} per year of service`}
+        </p>
+        <h2>2. Storage</h2>
+        <p>
+          {provider.storage_limit_in_megabytes} megabytes of storage per year 
of
+          service
+        </p>
+        <Checkbox
+          label="Accept terms of service"
+          name="terms"
+          onToggle={() => setAccepted((old) => !old)}
+          enabled={accepted}
+        />
+      </section>
+      <footer>
+        <Button onClick={onCancel}>
+          <i18n.Translate> &lt; Back</i18n.Translate>
+        </Button>
+        <ButtonPrimary disabled={!accepted} onClick={onConfirm}>
+          <i18n.Translate>Add provider</i18n.Translate>
+        </ButtonPrimary>
+      </footer>
+    </WalletBox>
+  );
 }
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index bea05dec..b14baed1 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -12,6 +12,19 @@ importers:
       '@linaria/shaker': 3.0.0-beta.7
       esbuild: 0.12.21
 
+  packages/anastasis-core:
+    specifiers:
+      '@gnu-taler/taler-util': workspace:^0.8.3
+      ava: ^3.15.0
+      hash-wasm: ^4.9.0
+      typescript: ^4.4.3
+    dependencies:
+      '@gnu-taler/taler-util': link:../taler-util
+      hash-wasm: 4.9.0
+    devDependencies:
+      ava: 3.15.0
+      typescript: 4.4.3
+
   packages/idb-bridge:
     specifiers:
       '@rollup/plugin-commonjs': ^17.1.0
@@ -52,6 +65,7 @@ importers:
     specifiers:
       '@types/node': ^14.14.22
       ava: ^3.15.0
+      big-integer: ^1.6.48
       esbuild: ^0.9.2
       jed: ^1.1.1
       prettier: ^2.2.1
@@ -59,6 +73,7 @@ importers:
       tslib: ^2.1.0
       typescript: ^4.2.3
     dependencies:
+      big-integer: 1.6.48
       jed: 1.1.1
       tslib: 2.1.0
     devDependencies:
@@ -11813,6 +11828,10 @@ packages:
       safe-buffer: 5.2.1
     dev: true
 
+  /hash-wasm/4.9.0:
+    resolution: {integrity: 
sha512-7SW7ejyfnRxuOc7ptQHSf4LDoZaWOivfzqw+5rpcQku0nHfmicPKE51ra9BiRLAmT8+gGLestr1XroUkqdjL6w==}
+    dev: false
+
   /hash.js/1.1.7:
     resolution: {integrity: 
sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==}
     dependencies:
@@ -19292,6 +19311,12 @@ packages:
     hasBin: true
     dev: true
 
+  /typescript/4.4.3:
+    resolution: {integrity: 
sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==}
+    engines: {node: '>=4.2.0'}
+    hasBin: true
+    dev: true
+
   /uglify-js/3.12.5:
     resolution: {integrity: 
sha512-SgpgScL4T7Hj/w/GexjnBHi3Ien9WS1Rpfg5y91WXMj9SY997ZCQU76mH4TpLwwfmMvoOU8wiaRkIf6NaH3mtg==}
     engines: {node: '>=0.8.0'}

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

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