gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] branch master updated: wallet: implement exchange pr


From: gnunet
Subject: [taler-wallet-core] branch master updated: wallet: implement exchange protocol v9
Date: Wed, 17 Nov 2021 10:23:33 +0100

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 9f0429cb wallet: implement exchange protocol v9
9f0429cb is described below

commit 9f0429cb2f8ad9cb2e98a787139602d913c1aefa
Author: Florian Dold <florian@dold.me>
AuthorDate: Wed Nov 17 10:23:22 2021 +0100

    wallet: implement exchange protocol v9
---
 package.json                                       |   2 +-
 packages/taler-util/src/backupTypes.ts             |   5 +-
 packages/taler-util/src/helpers.ts                 |  11 +-
 packages/taler-util/src/talerCrypto.ts             |  15 +
 packages/taler-util/src/talerTypes.ts              |  77 ++++-
 packages/taler-util/src/walletTypes.ts             |   8 +-
 packages/taler-wallet-core/package.json            |   2 +-
 .../taler-wallet-core/src/crypto/cryptoTypes.ts    |   6 +-
 .../src/crypto/workers/cryptoImplementation.ts     |  50 ++-
 packages/taler-wallet-core/src/db.ts               |  13 +-
 packages/taler-wallet-core/src/errors.ts           |   2 +-
 .../src/operations/backup/import.ts                |   9 +-
 .../src/operations/backup/index.ts                 |  19 +-
 .../taler-wallet-core/src/operations/deposits.ts   |   9 +-
 .../taler-wallet-core/src/operations/exchanges.ts  |  42 +--
 .../taler-wallet-core/src/operations/refresh.ts    |  25 +-
 packages/taler-wallet-core/src/operations/tip.ts   |  15 +-
 .../src/operations/withdraw.test.ts                |  44 ++-
 .../taler-wallet-core/src/operations/withdraw.ts   |  35 +-
 .../src/util/coinSelection.test.ts                 |   5 +-
 .../taler-wallet-core/src/util/coinSelection.ts    |  21 +-
 packages/taler-wallet-core/src/wallet.ts           |   3 +-
 pnpm-lock.yaml                                     | 371 ++++++++++++++++++---
 23 files changed, 619 insertions(+), 170 deletions(-)

diff --git a/package.json b/package.json
index d857a011..e00de0c5 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,6 @@
     "@linaria/esbuild": "^3.0.0-beta.13",
     "@linaria/shaker": "^3.0.0-beta.13",
     "esbuild": "^0.12.29",
-    "prettier": "^2.2.1"
+    "prettier": "^2.4.1"
   }
 }
diff --git a/packages/taler-util/src/backupTypes.ts 
b/packages/taler-util/src/backupTypes.ts
index 70e52e63..ecdd6fdf 100644
--- a/packages/taler-util/src/backupTypes.ts
+++ b/packages/taler-util/src/backupTypes.ts
@@ -53,6 +53,7 @@
 /**
  * Imports.
  */
+import { DenominationPubKey, UnblindedSignature } from "./talerTypes.js";
 import { Duration, Timestamp } from "./time.js";
 
 /**
@@ -440,7 +441,7 @@ export interface BackupCoin {
   /**
    * Unblinded signature by the exchange.
    */
-  denom_sig: string;
+  denom_sig: UnblindedSignature;
 
   /**
    * Amount that's left on the coin.
@@ -831,7 +832,7 @@ export interface BackupDenomination {
   /**
    * The denomination public key.
    */
-  denom_pub: string;
+  denom_pub: DenominationPubKey;
 
   /**
    * Fee for withdrawing.
diff --git a/packages/taler-util/src/helpers.ts 
b/packages/taler-util/src/helpers.ts
index 089602c9..6c836c48 100644
--- a/packages/taler-util/src/helpers.ts
+++ b/packages/taler-util/src/helpers.ts
@@ -94,7 +94,7 @@ export function canonicalJson(obj: any): string {
 /**
  * Lexically compare two strings.
  */
-export function strcmp(s1: string, s2: string): number {
+export function strcmp(s1: string, s2: string): -1 | 0 | 1 {
   if (s1 < s2) {
     return -1;
   }
@@ -113,15 +113,14 @@ export function j2s(x: any): string {
 
 /**
  * Use this to filter null or undefined from an array in a type-safe fashion
- * 
+ *
  * example:
  * const array: Array<T | undefined> = [undefined, null]
  * const filtered: Array<T> = array.filter(notEmpty)
- * 
- * @param value 
- * @returns 
+ *
+ * @param value
+ * @returns
  */
 export function notEmpty<T>(value: T | null | undefined): value is T {
   return value !== null && value !== undefined;
 }
-
diff --git a/packages/taler-util/src/talerCrypto.ts 
b/packages/taler-util/src/talerCrypto.ts
index d8ac75dc..b107786c 100644
--- a/packages/taler-util/src/talerCrypto.ts
+++ b/packages/taler-util/src/talerCrypto.ts
@@ -24,6 +24,7 @@
 import * as nacl from "./nacl-fast.js";
 import { kdf } from "./kdf.js";
 import bigint from "big-integer";
+import { DenominationPubKey } from "./talerTypes.js";
 
 export function getRandomBytes(n: number): Uint8Array {
   return nacl.randomBytes(n);
@@ -348,6 +349,20 @@ export function hash(d: Uint8Array): Uint8Array {
   return nacl.hash(d);
 }
 
+export function hashDenomPub(pub: DenominationPubKey): Uint8Array {
+  if (pub.cipher !== 1) {
+    throw Error("unsupported cipher");
+  }
+  const pubBuf = decodeCrock(pub.rsa_public_key);
+  const hashInputBuf = new ArrayBuffer(pubBuf.length + 4 + 4);
+  const uint8ArrayBuf = new Uint8Array(hashInputBuf);
+  const dv = new DataView(hashInputBuf);
+  dv.setUint32(0, pub.age_mask ?? 0);
+  dv.setUint32(4, pub.cipher);
+  uint8ArrayBuf.set(pubBuf, 8);
+  return nacl.hash(uint8ArrayBuf);
+}
+
 export function eddsaSign(msg: Uint8Array, eddsaPriv: Uint8Array): Uint8Array {
   const pair = nacl.crypto_sign_keyPair_fromSeed(eddsaPriv);
   return nacl.sign_detached(msg, pair.secretKey);
diff --git a/packages/taler-util/src/talerTypes.ts 
b/packages/taler-util/src/talerTypes.ts
index 56110ec1..04d70048 100644
--- a/packages/taler-util/src/talerTypes.ts
+++ b/packages/taler-util/src/talerTypes.ts
@@ -59,7 +59,7 @@ export class Denomination {
   /**
    * Public signing key of the denomination.
    */
-  denom_pub: string;
+  denom_pub: DenominationPubKey;
 
   /**
    * Fee for withdrawing.
@@ -158,7 +158,7 @@ export interface RecoupRequest {
   /**
    * Signature over the coin public key by the denomination.
    */
-  denom_sig: string;
+  denom_sig: UnblindedSignature;
 
   /**
    * Coin public key of the coin we want to refund.
@@ -198,6 +198,11 @@ export interface RecoupConfirmation {
   old_coin_pub?: string;
 }
 
+export interface UnblindedSignature {
+  cipher: DenomKeyType.Rsa;
+  rsa_signature: string;
+}
+
 /**
  * Deposit permission for a single coin.
  */
@@ -213,7 +218,7 @@ export interface CoinDepositPermission {
   /**
    * Signature made by the denomination public key.
    */
-  ub_sig: string;
+  ub_sig: UnblindedSignature;
   /**
    * The denomination public key associated with this coin.
    */
@@ -779,8 +784,38 @@ export class TipPickupGetResponse {
   expiration: Timestamp;
 }
 
+export enum DenomKeyType {
+  Rsa = 1,
+  ClauseSchnorr = 2,
+}
+
+export interface RsaBlindedDenominationSignature {
+  cipher: DenomKeyType.Rsa;
+  blinded_rsa_signature: string;
+}
+
+export interface CSBlindedDenominationSignature {
+  cipher: DenomKeyType.ClauseSchnorr;
+}
+
+export type BlindedDenominationSignature =
+  | RsaBlindedDenominationSignature
+  | CSBlindedDenominationSignature;
+
+export const codecForBlindedDenominationSignature = () =>
+  buildCodecForUnion<BlindedDenominationSignature>()
+    .discriminateOn("cipher")
+    .alternative(1, codecForRsaBlindedDenominationSignature())
+    .build("BlindedDenominationSignature");
+
+export const codecForRsaBlindedDenominationSignature = () =>
+  buildCodecForObject<RsaBlindedDenominationSignature>()
+    .property("cipher", codecForConstNumber(1))
+    .property("blinded_rsa_signature", codecForString())
+    .build("RsaBlindedDenominationSignature");
+
 export class WithdrawResponse {
-  ev_sig: string;
+  ev_sig: BlindedDenominationSignature;
 }
 
 /**
@@ -792,7 +827,7 @@ export interface CoinDumpJson {
     /**
      * The coin's denomination's public key.
      */
-    denom_pub: string;
+    denom_pub: DenominationPubKey;
     /**
      * Hash of denom_pub.
      */
@@ -875,7 +910,7 @@ export interface ExchangeMeltResponse {
 }
 
 export interface ExchangeRevealItem {
-  ev_sig: string;
+  ev_sig: BlindedDenominationSignature;
 }
 
 export interface ExchangeRevealResponse {
@@ -994,6 +1029,30 @@ export interface BankWithdrawalOperationPostResponse {
   transfer_done: boolean;
 }
 
+export type DenominationPubKey = RsaDenominationPubKey | CsDenominationPubKey;
+
+export interface RsaDenominationPubKey {
+  cipher: 1;
+  rsa_public_key: string;
+  age_mask?: number;
+}
+
+export interface CsDenominationPubKey {
+  cipher: 2;
+}
+
+export const codecForDenominationPubKey = () =>
+  buildCodecForUnion<DenominationPubKey>()
+    .discriminateOn("cipher")
+    .alternative(1, codecForRsaDenominationPubKey())
+    .build("DenominationPubKey");
+
+export const codecForRsaDenominationPubKey = () =>
+  buildCodecForObject<RsaDenominationPubKey>()
+    .property("cipher", codecForConstNumber(1))
+    .property("rsa_public_key", codecForString())
+    .build("DenominationPubKey");
+
 export const codecForBankWithdrawalOperationPostResponse = (): 
Codec<BankWithdrawalOperationPostResponse> =>
   buildCodecForObject<BankWithdrawalOperationPostResponse>()
     .property("transfer_done", codecForBoolean())
@@ -1008,7 +1067,7 @@ export type CoinPublicKeyString = string;
 export const codecForDenomination = (): Codec<Denomination> =>
   buildCodecForObject<Denomination>()
     .property("value", codecForString())
-    .property("denom_pub", codecForString())
+    .property("denom_pub", codecForDenominationPubKey())
     .property("fee_withdraw", codecForString())
     .property("fee_deposit", codecForString())
     .property("fee_refresh", codecForString())
@@ -1242,7 +1301,7 @@ export const codecForRecoupConfirmation = (): 
Codec<RecoupConfirmation> =>
 
 export const codecForWithdrawResponse = (): Codec<WithdrawResponse> =>
   buildCodecForObject<WithdrawResponse>()
-    .property("ev_sig", codecForString())
+    .property("ev_sig", codecForBlindedDenominationSignature())
     .build("WithdrawResponse");
 
 export const codecForMerchantPayResponse = (): Codec<MerchantPayResponse> =>
@@ -1260,7 +1319,7 @@ export const codecForExchangeMeltResponse = (): 
Codec<ExchangeMeltResponse> =>
 
 export const codecForExchangeRevealItem = (): Codec<ExchangeRevealItem> =>
   buildCodecForObject<ExchangeRevealItem>()
-    .property("ev_sig", codecForString())
+    .property("ev_sig", codecForBlindedDenominationSignature())
     .build("ExchangeRevealItem");
 
 export const codecForExchangeRevealResponse = (): 
Codec<ExchangeRevealResponse> =>
diff --git a/packages/taler-util/src/walletTypes.ts 
b/packages/taler-util/src/walletTypes.ts
index 6e68ee08..879640e8 100644
--- a/packages/taler-util/src/walletTypes.ts
+++ b/packages/taler-util/src/walletTypes.ts
@@ -48,6 +48,8 @@ import {
   AmountString,
   codecForContractTerms,
   ContractTerms,
+  DenominationPubKey,
+  UnblindedSignature,
 } from "./talerTypes.js";
 import { OrderShortInfo, codecForOrderShortInfo } from 
"./transactionsTypes.js";
 import { BackupRecovery } from "./backupTypes.js";
@@ -454,7 +456,7 @@ export interface PlanchetCreationResult {
   coinPriv: string;
   reservePub: string;
   denomPubHash: string;
-  denomPub: string;
+  denomPub: DenominationPubKey;
   blindingKey: string;
   withdrawSig: string;
   coinEv: string;
@@ -467,7 +469,7 @@ export interface PlanchetCreationRequest {
   coinIndex: number;
   value: AmountJson;
   feeWithdraw: AmountJson;
-  denomPub: string;
+  denomPub: DenominationPubKey;
   reservePub: string;
   reservePriv: string;
 }
@@ -514,7 +516,7 @@ export interface DepositInfo {
   feeDeposit: AmountJson;
   wireInfoHash: string;
   denomPubHash: string;
-  denomSig: string;
+  denomSig: UnblindedSignature;
 }
 
 export interface ExchangesListRespose {
diff --git a/packages/taler-wallet-core/package.json 
b/packages/taler-wallet-core/package.json
index d8b344f2..3f20811f 100644
--- a/packages/taler-wallet-core/package.json
+++ b/packages/taler-wallet-core/package.json
@@ -58,7 +58,7 @@
     "rollup-plugin-sourcemaps": "^0.6.3",
     "source-map-resolve": "^0.6.0",
     "typedoc": "^0.20.16",
-    "typescript": "^4.1.3"
+    "typescript": "^4.4.4"
   },
   "dependencies": {
     "@gnu-taler/idb-bridge": "workspace:*",
diff --git a/packages/taler-wallet-core/src/crypto/cryptoTypes.ts 
b/packages/taler-wallet-core/src/crypto/cryptoTypes.ts
index 922fbbfa..7d616ecb 100644
--- a/packages/taler-wallet-core/src/crypto/cryptoTypes.ts
+++ b/packages/taler-wallet-core/src/crypto/cryptoTypes.ts
@@ -27,13 +27,13 @@
 /**
  * Imports.
  */
-import { AmountJson } from "@gnu-taler/taler-util";
+import { AmountJson, DenominationPubKey } from "@gnu-taler/taler-util";
 
 export interface RefreshNewDenomInfo {
   count: number;
   value: AmountJson;
   feeWithdraw: AmountJson;
-  denomPub: string;
+  denomPub: DenominationPubKey;
 }
 
 /**
@@ -117,7 +117,7 @@ export interface DerivedRefreshSession {
 
 export interface DeriveTipRequest {
   secretSeed: string;
-  denomPub: string;
+  denomPub: DenominationPubKey;
   planchetIndex: number;
 }
 
diff --git 
a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts 
b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts
index 169d1d9b..389b98b2 100644
--- a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts
+++ b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts
@@ -35,7 +35,9 @@ import {
 import {
   buildSigPS,
   CoinDepositPermission,
+  DenomKeyType,
   FreshCoin,
+  hashDenomPub,
   RecoupRequest,
   RefreshPlanchetInfo,
   TalerSignaturePurpose,
@@ -152,17 +154,20 @@ export class CryptoImplementation {
    * reserve.
    */
   createPlanchet(req: PlanchetCreationRequest): PlanchetCreationResult {
+    if (req.denomPub.cipher !== 1) {
+      throw Error("unsupported cipher");
+    }
     const reservePub = decodeCrock(req.reservePub);
     const reservePriv = decodeCrock(req.reservePriv);
-    const denomPub = decodeCrock(req.denomPub);
+    const denomPubRsa = decodeCrock(req.denomPub.rsa_public_key);
     const derivedPlanchet = setupWithdrawPlanchet(
       decodeCrock(req.secretSeed),
       req.coinIndex,
     );
     const coinPubHash = hash(derivedPlanchet.coinPub);
-    const ev = rsaBlind(coinPubHash, derivedPlanchet.bks, denomPub);
+    const ev = rsaBlind(coinPubHash, derivedPlanchet.bks, denomPubRsa);
     const amountWithFee = Amounts.add(req.value, req.feeWithdraw).amount;
-    const denomPubHash = hash(denomPub);
+    const denomPubHash = hashDenomPub(req.denomPub);
     const evHash = hash(ev);
 
     const withdrawRequest = buildSigPS(
@@ -182,7 +187,10 @@ export class CryptoImplementation {
       coinPriv: encodeCrock(derivedPlanchet.coinPriv),
       coinPub: encodeCrock(derivedPlanchet.coinPub),
       coinValue: req.value,
-      denomPub: encodeCrock(denomPub),
+      denomPub: {
+        cipher: 1,
+        rsa_public_key: encodeCrock(denomPubRsa),
+      },
       denomPubHash: encodeCrock(denomPubHash),
       reservePub: encodeCrock(reservePub),
       withdrawSig: encodeCrock(sig),
@@ -195,8 +203,11 @@ export class CryptoImplementation {
    * Create a planchet used for tipping, including the private keys.
    */
   createTipPlanchet(req: DeriveTipRequest): DerivedTipPlanchet {
+    if (req.denomPub.cipher !== 1) {
+      throw Error("unsupported cipher");
+    }
     const fc = setupTipPlanchet(decodeCrock(req.secretSeed), 
req.planchetIndex);
-    const denomPub = decodeCrock(req.denomPub);
+    const denomPub = decodeCrock(req.denomPub.rsa_public_key);
     const coinPubHash = hash(fc.coinPub);
     const ev = rsaBlind(coinPubHash, fc.bks, denomPub);
 
@@ -319,14 +330,9 @@ export class CryptoImplementation {
     sig: string,
     masterPub: string,
   ): boolean {
-    const h = kdf(
-      64,
-      stringToBytes("exchange-wire-signature"),
-      stringToBytes(paytoUri + "\0"),
-      new Uint8Array(0),
-    );
+    const paytoHash = hash(stringToBytes(paytoUri + "\0"));
     const p = buildSigPS(TalerSignaturePurpose.MASTER_WIRE_DETAILS)
-      .put(h)
+      .put(paytoHash)
       .build();
     return eddsaVerify(p, decodeCrock(sig), decodeCrock(masterPub));
   }
@@ -385,8 +391,11 @@ export class CryptoImplementation {
    * and deposit permissions for each given coin.
    */
   signDepositPermission(depositInfo: DepositInfo): CoinDepositPermission {
+    // FIXME: put extensions here if used
+    const hExt = new Uint8Array(64);
     const d = buildSigPS(TalerSignaturePurpose.WALLET_COIN_DEPOSIT)
       .put(decodeCrock(depositInfo.contractTermsHash))
+      .put(hExt)
       .put(decodeCrock(depositInfo.wireInfoHash))
       .put(decodeCrock(depositInfo.denomPubHash))
       .put(timestampRoundedToBuffer(depositInfo.timestamp))
@@ -394,7 +403,6 @@ export class CryptoImplementation {
       .put(amountToBuffer(depositInfo.spendAmount))
       .put(amountToBuffer(depositInfo.feeDeposit))
       .put(decodeCrock(depositInfo.merchantPub))
-      .put(decodeCrock(depositInfo.coinPub))
       .build();
     const coinSig = eddsaSign(d, decodeCrock(depositInfo.coinPriv));
 
@@ -404,7 +412,10 @@ export class CryptoImplementation {
       contribution: Amounts.stringify(depositInfo.spendAmount),
       h_denom: depositInfo.denomPubHash,
       exchange_url: depositInfo.exchangeBaseUrl,
-      ub_sig: depositInfo.denomSig,
+      ub_sig: {
+        cipher: DenomKeyType.Rsa,
+        rsa_signature: depositInfo.denomSig.rsa_signature,
+      },
     };
     return s;
   }
@@ -455,8 +466,10 @@ export class CryptoImplementation {
 
     for (const denomSel of newCoinDenoms) {
       for (let i = 0; i < denomSel.count; i++) {
-        const r = decodeCrock(denomSel.denomPub);
-        sessionHc.update(r);
+        if (denomSel.denomPub.cipher !== 1) {
+          throw Error("unsupported cipher");
+        }
+        sessionHc.update(hashDenomPub(denomSel.denomPub));
       }
     }
 
@@ -495,7 +508,10 @@ export class CryptoImplementation {
             blindingFactor = fresh.bks;
           }
           const pubHash = hash(coinPub);
-          const denomPub = decodeCrock(denomSel.denomPub);
+          if (denomSel.denomPub.cipher !== 1) {
+            throw Error("unsupported cipher");
+          }
+          const denomPub = decodeCrock(denomSel.denomPub.rsa_public_key);
           const ev = rsaBlind(pubHash, blindingFactor, denomPub);
           const planchet: RefreshPlanchetInfo = {
             blindingKey: encodeCrock(blindingFactor),
diff --git a/packages/taler-wallet-core/src/db.ts 
b/packages/taler-wallet-core/src/db.ts
index 902f749c..483cb16c 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -28,6 +28,7 @@ import {
   Auditor,
   CoinDepositPermission,
   ContractTerms,
+  DenominationPubKey,
   Duration,
   ExchangeSignKeyJson,
   InternationalizedString,
@@ -36,6 +37,7 @@ import {
   RefreshReason,
   TalerErrorDetails,
   Timestamp,
+  UnblindedSignature,
 } from "@gnu-taler/taler-util";
 import { RetryInfo } from "./util/retries.js";
 import { PayCoinSelection } from "./util/coinSelection.js";
@@ -310,7 +312,7 @@ export interface DenominationRecord {
   /**
    * The denomination public key.
    */
-  denomPub: string;
+  denomPub: DenominationPubKey;
 
   /**
    * Hash of the denomination public key.
@@ -452,7 +454,7 @@ export interface ExchangeDetailsRecord {
   /**
    * content-type of the last downloaded termsOfServiceText.
    */
-   termsOfServiceContentType: string | undefined;
+  termsOfServiceContentType: string | undefined;
 
   /**
    * ETag for last terms of service download.
@@ -578,7 +580,8 @@ export interface PlanchetRecord {
 
   denomPubHash: string;
 
-  denomPub: string;
+  // FIXME: maybe too redundant?
+  denomPub: DenominationPubKey;
 
   blindingKey: string;
 
@@ -668,7 +671,7 @@ export interface CoinRecord {
   /**
    * Key used by the exchange used to sign the coin.
    */
-  denomPub: string;
+  denomPub: DenominationPubKey;
 
   /**
    * Hash of the public key that signs the coin.
@@ -678,7 +681,7 @@ export interface CoinRecord {
   /**
    * Unblinded signature by the exchange.
    */
-  denomSig: string;
+  denomSig: UnblindedSignature;
 
   /**
    * Amount that's left on the coin.
diff --git a/packages/taler-wallet-core/src/errors.ts 
b/packages/taler-wallet-core/src/errors.ts
index d788405f..3109644a 100644
--- a/packages/taler-wallet-core/src/errors.ts
+++ b/packages/taler-wallet-core/src/errors.ts
@@ -93,7 +93,7 @@ export async function guardOperationException<T>(
 ): Promise<T> {
   try {
     return await op();
-  } catch (e) {
+  } catch (e: any) {
     if (e instanceof OperationFailedAndReportedError) {
       throw e;
     }
diff --git a/packages/taler-wallet-core/src/operations/backup/import.ts 
b/packages/taler-wallet-core/src/operations/backup/import.ts
index 7623ab18..e8e1de0b 100644
--- a/packages/taler-wallet-core/src/operations/backup/import.ts
+++ b/packages/taler-wallet-core/src/operations/backup/import.ts
@@ -202,7 +202,7 @@ export interface CompletedCoin {
  * as the async crypto worker communication would auto-close the database 
transaction.
  */
 export interface BackupCryptoPrecomputedData {
-  denomPubToHash: Record<string, string>;
+  rsaDenomPubToHash: Record<string, string>;
   coinPrivToCompletedCoin: Record<string, CompletedCoin>;
   proposalNoncePrivToPub: { [priv: string]: string };
   proposalIdToContractTermsHash: { [proposalId: string]: string };
@@ -330,8 +330,13 @@ export async function importBackup(
         }
 
         for (const backupDenomination of backupExchangeDetails.denominations) {
+          if (backupDenomination.denom_pub.cipher !== 1) {
+            throw Error("unsupported cipher");
+          }
           const denomPubHash =
-            cryptoComp.denomPubToHash[backupDenomination.denom_pub];
+            cryptoComp.rsaDenomPubToHash[
+              backupDenomination.denom_pub.rsa_public_key
+            ];
           checkLogicInvariant(!!denomPubHash);
           const existingDenom = await tx.denominations.get([
             backupExchangeDetails.base_url,
diff --git a/packages/taler-wallet-core/src/operations/backup/index.ts 
b/packages/taler-wallet-core/src/operations/backup/index.ts
index 3f4c0227..9027625c 100644
--- a/packages/taler-wallet-core/src/operations/backup/index.ts
+++ b/packages/taler-wallet-core/src/operations/backup/index.ts
@@ -40,6 +40,7 @@ import {
   ConfirmPayResultType,
   durationFromSpec,
   getTimestampNow,
+  hashDenomPub,
   HttpStatusCode,
   j2s,
   Logger,
@@ -57,10 +58,7 @@ import {
 import { gunzipSync, gzipSync } from "fflate";
 import { InternalWalletState } from "../../common.js";
 import { kdf } from "@gnu-taler/taler-util";
-import {
-  secretbox,
-  secretbox_open,
-} from "@gnu-taler/taler-util";
+import { secretbox, secretbox_open } from "@gnu-taler/taler-util";
 import {
   bytesToString,
   decodeCrock,
@@ -162,13 +160,16 @@ async function computeBackupCryptoData(
 ): Promise<BackupCryptoPrecomputedData> {
   const cryptoData: BackupCryptoPrecomputedData = {
     coinPrivToCompletedCoin: {},
-    denomPubToHash: {},
+    rsaDenomPubToHash: {},
     proposalIdToContractTermsHash: {},
     proposalNoncePrivToPub: {},
     reservePrivToPub: {},
   };
   for (const backupExchangeDetails of backupContent.exchange_details) {
     for (const backupDenom of backupExchangeDetails.denominations) {
+      if (backupDenom.denom_pub.cipher !== 1) {
+        throw Error("unsupported cipher");
+      }
       for (const backupCoin of backupDenom.coins) {
         const coinPub = encodeCrock(
           eddsaGetPublic(decodeCrock(backupCoin.coin_priv)),
@@ -176,16 +177,16 @@ async function computeBackupCryptoData(
         const blindedCoin = rsaBlind(
           hash(decodeCrock(backupCoin.coin_priv)),
           decodeCrock(backupCoin.blinding_key),
-          decodeCrock(backupDenom.denom_pub),
+          decodeCrock(backupDenom.denom_pub.rsa_public_key),
         );
         cryptoData.coinPrivToCompletedCoin[backupCoin.coin_priv] = {
           coinEvHash: encodeCrock(hash(blindedCoin)),
           coinPub,
         };
       }
-      cryptoData.denomPubToHash[backupDenom.denom_pub] = encodeCrock(
-        hash(decodeCrock(backupDenom.denom_pub)),
-      );
+      cryptoData.rsaDenomPubToHash[
+        backupDenom.denom_pub.rsa_public_key
+      ] = encodeCrock(hashDenomPub(backupDenom.denom_pub));
     }
     for (const backupReserve of backupExchangeDetails.reserves) {
       cryptoData.reservePrivToPub[backupReserve.reserve_priv] = encodeCrock(
diff --git a/packages/taler-wallet-core/src/operations/deposits.ts 
b/packages/taler-wallet-core/src/operations/deposits.ts
index 74024205..8fe3702f 100644
--- a/packages/taler-wallet-core/src/operations/deposits.ts
+++ b/packages/taler-wallet-core/src/operations/deposits.ts
@@ -25,6 +25,7 @@ import {
   ContractTerms,
   CreateDepositGroupRequest,
   CreateDepositGroupResponse,
+  decodeCrock,
   durationFromSpec,
   getTimestampNow,
   Logger,
@@ -106,7 +107,7 @@ function hashWire(paytoUri: string, salt: string): string {
   const r = kdf(
     64,
     stringToBytes(paytoUri + "\0"),
-    stringToBytes(salt + "\0"),
+    decodeCrock(salt),
     stringToBytes("merchant-wire-signature"),
   );
   return encodeCrock(r);
@@ -213,8 +214,8 @@ async function processDepositGroupImpl(
     const url = new URL(`coins/${perm.coin_pub}/deposit`, perm.exchange_url);
     const httpResp = await ws.http.postJson(url.href, {
       contribution: Amounts.stringify(perm.contribution),
-      wire: depositGroup.wire,
-      h_wire: depositGroup.contractTermsRaw.h_wire,
+      merchant_payto_uri: depositGroup.wire.payto_uri,
+      wire_salt: depositGroup.wire.salt,
       h_contract_terms: depositGroup.contractTermsHash,
       ub_sig: perm.ub_sig,
       timestamp: depositGroup.contractTermsRaw.timestamp,
@@ -355,7 +356,7 @@ export async function createDepositGroup(
   const timestampRound = timestampTruncateToSecond(timestamp);
   const noncePair = await ws.cryptoApi.createEddsaKeypair();
   const merchantPair = await ws.cryptoApi.createEddsaKeypair();
-  const wireSalt = encodeCrock(getRandomBytes(64));
+  const wireSalt = encodeCrock(getRandomBytes(16));
   const wireHash = hashWire(req.depositPaytoUri, wireSalt);
   const contractTerms: ContractTerms = {
     auditors: [],
diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts 
b/packages/taler-wallet-core/src/operations/exchanges.ts
index 629957ef..c170c546 100644
--- a/packages/taler-wallet-core/src/operations/exchanges.ts
+++ b/packages/taler-wallet-core/src/operations/exchanges.ts
@@ -39,6 +39,7 @@ import {
   URL,
   TalerErrorDetails,
   Timestamp,
+  hashDenomPub,
 } from "@gnu-taler/taler-util";
 import { decodeCrock, encodeCrock, hash } from "@gnu-taler/taler-util";
 import { CryptoApi } from "../crypto/workers/cryptoApi.js";
@@ -78,7 +79,7 @@ function denominationRecordFromKeys(
   listIssueDate: Timestamp,
   denomIn: Denomination,
 ): DenominationRecord {
-  const denomPubHash = encodeCrock(hash(decodeCrock(denomIn.denom_pub)));
+  const denomPubHash = encodeCrock(hashDenomPub(denomIn.denom_pub));
   const d: DenominationRecord = {
     denomPub: denomIn.denom_pub,
     denomPubHash,
@@ -472,26 +473,29 @@ async function updateExchangeFromUrlImpl(
 
   let tosFound: ExchangeTosDownloadResult | undefined;
   //Remove this when exchange supports multiple content-type in accept header
-  if (acceptedFormat) for (const format of acceptedFormat) {
-    const resp = await downloadExchangeWithTermsOfService(
-      baseUrl,
-      ws.http,
-      timeout,
-      format
-    );
-    if (resp.tosContentType === format) {
-      tosFound = resp
-      break
+  if (acceptedFormat)
+    for (const format of acceptedFormat) {
+      const resp = await downloadExchangeWithTermsOfService(
+        baseUrl,
+        ws.http,
+        timeout,
+        format,
+      );
+      if (resp.tosContentType === format) {
+        tosFound = resp;
+        break;
+      }
     }
-  }
   // If none of the specified format was found try text/plain
-  const tosDownload = tosFound !== undefined ? tosFound :
-    await downloadExchangeWithTermsOfService(
-      baseUrl,
-      ws.http,
-      timeout,
-      "text/plain"
-    );
+  const tosDownload =
+    tosFound !== undefined
+      ? tosFound
+      : await downloadExchangeWithTermsOfService(
+          baseUrl,
+          ws.http,
+          timeout,
+          "text/plain",
+        );
 
   let recoupGroupId: string | undefined = undefined;
 
diff --git a/packages/taler-wallet-core/src/operations/refresh.ts 
b/packages/taler-wallet-core/src/operations/refresh.ts
index d727bd06..956e4d65 100644
--- a/packages/taler-wallet-core/src/operations/refresh.ts
+++ b/packages/taler-wallet-core/src/operations/refresh.ts
@@ -14,7 +14,12 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-import { encodeCrock, getRandomBytes, HttpStatusCode } from 
"@gnu-taler/taler-util";
+import {
+  DenomKeyType,
+  encodeCrock,
+  getRandomBytes,
+  HttpStatusCode,
+} from "@gnu-taler/taler-util";
 import {
   CoinRecord,
   CoinSourceType,
@@ -599,10 +604,17 @@ async function refreshReveal(
         continue;
       }
       const pc = derived.planchetsForGammas[norevealIndex][newCoinIndex];
-      const denomSig = await ws.cryptoApi.rsaUnblind(
-        reveal.ev_sigs[newCoinIndex].ev_sig,
+      if (denom.denomPub.cipher !== 1) {
+        throw Error("cipher unsupported");
+      }
+      const evSig = reveal.ev_sigs[newCoinIndex].ev_sig;
+      if (evSig.cipher !== DenomKeyType.Rsa) {
+        throw Error("unsupported cipher");
+      }
+      const denomSigRsa = await ws.cryptoApi.rsaUnblind(
+        evSig.blinded_rsa_signature,
         pc.blindingKey,
-        denom.denomPub,
+        denom.denomPub.rsa_public_key,
       );
       const coin: CoinRecord = {
         blindingKey: pc.blindingKey,
@@ -611,7 +623,10 @@ async function refreshReveal(
         currentAmount: denom.value,
         denomPub: denom.denomPub,
         denomPubHash: denom.denomPubHash,
-        denomSig,
+        denomSig: {
+          cipher: DenomKeyType.Rsa,
+          rsa_signature: denomSigRsa,
+        },
         exchangeBaseUrl: oldCoin.exchangeBaseUrl,
         status: CoinStatus.Fresh,
         coinSource: {
diff --git a/packages/taler-wallet-core/src/operations/tip.ts 
b/packages/taler-wallet-core/src/operations/tip.ts
index a90e5270..07ce00d2 100644
--- a/packages/taler-wallet-core/src/operations/tip.ts
+++ b/packages/taler-wallet-core/src/operations/tip.ts
@@ -30,6 +30,7 @@ import {
   codecForTipResponse,
   Logger,
   URL,
+  DenomKeyType,
 } from "@gnu-taler/taler-util";
 import { DerivedTipPlanchet } from "../crypto/cryptoTypes.js";
 import {
@@ -322,16 +323,20 @@ async function processTipImpl(
     const planchet = planchets[i];
     checkLogicInvariant(!!planchet);
 
-    const denomSig = await ws.cryptoApi.rsaUnblind(
+    if (denom.denomPub.cipher !== 1) {
+      throw Error("unsupported cipher");
+    }
+
+    const denomSigRsa = await ws.cryptoApi.rsaUnblind(
       blindedSig,
       planchet.blindingKey,
-      denom.denomPub,
+      denom.denomPub.rsa_public_key,
     );
 
     const isValid = await ws.cryptoApi.rsaVerify(
       planchet.coinPub,
-      denomSig,
-      denom.denomPub,
+      denomSigRsa,
+      denom.denomPub.rsa_public_key,
     );
 
     if (!isValid) {
@@ -364,7 +369,7 @@ async function processTipImpl(
       currentAmount: denom.value,
       denomPub: denom.denomPub,
       denomPubHash: denom.denomPubHash,
-      denomSig: denomSig,
+      denomSig: { cipher: DenomKeyType.Rsa, rsa_signature: denomSigRsa },
       exchangeBaseUrl: tipRecord.exchangeBaseUrl,
       status: CoinStatus.Fresh,
       suspended: false,
diff --git a/packages/taler-wallet-core/src/operations/withdraw.test.ts 
b/packages/taler-wallet-core/src/operations/withdraw.test.ts
index b4f0d35e..17985296 100644
--- a/packages/taler-wallet-core/src/operations/withdraw.test.ts
+++ b/packages/taler-wallet-core/src/operations/withdraw.test.ts
@@ -28,8 +28,11 @@ test("withdrawal selection bug repro", (t) => {
 
   const denoms: DenominationRecord[] = [
     {
-      denomPub:
-        
"040000XT67C8KBD6B75TTQ3SK8FWXMNQW4372T3BDDGPAMB9RFCA03638W8T3F71WFEFK9NP32VKYVNFXPYRWQ1N1HDKV5J0DFEKHBPJCYSWCBJDRNWD7G8BN8PT97FA9AMV75MYEK4X54D1HGJ207JSVJBGFCATSPNTEYNHEQF1F220W00TBZR1HNPDQFD56FG0DJQ9KGHM8EC33H6AY9YN9CNX5R3Z4TZ4Q23W47SBHB13H6W74FQJG1F50X38VRSC4SR8RWBAFB7S4K8D2H4NMRFSQT892A3T0BTBW7HM5C0H2CK6FRKG31F7W9WP1S29013K5CXYE55CT8TH6N8J9B780R42Y5S3ZB6J6E9H76XBPSGH4TGYSR2VZRB98J417KCQMZKX1BB67E7W5KVE37TC9SJ904002",
+      denomPub: {
+        cipher: 1,
+        rsa_public_key:
+          
"040000XT67C8KBD6B75TTQ3SK8FWXMNQW4372T3BDDGPAMB9RFCA03638W8T3F71WFEFK9NP32VKYVNFXPYRWQ1N1HDKV5J0DFEKHBPJCYSWCBJDRNWD7G8BN8PT97FA9AMV75MYEK4X54D1HGJ207JSVJBGFCATSPNTEYNHEQF1F220W00TBZR1HNPDQFD56FG0DJQ9KGHM8EC33H6AY9YN9CNX5R3Z4TZ4Q23W47SBHB13H6W74FQJG1F50X38VRSC4SR8RWBAFB7S4K8D2H4NMRFSQT892A3T0BTBW7HM5C0H2CK6FRKG31F7W9WP1S29013K5CXYE55CT8TH6N8J9B780R42Y5S3ZB6J6E9H76XBPSGH4TGYSR2VZRB98J417KCQMZKX1BB67E7W5KVE37TC9SJ904002",
+      },
       denomPubHash:
         
"Q21FQSSG4FXNT96Z14CHXM8N1RZAG9GPHAV8PRWS0PZAAVWH7PBW6R97M2CH19KKP65NNSWXY7B6S53PT3CBM342E357ZXDDJ8RDVW8",
       exchangeBaseUrl: "https://exchange.demo.taler.net/";,
@@ -79,8 +82,12 @@ test("withdrawal selection bug repro", (t) => {
       listIssueDate: { t_ms: 0 },
     },
     {
-      denomPub:
-        
"040000Y63CF78QFPKRY77BRK9P557Q1GQWX3NCZ3HSYSK0Z7TT0KGRA7N4SKBKEHSTVHX1Z9DNXMJR4EXSY1TXCKV0GJ3T3YYC6Z0JNMJFVYQAV4FX5J90NZH1N33MZTV8HS9SMNAA9S6K73G4P99GYBB01B0P6M1KXZ5JRDR7VWBR3MEJHHGJ6QBMCJR3NWJRE3WJW9PRY8QPQ2S7KFWTWRESH2DBXCXWBD2SRN6P9YX8GRAEMFEGXC9V5GVJTEMH6ZDGNXFPWZE3JVJ2Q4N9GDYKBCHZCJ7M7M2RJ9ZV4Y64NAN9BT6XDC68215GKKRHTW1BBF1MYY6AR3JCTT9HYAM923RMVQR3TAEB7SDX8J76XRZWYH3AGJCZAQGMN5C8SSH9AHQ9RNQJQ15CN45R37X4YNFJV904002",
+      denomPub: {
+        cipher: 1,
+        rsa_public_key:
+          
"040000Y63CF78QFPKRY77BRK9P557Q1GQWX3NCZ3HSYSK0Z7TT0KGRA7N4SKBKEHSTVHX1Z9DNXMJR4EXSY1TXCKV0GJ3T3YYC6Z0JNMJFVYQAV4FX5J90NZH1N33MZTV8HS9SMNAA9S6K73G4P99GYBB01B0P6M1KXZ5JRDR7VWBR3MEJHHGJ6QBMCJR3NWJRE3WJW9PRY8QPQ2S7KFWTWRESH2DBXCXWBD2SRN6P9YX8GRAEMFEGXC9V5GVJTEMH6ZDGNXFPWZE3JVJ2Q4N9GDYKBCHZCJ7M7M2RJ9ZV4Y64NAN9BT6XDC68215GKKRHTW1BBF1MYY6AR3JCTT9HYAM923RMVQR3TAEB7SDX8J76XRZWYH3AGJCZAQGMN5C8SSH9AHQ9RNQJQ15CN45R37X4YNFJV904002",
+      },
+
       denomPubHash:
         
"447WA23SCBATMABHA0793F92MYTBYVPYMMQHCPKMKVY5P7RZRFMQ6VRW0Y8HRA7177GTBT0TBT08R21DZD129AJ995H9G09XBFE55G8",
       exchangeBaseUrl: "https://exchange.demo.taler.net/";,
@@ -130,8 +137,11 @@ test("withdrawal selection bug repro", (t) => {
       listIssueDate: { t_ms: 0 },
     },
     {
-      denomPub:
-        
"040000YDESWC2B962DA4WK356SC50MA3N9KV0ZSGY3RC48JCTY258W909C7EEMT5BTC5KZ5T4CERCZ141P9QF87EK2BD1XEEM5GB07MB3H19WE4CQGAS8X84JBWN83PQGQXVMWE5HFA992KMGHC566GT9ZS2QPHZB6X89C4A80Z663PYAAPXP728VHAKATGNNBQ01ZZ2XD1CH9Y38YZBSPJ4K7GB2J76GBCYAVD9ENHDVWXJAXYRPBX4KSS5TXRR3K5NEN9ZV3AJD2V65K7ABRZDF5D5V1FJZZMNJ5XZ4FEREEKEBV9TDFPGJTKDEHEC60K3DN24DAATRESDJ1ZYYSYSRCAT4BT2B62ARGVMJTT5N2R126DRW9TGRWCW0ZAF2N2WET1H4NJEW77X0QT46Z5R3MZ0XPHD04002",
+      denomPub: {
+        cipher: 1,
+        rsa_public_key:
+          
"040000YDESWC2B962DA4WK356SC50MA3N9KV0ZSGY3RC48JCTY258W909C7EEMT5BTC5KZ5T4CERCZ141P9QF87EK2BD1XEEM5GB07MB3H19WE4CQGAS8X84JBWN83PQGQXVMWE5HFA992KMGHC566GT9ZS2QPHZB6X89C4A80Z663PYAAPXP728VHAKATGNNBQ01ZZ2XD1CH9Y38YZBSPJ4K7GB2J76GBCYAVD9ENHDVWXJAXYRPBX4KSS5TXRR3K5NEN9ZV3AJD2V65K7ABRZDF5D5V1FJZZMNJ5XZ4FEREEKEBV9TDFPGJTKDEHEC60K3DN24DAATRESDJ1ZYYSYSRCAT4BT2B62ARGVMJTT5N2R126DRW9TGRWCW0ZAF2N2WET1H4NJEW77X0QT46Z5R3MZ0XPHD04002",
+      },
       denomPubHash:
         
"JS61DTKAFM0BX8Q4XV3ZSKB921SM8QK745Z2AFXTKFMBHHFNBD8TQ5ETJHFNDGBGX22FFN2A2ERNYG1SGSDQWNQHQQ2B14DBVJYJG8R",
       exchangeBaseUrl: "https://exchange.demo.taler.net/";,
@@ -181,8 +191,12 @@ test("withdrawal selection bug repro", (t) => {
       listIssueDate: { t_ms: 0 },
     },
     {
-      denomPub:
-        
"040000YG3T1ADB8DVA6BD3EPV6ZHSHTDW35DEN4VH1AE6CSB7P1PSDTNTJG866PHF6QB1CCWYCVRGA0FVBJ9Q0G7KV7AD9010GDYBQH0NNPHW744MTNXVXWBGGGRGQGYK4DTYN1DSWQ1FZNDSZZPB5BEKG2PDJ93NX2JTN06Y8QMS2G734Z9XHC10EENBG2KVB7EJ3CM8PV1T32RC7AY62F3496E8D8KRHJQQTT67DSGMNKK86QXVDTYW677FG27DP20E8XY3M6FQD53NDJ1WWES91401MV1A3VXVPGC76GZVDD62W3WTJ1YMKHTTA3MRXX3VEAAH3XTKDN1ER7X6CZPMYTF8VK735VP2B2TZGTF28TTW4FZS32SBS64APCDF6SZQ427N5538TJC7SRE71YSP5ET8GS904002",
+      denomPub: {
+        cipher: 1,
+        rsa_public_key:
+          
"040000YG3T1ADB8DVA6BD3EPV6ZHSHTDW35DEN4VH1AE6CSB7P1PSDTNTJG866PHF6QB1CCWYCVRGA0FVBJ9Q0G7KV7AD9010GDYBQH0NNPHW744MTNXVXWBGGGRGQGYK4DTYN1DSWQ1FZNDSZZPB5BEKG2PDJ93NX2JTN06Y8QMS2G734Z9XHC10EENBG2KVB7EJ3CM8PV1T32RC7AY62F3496E8D8KRHJQQTT67DSGMNKK86QXVDTYW677FG27DP20E8XY3M6FQD53NDJ1WWES91401MV1A3VXVPGC76GZVDD62W3WTJ1YMKHTTA3MRXX3VEAAH3XTKDN1ER7X6CZPMYTF8VK735VP2B2TZGTF28TTW4FZS32SBS64APCDF6SZQ427N5538TJC7SRE71YSP5ET8GS904002",
+      },
+
       denomPubHash:
         
"8T51NEY81VMPQ180EQ5WR0YH7GMNNT90W55Q0514KZM18AZT71FHJGJHQXGK0WTA7ACN1X2SD0S53XPBQ1A9KH960R48VCVVM6E3TH8",
       exchangeBaseUrl: "https://exchange.demo.taler.net/";,
@@ -232,8 +246,11 @@ test("withdrawal selection bug repro", (t) => {
       listIssueDate: { t_ms: 0 },
     },
     {
-      denomPub:
-        
"040000ZC0G60E9QQ5PD81TSDWD9GV5Y6P8Z05NSPA696DP07NGQQVSRQXBA76Q6PRB0YFX295RG4MTQJXAZZ860ET307HSC2X37XAVGQXRVB8Q4F1V7NP5ZEVKTX75DZK1QRAVHEZGQYKSSH6DBCJNQF6V9WNQF3GEYVA4KCBHA7JF772KHXM9642C28Z0AS4XXXV2PABAN5C8CHYD5H7JDFNK3920W5Q69X0BS84XZ4RE2PW6HM1WZ6KGZ3MKWWWCPKQ1FSFABRBWKAB09PF563BEBXKY6M38QETPH5EDWGANHD0SC3QV0WXYVB7BNHNNQ0J5BNV56K563SYHM4E5ND260YRJSYA1GN5YSW2B1J5T1A1EBNYF2DN6JNJKWXWEQ42G5YS17ZSZ5EWDRA9QKV8EGTCNAD04002",
+      denomPub: {
+        cipher: 1,
+        rsa_public_key:
+          
"040000ZC0G60E9QQ5PD81TSDWD9GV5Y6P8Z05NSPA696DP07NGQQVSRQXBA76Q6PRB0YFX295RG4MTQJXAZZ860ET307HSC2X37XAVGQXRVB8Q4F1V7NP5ZEVKTX75DZK1QRAVHEZGQYKSSH6DBCJNQF6V9WNQF3GEYVA4KCBHA7JF772KHXM9642C28Z0AS4XXXV2PABAN5C8CHYD5H7JDFNK3920W5Q69X0BS84XZ4RE2PW6HM1WZ6KGZ3MKWWWCPKQ1FSFABRBWKAB09PF563BEBXKY6M38QETPH5EDWGANHD0SC3QV0WXYVB7BNHNNQ0J5BNV56K563SYHM4E5ND260YRJSYA1GN5YSW2B1J5T1A1EBNYF2DN6JNJKWXWEQ42G5YS17ZSZ5EWDRA9QKV8EGTCNAD04002",
+      },
       denomPubHash:
         
"A41HW0Q2H9PCNMEWW0C0N45QAYVXZ8SBVRRAHE4W6X24SV1TH38ANTWDT80JXEBW9Z8PVPGT9GFV2EYZWJ5JW5W1N34NFNKHQSZ1PFR",
       exchangeBaseUrl: "https://exchange.demo.taler.net/";,
@@ -283,8 +300,11 @@ test("withdrawal selection bug repro", (t) => {
       listIssueDate: { t_ms: 0 },
     },
     {
-      denomPub:
-        
"040000ZSK2PMVY6E3NBQ52KXMW029M60F4BWYTDS0FZSD0PE53CNZ9H6TM3GQK1WRTEKQ5GRWJ1J9DY6Y42SP47QVT1XD1G0W05SQ5F3F7P5KSWR0FJBJ9NZBXQEVN8Q4JRC94X3JJ3XV3KBYTZ2HTDFV28C3H2SRR0XGNZB4FY85NDZF1G4AEYJJ9QB3C0V8H70YB8RV3FKTNH7XS4K4HFNZHJ5H9VMX5SM9Z2DX37HA5WFH0E2MJBVVF2BWWA5M0HPPSB365RAE2AMD42Q65A96WD80X27SB2ZNQZ8WX0K13FWF85GZ6YNYAJGE1KGN06JDEKE9QD68Z651D7XE8V6664TVVC8M68S7WD0DSXMJQKQ0BNJXNDE29Q7MRX6DA3RW0PZ44B3TKRK0294FPVZTNSTA6XF04002",
+      denomPub: {
+        cipher: 1,
+        rsa_public_key:
+          
"040000ZSK2PMVY6E3NBQ52KXMW029M60F4BWYTDS0FZSD0PE53CNZ9H6TM3GQK1WRTEKQ5GRWJ1J9DY6Y42SP47QVT1XD1G0W05SQ5F3F7P5KSWR0FJBJ9NZBXQEVN8Q4JRC94X3JJ3XV3KBYTZ2HTDFV28C3H2SRR0XGNZB4FY85NDZF1G4AEYJJ9QB3C0V8H70YB8RV3FKTNH7XS4K4HFNZHJ5H9VMX5SM9Z2DX37HA5WFH0E2MJBVVF2BWWA5M0HPPSB365RAE2AMD42Q65A96WD80X27SB2ZNQZ8WX0K13FWF85GZ6YNYAJGE1KGN06JDEKE9QD68Z651D7XE8V6664TVVC8M68S7WD0DSXMJQKQ0BNJXNDE29Q7MRX6DA3RW0PZ44B3TKRK0294FPVZTNSTA6XF04002",
+      },
       denomPubHash:
         
"F5NGBX33DTV4595XZZVK0S2MA1VMXFEJQERE5EBP5DS4QQ9EFRANN7YHWC1TKSHT2K6CQWDBRES8D3DWR0KZF5RET40B4AZXZ0RW1ZG",
       exchangeBaseUrl: "https://exchange.demo.taler.net/";,
diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts 
b/packages/taler-wallet-core/src/operations/withdraw.ts
index 620ad88b..57bd49d2 100644
--- a/packages/taler-wallet-core/src/operations/withdraw.ts
+++ b/packages/taler-wallet-core/src/operations/withdraw.ts
@@ -41,6 +41,7 @@ import {
   URL,
   WithdrawUriInfoResponse,
   VersionMatchResult,
+  DenomKeyType,
 } from "@gnu-taler/taler-util";
 import {
   CoinRecord,
@@ -495,7 +496,7 @@ async function processPlanchetExchangeRequest(
       ]);
 
       if (!denom) {
-        console.error("db inconsistent: denom for planchet not found");
+        logger.error("db inconsistent: denom for planchet not found");
         return;
       }
 
@@ -589,16 +590,26 @@ async function processPlanchetVerifyAndStoreCoin(
 
   const { planchet, exchangeBaseUrl } = d;
 
-  const denomSig = await ws.cryptoApi.rsaUnblind(
-    resp.ev_sig,
+  const planchetDenomPub = planchet.denomPub;
+  if (planchetDenomPub.cipher !== DenomKeyType.Rsa) {
+    throw Error("cipher not supported");
+  }
+
+  const evSig = resp.ev_sig;
+  if (evSig.cipher !== DenomKeyType.Rsa) {
+    throw Error("unsupported cipher");
+  }
+
+  const denomSigRsa = await ws.cryptoApi.rsaUnblind(
+    evSig.blinded_rsa_signature,
     planchet.blindingKey,
-    planchet.denomPub,
+    planchetDenomPub.rsa_public_key,
   );
 
   const isValid = await ws.cryptoApi.rsaVerify(
     planchet.coinPub,
-    denomSig,
-    planchet.denomPub,
+    denomSigRsa,
+    planchetDenomPub.rsa_public_key,
   );
 
   if (!isValid) {
@@ -629,7 +640,10 @@ async function processPlanchetVerifyAndStoreCoin(
     currentAmount: planchet.coinValue,
     denomPub: planchet.denomPub,
     denomPubHash: planchet.denomPubHash,
-    denomSig,
+    denomSig: {
+      cipher: DenomKeyType.Rsa,
+      rsa_signature: denomSigRsa,
+    },
     coinEvHash: planchet.coinEvHash,
     exchangeBaseUrl: exchangeBaseUrl,
     status: CoinStatus.Fresh,
@@ -728,7 +742,9 @@ export async function updateWithdrawalDenoms(
       batchIdx++, current++
     ) {
       const denom = denominations[current];
-      if (denom.verificationStatus === 
DenominationVerificationStatus.Unverified) {
+      if (
+        denom.verificationStatus === DenominationVerificationStatus.Unverified
+      ) {
         logger.trace(
           `Validating denomination (${current + 1}/${
             denominations.length
@@ -745,7 +761,8 @@ export async function updateWithdrawalDenoms(
           );
           denom.verificationStatus = 
DenominationVerificationStatus.VerifiedBad;
         } else {
-          denom.verificationStatus = 
DenominationVerificationStatus.VerifiedGood;
+          denom.verificationStatus =
+            DenominationVerificationStatus.VerifiedGood;
         }
         updatedDenominations.push(denom);
       }
diff --git a/packages/taler-wallet-core/src/util/coinSelection.test.ts 
b/packages/taler-wallet-core/src/util/coinSelection.test.ts
index ed48b8dd..b4dc2a18 100644
--- a/packages/taler-wallet-core/src/util/coinSelection.test.ts
+++ b/packages/taler-wallet-core/src/util/coinSelection.test.ts
@@ -33,7 +33,10 @@ function fakeAci(current: string, feeDeposit: string): 
AvailableCoinInfo {
   return {
     availableAmount: a(current),
     coinPub: "foobar",
-    denomPub: "foobar",
+    denomPub: {
+      cipher: 1,
+      rsa_public_key: "foobar",
+    },
     feeDeposit: a(feeDeposit),
     exchangeBaseUrl: "https://example.com/";,
   };
diff --git a/packages/taler-wallet-core/src/util/coinSelection.ts 
b/packages/taler-wallet-core/src/util/coinSelection.ts
index 500cee5d..ba26c98f 100644
--- a/packages/taler-wallet-core/src/util/coinSelection.ts
+++ b/packages/taler-wallet-core/src/util/coinSelection.ts
@@ -23,7 +23,7 @@
 /**
  * Imports.
  */
-import { AmountJson, Amounts } from "@gnu-taler/taler-util";
+import { AmountJson, Amounts, DenominationPubKey } from 
"@gnu-taler/taler-util";
 import { strcmp, Logger } from "@gnu-taler/taler-util";
 
 const logger = new Logger("coinSelection.ts");
@@ -72,7 +72,7 @@ export interface AvailableCoinInfo {
   /**
    * Coin's denomination public key.
    */
-  denomPub: string;
+  denomPub: DenominationPubKey;
 
   /**
    * Amount still remaining (typically the full amount,
@@ -206,6 +206,21 @@ function tallyFees(
   };
 }
 
+function denomPubCmp(
+  p1: DenominationPubKey,
+  p2: DenominationPubKey,
+): -1 | 0 | 1 {
+  if (p1.cipher < p2.cipher) {
+    return -1;
+  } else if (p1.cipher > p2.cipher) {
+    return +1;
+  }
+  if (p1.cipher !== 1 || p2.cipher !== 1) {
+    throw Error("unsupported cipher");
+  }
+  return strcmp(p1.rsa_public_key, p2.rsa_public_key);
+}
+
 /**
  * Given a list of candidate coins, select coins to spend under the merchant's
  * constraints.
@@ -272,7 +287,7 @@ export function selectPayCoins(
     (o1, o2) =>
       -Amounts.cmp(o1.availableAmount, o2.availableAmount) ||
       Amounts.cmp(o1.feeDeposit, o2.feeDeposit) ||
-      strcmp(o1.denomPub, o2.denomPub),
+      denomPubCmp(o1.denomPub, o2.denomPub),
   );
 
   // FIXME:  Here, we should select coins in a smarter way.
diff --git a/packages/taler-wallet-core/src/wallet.ts 
b/packages/taler-wallet-core/src/wallet.ts
index 32e3945e..cd2dd7f1 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -387,6 +387,7 @@ async function runTaskLoop(
         } catch (e) {
           if (e instanceof OperationFailedAndReportedError) {
             logger.warn("operation processed resulted in reported error");
+            logger.warn(`reporred error was: ${j2s(e.operationError)}`);
           } else {
             logger.error("Uncaught exception", e);
             ws.notify({
@@ -929,7 +930,7 @@ async function dispatchRequestInternal(
       }
       const components = pt.targetPath.split("/");
       const creditorAcct = components[components.length - 1];
-      logger.info(`making testbank transfer to '${creditorAcct}''`)
+      logger.info(`making testbank transfer to '${creditorAcct}''`);
       const fbReq = await ws.http.postJson(
         new URL(`${creditorAcct}/admin/add-incoming`, req.bank).href,
         {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 9a425713..7c306926 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -7,12 +7,12 @@ importers:
       '@linaria/esbuild': ^3.0.0-beta.13
       '@linaria/shaker': ^3.0.0-beta.13
       esbuild: ^0.12.29
-      prettier: ^2.2.1
+      prettier: ^2.4.1
     devDependencies:
       '@linaria/esbuild': 3.0.0-beta.13
       '@linaria/shaker': 3.0.0-beta.13
       esbuild: 0.12.29
-      prettier: 2.2.1
+      prettier: 2.4.1
 
   packages/anastasis-core:
     specifiers:
@@ -255,7 +255,7 @@ importers:
       source-map-support: ^0.5.19
       tslib: ^2.1.0
       typedoc: ^0.20.16
-      typescript: ^4.1.3
+      typescript: ^4.4.4
     dependencies:
       '@gnu-taler/idb-bridge': link:../idb-bridge
       '@gnu-taler/taler-util': link:../taler-util
@@ -269,11 +269,11 @@ importers:
       '@ava/typescript': 1.1.1
       '@gnu-taler/pogen': link:../pogen
       '@microsoft/api-extractor': 7.13.0
-      '@typescript-eslint/eslint-plugin': 
4.14.0_980e7d90d2d08155204a38366bd3b934
-      '@typescript-eslint/parser': 4.14.0_eslint@7.18.0+typescript@4.1.3
+      '@typescript-eslint/eslint-plugin': 
4.14.0_4f40ec8f9ae74407a8c29890901bb23f
+      '@typescript-eslint/parser': 4.14.0_eslint@7.18.0+typescript@4.4.4
       ava: 3.15.0
       eslint: 7.18.0
-      eslint-config-airbnb-typescript: 12.0.0_aa91c0ea1e61103ae60b9cd49dfd9775
+      eslint-config-airbnb-typescript: 12.0.0_b55a7168bd2ecdf8767ddb224d20fd7e
       eslint-plugin-import: 2.22.1_eslint@7.18.0
       eslint-plugin-jsx-a11y: 6.4.1_eslint@7.18.0
       eslint-plugin-react: 7.22.0_eslint@7.18.0
@@ -286,8 +286,8 @@ importers:
       rollup: 2.59.0
       rollup-plugin-sourcemaps: 0.6.3_57eeb328ceff0756ae1d32f4d22d60f9
       source-map-resolve: 0.6.0
-      typedoc: 0.20.16_typescript@4.1.3
-      typescript: 4.1.3
+      typedoc: 0.20.16_typescript@4.4.4
+      typescript: 4.4.4
 
   packages/taler-wallet-embedded:
     specifiers:
@@ -498,6 +498,11 @@ packages:
     engines: {node: '>=6.9.0'}
     dev: true
 
+  /@babel/compat-data/7.16.4:
+    resolution: {integrity: 
sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q==}
+    engines: {node: '>=6.9.0'}
+    dev: true
+
   /@babel/core/7.12.9:
     resolution: {integrity: 
sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==}
     engines: {node: '>=6.9.0'}
@@ -717,6 +722,18 @@ packages:
       semver: 6.3.0
     dev: true
 
+  /@babel/helper-compilation-targets/7.16.3:
+    resolution: {integrity: 
sha512-vKsoSQAyBmxS35JUOOt+07cLc6Nk/2ljLIHwmq2/NM6hdioUaqEXq/S+nXvbvXbZkNDlWOymPanJGOc4CBjSJA==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0
+    dependencies:
+      '@babel/compat-data': 7.16.4
+      '@babel/helper-validator-option': 7.14.5
+      browserslist: 4.18.1
+      semver: 6.3.0
+    dev: true
+
   /@babel/helper-create-class-features-plugin/7.15.0_@babel+core@7.13.16:
     resolution: {integrity: 
sha512-MdmDXgvTIi4heDVX/e9EFfeGpugqm9fobBVg/iioE8kueXrOHdRDe36FAY7SnE9xXLVeYCoJR/gdrBEIHRC83Q==}
     engines: {node: '>=6.9.0'}
@@ -934,6 +951,23 @@ packages:
       - supports-color
     dev: true
 
+  /@babel/helper-define-polyfill-provider/0.3.0:
+    resolution: {integrity: 
sha512-7hfT8lUljl/tM3h+izTX/pO3W3frz2ok6Pk+gzys8iJqDfZrZy2pXjRTZAvG2YmfHun1X4q8/UZRLatMfqc5Tg==}
+    peerDependencies:
+      '@babel/core': ^7.4.0-0
+    dependencies:
+      '@babel/helper-compilation-targets': 7.16.3
+      '@babel/helper-module-imports': 7.16.0
+      '@babel/helper-plugin-utils': 7.14.5
+      '@babel/traverse': 7.16.3
+      debug: 4.3.2
+      lodash.debounce: 4.0.8
+      resolve: 1.20.0
+      semver: 6.3.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
   /@babel/helper-explode-assignable-expression/7.14.5:
     resolution: {integrity: 
sha512-Htb24gnGJdIGT4vnRKMdoXiOIlqOLmdiUYpAQ0mYfgVT/GDm8GOYhgi4GL+hMKrkiPRohO4ts34ELFsGAPQLDQ==}
     engines: {node: '>=6.9.0'}
@@ -1099,6 +1133,17 @@ packages:
       - supports-color
     dev: true
 
+  /@babel/helper-remap-async-to-generator/7.16.4:
+    resolution: {integrity: 
sha512-vGERmmhR+s7eH5Y/cp8PCVzj4XEjerq8jooMfxFdA5xVtAk9Sh4AQsrWgiErUEBjtGrBtOFKDUcWQFW4/dFwMA==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/helper-annotate-as-pure': 7.16.0
+      '@babel/helper-wrap-function': 7.16.0
+      '@babel/types': 7.16.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
   /@babel/helper-replace-supers/7.15.0:
     resolution: {integrity: 
sha512-6O+eWrhx+HEra/uJnifCwhwMd6Bp5+ZfZeJwbqUTuqkhIT6YcRhiZCOOFChRypOIe0cV46kFrRBlm+t5vHCEaA==}
     engines: {node: '>=6.9.0'}
@@ -1206,7 +1251,7 @@ packages:
     dependencies:
       '@babel/helper-function-name': 7.16.0
       '@babel/template': 7.16.0
-      '@babel/traverse': 7.16.0
+      '@babel/traverse': 7.16.3
       '@babel/types': 7.16.0
     transitivePeerDependencies:
       - supports-color
@@ -1280,6 +1325,12 @@ packages:
     hasBin: true
     dev: true
 
+  /@babel/parser/7.16.4:
+    resolution: {integrity: 
sha512-6V0qdPUaiVHH3RtZeLIsc+6pDhbYzHR8ogA8w+f+Wc77DuXto19g2QUwveINoS34Uw+W8/hQDGJCx+i4n7xcng==}
+    engines: {node: '>=6.0.0'}
+    hasBin: true
+    dev: true
+
   
/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.16.2:
     resolution: {integrity: 
sha512-h37CvpLSf8gb2lIJ2CgC3t+EjFbi0t8qS7LCS1xcJIlEXE4czlofwaW7W1HA8zpgOCzI9C1nmoqNR1zWkk0pQg==}
     engines: {node: '>=6.9.0'}
@@ -1401,6 +1452,19 @@ packages:
       - supports-color
     dev: true
 
+  /@babel/plugin-proposal-async-generator-functions/7.16.4:
+    resolution: {integrity: 
sha512-/CUekqaAaZCQHleSK/9HajvcD/zdnJiKRiuUFq8ITE+0HsPzquf53cpFiqAwl/UfmJbR6n5uGPQSPdrmKOvHHg==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+    dependencies:
+      '@babel/helper-plugin-utils': 7.14.5
+      '@babel/helper-remap-async-to-generator': 7.16.4
+      '@babel/plugin-syntax-async-generators': 7.8.4
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
   /@babel/plugin-proposal-class-properties/7.14.5_@babel+core@7.13.16:
     resolution: {integrity: 
sha512-q/PLpv5Ko4dVc1LYMpCY7RVAAO4uk55qPwrIuJ5QJ8c6cVuAmhu7I/49JOppXL6gXf7ZHzpRVEUZdYoPLM04Gg==}
     engines: {node: '>=6.9.0'}
@@ -1860,11 +1924,11 @@ packages:
     peerDependencies:
       '@babel/core': ^7.0.0-0
     dependencies:
-      '@babel/compat-data': 7.16.0
-      '@babel/helper-compilation-targets': 7.16.0
+      '@babel/compat-data': 7.16.4
+      '@babel/helper-compilation-targets': 7.16.3
       '@babel/helper-plugin-utils': 7.14.5
       '@babel/plugin-syntax-object-rest-spread': 7.8.3
-      '@babel/plugin-transform-parameters': 7.16.0
+      '@babel/plugin-transform-parameters': 7.16.3
     dev: true
 
   /@babel/plugin-proposal-object-rest-spread/7.16.0_@babel+core@7.16.0:
@@ -2864,7 +2928,7 @@ packages:
     dependencies:
       '@babel/helper-module-imports': 7.16.0
       '@babel/helper-plugin-utils': 7.14.5
-      '@babel/helper-remap-async-to-generator': 7.16.0
+      '@babel/helper-remap-async-to-generator': 7.16.4
     transitivePeerDependencies:
       - supports-color
     dev: true
@@ -3821,6 +3885,15 @@ packages:
       '@babel/helper-plugin-utils': 7.14.5
     dev: true
 
+  /@babel/plugin-transform-parameters/7.16.3:
+    resolution: {integrity: 
sha512-3MaDpJrOXT1MZ/WCmkOFo7EtmVVC8H4EUZVrHvFOsmwkk4lOjQj8rzv8JKUZV4YoQKeoIgk07GO+acPU9IMu/w==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+    dependencies:
+      '@babel/helper-plugin-utils': 7.14.5
+    dev: true
+
   /@babel/plugin-transform-property-literals/7.14.5_@babel+core@7.13.16:
     resolution: {integrity: 
sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw==}
     engines: {node: '>=6.9.0'}
@@ -4065,17 +4138,17 @@ packages:
       '@babel/helper-plugin-utils': 7.14.5
     dev: true
 
-  /@babel/plugin-transform-runtime/7.16.0:
-    resolution: {integrity: 
sha512-zlPf1/XFn5+vWdve3AAhf+Sxl+MVa5VlwTwWgnLx23u4GlatSRQJ3Eoo9vllf0a9il3woQsT4SK+5Z7c06h8ag==}
+  /@babel/plugin-transform-runtime/7.16.4:
+    resolution: {integrity: 
sha512-pru6+yHANMTukMtEZGC4fs7XPwg35v8sj5CIEmE+gEkFljFiVJxEWxx/7ZDkTK+iZRYo1bFXBtfIN95+K3cJ5A==}
     engines: {node: '>=6.9.0'}
     peerDependencies:
       '@babel/core': ^7.0.0-0
     dependencies:
       '@babel/helper-module-imports': 7.16.0
       '@babel/helper-plugin-utils': 7.14.5
-      babel-plugin-polyfill-corejs2: 0.2.3
-      babel-plugin-polyfill-corejs3: 0.3.0
-      babel-plugin-polyfill-regenerator: 0.2.3
+      babel-plugin-polyfill-corejs2: 0.3.0
+      babel-plugin-polyfill-corejs3: 0.4.0
+      babel-plugin-polyfill-regenerator: 0.3.0
       semver: 6.3.0
     transitivePeerDependencies:
       - supports-color
@@ -4741,6 +4814,90 @@ packages:
       - supports-color
     dev: true
 
+  /@babel/preset-env/7.16.4:
+    resolution: {integrity: 
sha512-v0QtNd81v/xKj4gNKeuAerQ/azeNn/G1B1qMLeXOcV8+4TWlD2j3NV1u8q29SDFBXx/NBq5kyEAO+0mpRgacjA==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+    dependencies:
+      '@babel/compat-data': 7.16.4
+      '@babel/helper-compilation-targets': 7.16.3
+      '@babel/helper-plugin-utils': 7.14.5
+      '@babel/helper-validator-option': 7.14.5
+      
'@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression':
 7.16.2
+      '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.16.0
+      '@babel/plugin-proposal-async-generator-functions': 7.16.4
+      '@babel/plugin-proposal-class-properties': 7.16.0
+      '@babel/plugin-proposal-class-static-block': 7.16.0
+      '@babel/plugin-proposal-dynamic-import': 7.16.0
+      '@babel/plugin-proposal-export-namespace-from': 7.16.0
+      '@babel/plugin-proposal-json-strings': 7.16.0
+      '@babel/plugin-proposal-logical-assignment-operators': 7.16.0
+      '@babel/plugin-proposal-nullish-coalescing-operator': 7.16.0
+      '@babel/plugin-proposal-numeric-separator': 7.16.0
+      '@babel/plugin-proposal-object-rest-spread': 7.16.0
+      '@babel/plugin-proposal-optional-catch-binding': 7.16.0
+      '@babel/plugin-proposal-optional-chaining': 7.16.0
+      '@babel/plugin-proposal-private-methods': 7.16.0
+      '@babel/plugin-proposal-private-property-in-object': 7.16.0
+      '@babel/plugin-proposal-unicode-property-regex': 7.16.0
+      '@babel/plugin-syntax-async-generators': 7.8.4
+      '@babel/plugin-syntax-class-properties': 7.12.13
+      '@babel/plugin-syntax-class-static-block': 7.14.5
+      '@babel/plugin-syntax-dynamic-import': 7.8.3
+      '@babel/plugin-syntax-export-namespace-from': 7.8.3
+      '@babel/plugin-syntax-json-strings': 7.8.3
+      '@babel/plugin-syntax-logical-assignment-operators': 7.10.4
+      '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3
+      '@babel/plugin-syntax-numeric-separator': 7.10.4
+      '@babel/plugin-syntax-object-rest-spread': 7.8.3
+      '@babel/plugin-syntax-optional-catch-binding': 7.8.3
+      '@babel/plugin-syntax-optional-chaining': 7.8.3
+      '@babel/plugin-syntax-private-property-in-object': 7.14.5
+      '@babel/plugin-syntax-top-level-await': 7.14.5
+      '@babel/plugin-transform-arrow-functions': 7.16.0
+      '@babel/plugin-transform-async-to-generator': 7.16.0
+      '@babel/plugin-transform-block-scoped-functions': 7.16.0
+      '@babel/plugin-transform-block-scoping': 7.16.0
+      '@babel/plugin-transform-classes': 7.16.0
+      '@babel/plugin-transform-computed-properties': 7.16.0
+      '@babel/plugin-transform-destructuring': 7.16.0
+      '@babel/plugin-transform-dotall-regex': 7.16.0
+      '@babel/plugin-transform-duplicate-keys': 7.16.0
+      '@babel/plugin-transform-exponentiation-operator': 7.16.0
+      '@babel/plugin-transform-for-of': 7.16.0
+      '@babel/plugin-transform-function-name': 7.16.0
+      '@babel/plugin-transform-literals': 7.16.0
+      '@babel/plugin-transform-member-expression-literals': 7.16.0
+      '@babel/plugin-transform-modules-amd': 7.16.0
+      '@babel/plugin-transform-modules-commonjs': 7.16.0
+      '@babel/plugin-transform-modules-systemjs': 7.16.0
+      '@babel/plugin-transform-modules-umd': 7.16.0
+      '@babel/plugin-transform-named-capturing-groups-regex': 7.16.0
+      '@babel/plugin-transform-new-target': 7.16.0
+      '@babel/plugin-transform-object-super': 7.16.0
+      '@babel/plugin-transform-parameters': 7.16.3
+      '@babel/plugin-transform-property-literals': 7.16.0
+      '@babel/plugin-transform-regenerator': 7.16.0
+      '@babel/plugin-transform-reserved-words': 7.16.0
+      '@babel/plugin-transform-shorthand-properties': 7.16.0
+      '@babel/plugin-transform-spread': 7.16.0
+      '@babel/plugin-transform-sticky-regex': 7.16.0
+      '@babel/plugin-transform-template-literals': 7.16.0
+      '@babel/plugin-transform-typeof-symbol': 7.16.0
+      '@babel/plugin-transform-unicode-escapes': 7.16.0
+      '@babel/plugin-transform-unicode-regex': 7.16.0
+      '@babel/preset-modules': 0.1.5
+      '@babel/types': 7.16.0
+      babel-plugin-polyfill-corejs2: 0.3.0
+      babel-plugin-polyfill-corejs3: 0.4.0
+      babel-plugin-polyfill-regenerator: 0.3.0
+      core-js-compat: 3.19.1
+      semver: 6.3.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
   /@babel/preset-modules/0.1.4_@babel+core@7.13.16:
     resolution: {integrity: 
sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==}
     peerDependencies:
@@ -4919,6 +5076,13 @@ packages:
       regenerator-runtime: 0.13.9
     dev: true
 
+  /@babel/runtime/7.16.3:
+    resolution: {integrity: 
sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      regenerator-runtime: 0.13.9
+    dev: true
+
   /@babel/template/7.14.5:
     resolution: {integrity: 
sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==}
     engines: {node: '>=6.9.0'}
@@ -4971,6 +5135,23 @@ packages:
       - supports-color
     dev: true
 
+  /@babel/traverse/7.16.3:
+    resolution: {integrity: 
sha512-eolumr1vVMjqevCpwVO99yN/LoGL0EyHiLO5I043aYQvwOJ9eR5UsZSClHVCzfhBduMAsSzgA/6AyqPjNayJag==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/code-frame': 7.16.0
+      '@babel/generator': 7.16.0
+      '@babel/helper-function-name': 7.16.0
+      '@babel/helper-hoist-variables': 7.16.0
+      '@babel/helper-split-export-declaration': 7.16.0
+      '@babel/parser': 7.16.4
+      '@babel/types': 7.16.0
+      debug: 4.3.2
+      globals: 11.12.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
   /@babel/types/7.15.0:
     resolution: {integrity: 
sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==}
     engines: {node: '>=6.9.0'}
@@ -5765,9 +5946,9 @@ packages:
       '@babel/core': '>=7'
     dependencies:
       '@babel/generator': 7.16.0
-      '@babel/plugin-transform-runtime': 7.16.0
+      '@babel/plugin-transform-runtime': 7.16.4
       '@babel/plugin-transform-template-literals': 7.16.0
-      '@babel/preset-env': 7.16.0
+      '@babel/preset-env': 7.16.4
       '@linaria/babel-preset': 3.0.0-beta.13
       '@linaria/logger': 3.0.0-beta.3
       '@linaria/preeval': 3.0.0-beta.13
@@ -5897,7 +6078,7 @@ packages:
       resolve: 1.17.0
       semver: 7.3.4
       source-map: 0.6.1
-      typescript: 4.1.3
+      typescript: 4.1.6
     dev: true
 
   /@microsoft/tsdoc/0.12.24:
@@ -10194,7 +10375,7 @@ packages:
       '@types/yargs-parser': 20.2.1
     dev: true
 
-  /@typescript-eslint/eslint-plugin/4.14.0_980e7d90d2d08155204a38366bd3b934:
+  /@typescript-eslint/eslint-plugin/4.14.0_4f40ec8f9ae74407a8c29890901bb23f:
     resolution: {integrity: 
sha512-IJ5e2W7uFNfg4qh9eHkHRUCbgZ8VKtGwD07kannJvM5t/GU8P8+24NX8gi3Hf5jST5oWPY8kyV1s/WtfiZ4+Ww==}
     engines: {node: ^10.12.0 || >=12.0.0}
     peerDependencies:
@@ -10205,8 +10386,8 @@ packages:
       typescript:
         optional: true
     dependencies:
-      '@typescript-eslint/experimental-utils': 
4.14.0_eslint@7.18.0+typescript@4.1.3
-      '@typescript-eslint/parser': 4.14.0_eslint@7.18.0+typescript@4.1.3
+      '@typescript-eslint/experimental-utils': 
4.14.0_eslint@7.18.0+typescript@4.4.4
+      '@typescript-eslint/parser': 4.14.0_eslint@7.18.0+typescript@4.4.4
       '@typescript-eslint/scope-manager': 4.14.0
       debug: 4.3.1
       eslint: 7.18.0
@@ -10214,8 +10395,8 @@ packages:
       lodash: 4.17.20
       regexpp: 3.1.0
       semver: 7.3.4
-      tsutils: 3.19.1_typescript@4.1.3
-      typescript: 4.1.3
+      tsutils: 3.19.1_typescript@4.4.4
+      typescript: 4.4.4
     transitivePeerDependencies:
       - supports-color
     dev: true
@@ -10262,7 +10443,7 @@ packages:
       - typescript
     dev: true
 
-  /@typescript-eslint/experimental-utils/4.14.0_eslint@7.18.0+typescript@4.1.3:
+  /@typescript-eslint/experimental-utils/4.14.0_eslint@7.18.0+typescript@4.4.4:
     resolution: {integrity: 
sha512-6i6eAoiPlXMKRbXzvoQD5Yn9L7k9ezzGRvzC/x1V3650rUk3c3AOjQyGYyF9BDxQQDK2ElmKOZRD0CbtdkMzQQ==}
     engines: {node: ^10.12.0 || >=12.0.0}
     peerDependencies:
@@ -10271,7 +10452,7 @@ packages:
       '@types/json-schema': 7.0.7
       '@typescript-eslint/scope-manager': 4.14.0
       '@typescript-eslint/types': 4.14.0
-      '@typescript-eslint/typescript-estree': 4.14.0_typescript@4.1.3
+      '@typescript-eslint/typescript-estree': 4.14.0_typescript@4.4.4
       eslint: 7.18.0
       eslint-scope: 5.1.1
       eslint-utils: 2.1.0
@@ -10298,7 +10479,7 @@ packages:
       - typescript
     dev: true
 
-  /@typescript-eslint/parser/4.14.0_eslint@7.18.0+typescript@4.1.3:
+  /@typescript-eslint/parser/4.14.0_eslint@7.18.0+typescript@4.4.4:
     resolution: {integrity: 
sha512-sUDeuCjBU+ZF3Lzw0hphTyScmDDJ5QVkyE21pRoBo8iDl7WBtVFS+WDN3blY1CH3SBt7EmYCw6wfmJjF0l/uYg==}
     engines: {node: ^10.12.0 || >=12.0.0}
     peerDependencies:
@@ -10310,15 +10491,15 @@ packages:
     dependencies:
       '@typescript-eslint/scope-manager': 4.14.0
       '@typescript-eslint/types': 4.14.0
-      '@typescript-eslint/typescript-estree': 4.14.0_typescript@4.1.3
+      '@typescript-eslint/typescript-estree': 4.14.0_typescript@4.4.4
       debug: 4.3.1
       eslint: 7.18.0
-      typescript: 4.1.3
+      typescript: 4.4.4
     transitivePeerDependencies:
       - supports-color
     dev: true
 
-  /@typescript-eslint/parser/4.4.1_eslint@7.18.0+typescript@4.1.3:
+  /@typescript-eslint/parser/4.4.1_eslint@7.18.0+typescript@4.4.4:
     resolution: {integrity: 
sha512-S0fuX5lDku28Au9REYUsV+hdJpW/rNW0gWlc4SXzF/kdrRaAVX9YCxKpziH7djeWT/HFAjLZcnY7NJD8xTeUEg==}
     engines: {node: ^10.12.0 || >=12.0.0}
     peerDependencies:
@@ -10330,10 +10511,10 @@ packages:
     dependencies:
       '@typescript-eslint/scope-manager': 4.4.1
       '@typescript-eslint/types': 4.4.1
-      '@typescript-eslint/typescript-estree': 4.4.1_typescript@4.1.3
+      '@typescript-eslint/typescript-estree': 4.4.1_typescript@4.4.4
       debug: 4.3.1
       eslint: 7.18.0
-      typescript: 4.1.3
+      typescript: 4.4.4
     transitivePeerDependencies:
       - supports-color
     dev: true
@@ -10418,7 +10599,7 @@ packages:
       - supports-color
     dev: true
 
-  /@typescript-eslint/typescript-estree/4.14.0_typescript@4.1.3:
+  /@typescript-eslint/typescript-estree/4.14.0_typescript@4.4.4:
     resolution: {integrity: 
sha512-wRjZ5qLao+bvS2F7pX4qi2oLcOONIB+ru8RGBieDptq/SudYwshveORwCVU4/yMAd4GK7Fsf8Uq1tjV838erag==}
     engines: {node: ^10.12.0 || >=12.0.0}
     peerDependencies:
@@ -10434,13 +10615,13 @@ packages:
       is-glob: 4.0.1
       lodash: 4.17.20
       semver: 7.3.4
-      tsutils: 3.19.1_typescript@4.1.3
-      typescript: 4.1.3
+      tsutils: 3.19.1_typescript@4.4.4
+      typescript: 4.4.4
     transitivePeerDependencies:
       - supports-color
     dev: true
 
-  /@typescript-eslint/typescript-estree/4.4.1_typescript@4.1.3:
+  /@typescript-eslint/typescript-estree/4.4.1_typescript@4.4.4:
     resolution: {integrity: 
sha512-wP/V7ScKzgSdtcY1a0pZYBoCxrCstLrgRQ2O9MmCUZDtmgxCO/TCqOTGRVwpP4/2hVfqMz/Vw1ZYrG8cVxvN3g==}
     engines: {node: ^10.12.0 || >=12.0.0}
     peerDependencies:
@@ -10456,8 +10637,8 @@ packages:
       is-glob: 4.0.1
       lodash: 4.17.20
       semver: 7.3.4
-      tsutils: 3.19.1_typescript@4.1.3
-      typescript: 4.1.3
+      tsutils: 3.19.1_typescript@4.4.4
+      typescript: 4.4.4
     transitivePeerDependencies:
       - supports-color
     dev: true
@@ -11644,6 +11825,18 @@ packages:
       - supports-color
     dev: true
 
+  /babel-plugin-polyfill-corejs2/0.3.0:
+    resolution: {integrity: 
sha512-wMDoBJ6uG4u4PNFh72Ty6t3EgfA91puCuAwKIazbQlci+ENb/UU9A3xG5lutjUIiXCIn1CY5L15r9LimiJyrSA==}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+    dependencies:
+      '@babel/compat-data': 7.16.4
+      '@babel/helper-define-polyfill-provider': 0.3.0
+      semver: 6.3.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
   /babel-plugin-polyfill-corejs3/0.1.7_@babel+core@7.15.0:
     resolution: {integrity: 
sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw==}
     peerDependencies:
@@ -11715,6 +11908,17 @@ packages:
       - supports-color
     dev: true
 
+  /babel-plugin-polyfill-corejs3/0.4.0:
+    resolution: {integrity: 
sha512-YxFreYwUfglYKdLUGvIF2nJEsGwj+RhWSX/ije3D2vQPOXuyMLMtg/cCGMDpOA7Nd+MwlNdnGODbd2EwUZPlsw==}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+    dependencies:
+      '@babel/helper-define-polyfill-provider': 0.3.0
+      core-js-compat: 3.19.1
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
   /babel-plugin-polyfill-regenerator/0.2.2_@babel+core@7.13.16:
     resolution: {integrity: 
sha512-Goy5ghsc21HgPDFtzRkSirpZVW35meGoTmTOb2bxqdl60ghub4xOidgNTHaZfQ2FaxQsKmwvXtOAkcIS4SMBWg==}
     peerDependencies:
@@ -11758,6 +11962,16 @@ packages:
       - supports-color
     dev: true
 
+  /babel-plugin-polyfill-regenerator/0.3.0:
+    resolution: {integrity: 
sha512-dhAPTDLGoMW5/84wkgwiLRwMnio2i1fUe53EuvtKMv0pn2p3S8OCoV1xAzfJPl0KOX7IB89s2ib85vbYiea3jg==}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+    dependencies:
+      '@babel/helper-define-polyfill-provider': 0.3.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
   /babel-plugin-syntax-jsx/6.18.0:
     resolution: {integrity: sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=}
     dev: true
@@ -12156,6 +12370,18 @@ packages:
       picocolors: 1.0.0
     dev: true
 
+  /browserslist/4.18.1:
+    resolution: {integrity: 
sha512-8ScCzdpPwR2wQh8IT82CA2VgDwjHyqMovPBZSNH54+tm4Jk2pCuv90gmAdH6J84OCRWi0b4gMe6O6XPXuJnjgQ==}
+    engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+    hasBin: true
+    dependencies:
+      caniuse-lite: 1.0.30001280
+      electron-to-chromium: 1.3.899
+      escalade: 3.1.1
+      node-releases: 2.0.1
+      picocolors: 1.0.0
+    dev: true
+
   /bser/2.1.1:
     resolution: {integrity: 
sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==}
     dependencies:
@@ -12394,6 +12620,10 @@ packages:
     resolution: {integrity: 
sha512-psUNoaG1ilknZPxi8HuhQWobuhLqtYSRUxplfVkEJdgZNB9TETVYGSBtv4YyfAdGvE6gn2eb0ztiXqHoWJcGnw==}
     dev: true
 
+  /caniuse-lite/1.0.30001280:
+    resolution: {integrity: 
sha512-kFXwYvHe5rix25uwueBxC569o53J6TpnGu0BEEn+6Lhl2vsnAumRFWEBhDft1fwyo6m1r4i+RqA4+163FpeFcA==}
+    dev: true
+
   /capture-exit/2.0.0:
     resolution: {integrity: 
sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==}
     engines: {node: 6.* || 8.* || >= 10.*}
@@ -13052,7 +13282,7 @@ packages:
   /core-js-compat/3.19.1:
     resolution: {integrity: 
sha512-Q/VJ7jAF/y68+aUsQJ/afPOewdsGkDtcMb40J8MbuWKlK3Y+wtHq8bTHKPj2WKWLIqmS5JhHs4CzHtz6pT2W6g==}
     dependencies:
-      browserslist: 4.17.6
+      browserslist: 4.18.1
       semver: 7.0.0
     dev: true
 
@@ -14141,6 +14371,10 @@ packages:
     resolution: {integrity: 
sha512-5iD1zgyPpFER4kJ716VsA4MxQ6x405dxdFNCEK2mITL075VHO5ResjY0xzQUZguCww/KlBxCA6JmBA9sDt1PRw==}
     dev: true
 
+  /electron-to-chromium/1.3.899:
+    resolution: {integrity: 
sha512-w16Dtd2zl7VZ4N4Db+FIa7n36sgPGCKjrKvUUmp5ialsikvcQLjcJR9RWnlYNxIyEHLdHaoIZEqKsPxU9MdyBg==}
+    dev: true
+
   /element-resize-detector/1.2.3:
     resolution: {integrity: 
sha512-+dhNzUgLpq9ol5tyhoG7YLoXL3ssjfFW+0gpszXPwRU6NjGr1fVHMEAF8fVzIiRJq57Nre0RFeIjJwI8Nh2NmQ==}
     dependencies:
@@ -14546,13 +14780,13 @@ packages:
       object.entries: 1.1.3
     dev: true
 
-  /eslint-config-airbnb-typescript/12.0.0_aa91c0ea1e61103ae60b9cd49dfd9775:
+  /eslint-config-airbnb-typescript/12.0.0_b55a7168bd2ecdf8767ddb224d20fd7e:
     resolution: {integrity: 
sha512-TUCVru1Z09eKnVAX5i3XoNzjcCOU3nDQz2/jQGkg1jVYm+25fKClveziSl16celfCq+npU0MBPW/ZnXdGFZ9lw==}
     peerDependencies:
       '@typescript-eslint/eslint-plugin': ^4.4.1
     dependencies:
-      '@typescript-eslint/eslint-plugin': 
4.14.0_980e7d90d2d08155204a38366bd3b934
-      '@typescript-eslint/parser': 4.4.1_eslint@7.18.0+typescript@4.1.3
+      '@typescript-eslint/eslint-plugin': 
4.14.0_4f40ec8f9ae74407a8c29890901bb23f
+      '@typescript-eslint/parser': 4.4.1_eslint@7.18.0+typescript@4.4.4
       eslint-config-airbnb: 18.2.0_8b932c4aedefa0fbb298d8c6e2d8003e
       eslint-config-airbnb-base: 14.2.0_d4477e7d44043beb7952cd76bd313965
     transitivePeerDependencies:
@@ -16140,7 +16374,7 @@ packages:
       source-map: 0.6.1
       wordwrap: 1.0.0
     optionalDependencies:
-      uglify-js: 3.12.5
+      uglify-js: 3.14.3
     dev: true
 
   /har-schema/2.0.0:
@@ -18774,7 +19008,7 @@ packages:
   /jsonfile/4.0.0:
     resolution: {integrity: sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=}
     optionalDependencies:
-      graceful-fs: 4.2.8
+      graceful-fs: 4.2.4
     dev: true
 
   /jsonfile/6.1.0:
@@ -18949,7 +19183,7 @@ packages:
     resolution: {integrity: sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=}
     engines: {node: '>=4'}
     dependencies:
-      graceful-fs: 4.2.4
+      graceful-fs: 4.2.8
       parse-json: 2.2.0
       pify: 2.3.0
       strip-bom: 3.0.0
@@ -21794,6 +22028,12 @@ packages:
     hasBin: true
     dev: true
 
+  /prettier/2.4.1:
+    resolution: {integrity: 
sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==}
+    engines: {node: '>=10.13.0'}
+    hasBin: true
+    dev: true
+
   /pretty-bytes/4.0.2:
     resolution: {integrity: sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=}
     engines: {node: '>=4'}
@@ -22643,7 +22883,7 @@ packages:
   /regenerator-transform/0.14.5:
     resolution: {integrity: 
sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==}
     dependencies:
-      '@babel/runtime': 7.16.0
+      '@babel/runtime': 7.16.3
     dev: true
 
   /regex-not/1.0.2:
@@ -24827,14 +25067,14 @@ packages:
   /tslib/2.3.1:
     resolution: {integrity: 
sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==}
 
-  /tsutils/3.19.1_typescript@4.1.3:
+  /tsutils/3.19.1_typescript@4.4.4:
     resolution: {integrity: 
sha512-GEdoBf5XI324lu7ycad7s6laADfnAqCw6wLGI+knxvw9vsIYBaJfYdmeCEG3FMMUiSm3OGgNb+m6utsWf5h9Vw==}
     engines: {node: '>= 6'}
     peerDependencies:
       typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || 
>= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta'
     dependencies:
       tslib: 1.14.1
-      typescript: 4.1.3
+      typescript: 4.4.4
     dev: true
 
   /tsutils/3.21.0_typescript@4.4.4:
@@ -24959,12 +25199,39 @@ packages:
       typescript: 4.1.3
     dev: true
 
+  /typedoc/0.20.16_typescript@4.4.4:
+    resolution: {integrity: 
sha512-xqIL8lT6ZE3QpP0GN30ckeTR05NSEkrP2pXQlNhC0OFkbvnjqJtDUcWSmCO15BuYyu4qsEbZT+tKYFEAt9Jxew==}
+    engines: {node: '>= 10.8.0'}
+    hasBin: true
+    peerDependencies:
+      typescript: 3.9.x || 4.0.x || 4.1.x
+    dependencies:
+      colors: 1.4.0
+      fs-extra: 9.1.0
+      handlebars: 4.7.6
+      lodash: 4.17.20
+      lunr: 2.3.9
+      marked: 1.2.7
+      minimatch: 3.0.4
+      progress: 2.0.3
+      shelljs: 0.8.4
+      shiki: 0.2.7
+      typedoc-default-themes: 0.12.4
+      typescript: 4.4.4
+    dev: true
+
   /typescript/4.1.3:
     resolution: {integrity: 
sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==}
     engines: {node: '>=4.2.0'}
     hasBin: true
     dev: true
 
+  /typescript/4.1.6:
+    resolution: {integrity: 
sha512-pxnwLxeb/Z5SP80JDRzVjh58KsM6jZHRAOtTpS7sXLS4ogXNKC9ANxHHZqLLeVHZN35jCtI4JdmLLbLiC1kBow==}
+    engines: {node: '>=4.2.0'}
+    hasBin: true
+    dev: true
+
   /typescript/4.2.3:
     resolution: {integrity: 
sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==}
     engines: {node: '>=4.2.0'}
@@ -24989,8 +25256,8 @@ packages:
     hasBin: true
     dev: true
 
-  /uglify-js/3.12.5:
-    resolution: {integrity: 
sha512-SgpgScL4T7Hj/w/GexjnBHi3Ien9WS1Rpfg5y91WXMj9SY997ZCQU76mH4TpLwwfmMvoOU8wiaRkIf6NaH3mtg==}
+  /uglify-js/3.14.3:
+    resolution: {integrity: 
sha512-mic3aOdiq01DuSVx0TseaEzMIVqebMZ0Z3vaeDhFEh9bsc24hV1TFvN74reA2vs08D0ZWfNjAcJ3UbVLaBss+g==}
     engines: {node: '>=0.8.0'}
     hasBin: true
     dev: true

-- 
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]