gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [taler-wallet-core] branch master updated (d98c1b09 -> defb


From: gnunet
Subject: [GNUnet-SVN] [taler-wallet-core] branch master updated (d98c1b09 -> defbf625)
Date: Thu, 29 Aug 2019 23:13:12 +0200

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

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

    from d98c1b09 idb: fix bug in index iteration
     new 70c0a557 taler://pay support
     new 1390175a rudimentary taler://withdraw support
     new defbf625 url-based pay/withdraw, use react hooks

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 gulpfile.js                                        |    1 +
 package.json                                       |   10 +-
 src/crypto/cryptoApi-test.ts                       |    2 +
 src/crypto/synchronousWorker.ts                    |   10 +-
 src/dbTypes.ts                                     |   18 +
 src/headless/bank.ts                               |    4 +-
 src/headless/helpers.ts                            |   74 +-
 src/headless/taler-wallet-cli.ts                   |   52 +-
 src/http.ts                                        |   50 +-
 src/i18n.tsx                                       |    4 +-
 src/i18n/de.po                                     |  273 +++--
 src/i18n/en-US.po                                  |  251 ++--
 src/i18n/fr.po                                     |  251 ++--
 src/i18n/it.po                                     |  251 ++--
 src/i18n/strings.ts                                |  590 +++++-----
 src/i18n/sv.po                                     |  277 +++--
 src/i18n/taler-wallet-webex.pot                    |  251 ++--
 src/talerTypes.ts                                  |   36 +
 src/taleruri-test.ts                               |   89 ++
 src/taleruri.ts                                    |  106 ++
 src/wallet.ts                                      |  276 ++++-
 src/walletTypes.ts                                 |  100 +-
 src/webex/messages.ts                              |   68 +-
 src/webex/pages/confirm-contract.tsx               |  417 -------
 src/webex/pages/confirm-create-reserve.tsx         |  526 ---------
 .../pages/{confirm-contract.html => pay.html}      |    2 +-
 src/webex/pages/pay.tsx                            |  173 +++
 .../{confirm-create-reserve.html => withdraw.html} |    2 +-
 src/webex/pages/withdraw.tsx                       |  231 ++++
 src/webex/style/wallet.css                         |    5 +
 src/webex/wxApi.ts                                 |   23 +
 src/webex/wxBackend.ts                             |  262 ++---
 tsconfig.json                                      |    9 +-
 webpack.config.js                                  |    4 +-
 yarn.lock                                          | 1232 +++++++++++++-------
 35 files changed, 3101 insertions(+), 2829 deletions(-)
 create mode 100644 src/taleruri-test.ts
 create mode 100644 src/taleruri.ts
 delete mode 100644 src/webex/pages/confirm-contract.tsx
 delete mode 100644 src/webex/pages/confirm-create-reserve.tsx
 rename src/webex/pages/{confirm-contract.html => pay.html} (96%)
 create mode 100644 src/webex/pages/pay.tsx
 rename src/webex/pages/{confirm-create-reserve.html => withdraw.html} (88%)
 create mode 100644 src/webex/pages/withdraw.tsx

diff --git a/gulpfile.js b/gulpfile.js
index 63965e7e..698944b2 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -104,6 +104,7 @@ const tsBaseArgs = {
   allowJs: true,
   checkJs: true,
   incremental: true,
+  esModuleInterop: true,
 };
 
 
diff --git a/package.json b/package.json
index b0a22151..184230a7 100644
--- a/package.json
+++ b/package.json
@@ -18,7 +18,7 @@
   "devDependencies": {
     "@types/react": "^16.4.0",
     "@types/react-dom": "^16.0.0",
-    "ava": "^1.4.1",
+    "ava": "^2.3.0",
     "awesome-typescript-loader": "^5.2.1",
     "glob": "^7.1.1",
     "gulp": "^4.0.0",
@@ -38,23 +38,23 @@
     "structured-clone": "^0.2.2",
     "terser-webpack-plugin": "^1.2.3",
     "through2": "3.0.1",
-    "tslint": "^5.14.0",
+    "tslint": "^5.19.0",
     "typedoc": "^0.15.0",
     "typescript": "^3.3.4000",
     "uglify-js": "^3.0.27",
     "vinyl": "^2.2.0",
     "vinyl-fs": "^3.0.3",
-    "webpack": "^4.29.6",
+    "webpack": "^4.39.3",
     "webpack-bundle-analyzer": "^3.0.2",
     "webpack-cli": "^3.1.0",
-    "webpack-merge": "^4.1.0"
+    "webpack-merge": "^4.2.2"
   },
   "dependencies": {
     "@types/chrome": "^0.0.88",
     "@types/urijs": "^1.19.3",
     "axios": "^0.19.0",
     "commander": "^3.0.0",
-    "idb-bridge": "^0.0.7",
+    "idb-bridge": "^0.0.9",
     "qrcode-generator": "^1.4.3",
     "source-map-support": "^0.5.12",
     "urijs": "^1.18.10"
diff --git a/src/crypto/cryptoApi-test.ts b/src/crypto/cryptoApi-test.ts
index 48231e5f..39f46c5c 100644
--- a/src/crypto/cryptoApi-test.ts
+++ b/src/crypto/cryptoApi-test.ts
@@ -96,6 +96,8 @@ test("precoin creation", async t => {
     reserve_pub: pub,
     timestamp_confirmed: 0,
     timestamp_depleted: 0,
+    timestamp_reserve_info_posted: 0,
+    exchangeWire: "payto://foo"
   };
 
   const precoin = await crypto.createPreCoin(denomValid1, r);
diff --git a/src/crypto/synchronousWorker.ts b/src/crypto/synchronousWorker.ts
index b697c8e1..41ebee4f 100644
--- a/src/crypto/synchronousWorker.ts
+++ b/src/crypto/synchronousWorker.ts
@@ -93,13 +93,19 @@ export class SynchronousCryptoWorker {
       return;
     }
 
+    let result: any;
     try {
-      const result = (impl as any)[operation](...args);
-      this.dispatchMessage({ result, id });
+      result = (impl as any)[operation](...args);
     } catch (e) {
       console.log("error during operation", e);
       return;
     }
+
+    try {
+      setImmediate(() => this.dispatchMessage({ result, id }));
+    } catch (e) {
+      console.log("got error during dispatch", e);
+    }
   }
 
   /**
diff --git a/src/dbTypes.ts b/src/dbTypes.ts
index 55b2ddbe..d9fd2e9d 100644
--- a/src/dbTypes.ts
+++ b/src/dbTypes.ts
@@ -81,6 +81,16 @@ export interface ReserveRecord {
    */
   timestamp_depleted: number;
 
+
+  /**
+   * Time when the information about this reserve was posted to the bank.
+   * 
+   * Only applies if bankWithdrawStatusUrl is defined.
+   * 
+   * Set to 0 if that hasn't happened yet.
+   */
+  timestamp_reserve_info_posted: number;
+
   /**
    * Time when the reserve was confirmed.
    *
@@ -117,6 +127,14 @@ export interface ReserveRecord {
    * transfered funds for this reserve.
    */
   senderWire?: string;
+
+  /**
+   * Wire information (as payto URI) for the exchange, specifically
+   * the account that was transferred to when creating the reserve.
+   */
+  exchangeWire: string;
+
+  bankWithdrawStatusUrl?: string;
 }
 
 
diff --git a/src/headless/bank.ts b/src/headless/bank.ts
index 7d8db9fe..f3502100 100644
--- a/src/headless/bank.ts
+++ b/src/headless/bank.ts
@@ -51,7 +51,7 @@ export class Bank {
     reservePub: string,
     exchangePaytoUri: string,
   ) {
-    const reqUrl = new URI("taler/withdraw")
+    const reqUrl = new URI("api/withdraw-headless")
       .absoluteTo(this.bankBaseUrl)
       .href();
 
@@ -80,7 +80,7 @@ export class Bank {
   }
 
   async registerRandomUser(): Promise<BankUser> {
-    const reqUrl = new URI("register").absoluteTo(this.bankBaseUrl).href();
+    const reqUrl = new URI("api/register").absoluteTo(this.bankBaseUrl).href();
     const randId = makeId(8);
     const bankUser: BankUser = {
       username: `testuser-${randId}`,
diff --git a/src/headless/helpers.ts b/src/headless/helpers.ts
index 9652c630..a86b2673 100644
--- a/src/headless/helpers.ts
+++ b/src/headless/helpers.ts
@@ -54,17 +54,21 @@ class ConsoleBadge implements Badge {
 export class NodeHttpLib implements HttpRequestLibrary {
   async get(url: string): Promise<import("../http").HttpResponse> {
     enableTracing && console.log("making GET request to", url);
-    const resp = await Axios({
-      method: "get",
-      url: url,
-      responseType: "json",
-    });
-    enableTracing && console.log("got response", resp.data);
-    enableTracing && console.log("resp type", typeof resp.data);
-    return {
-      responseJson: resp.data,
-      status: resp.status,
-    };
+    try {
+      const resp = await Axios({
+        method: "get",
+        url: url,
+        responseType: "json",
+      });
+      enableTracing && console.log("got response", resp.data);
+      enableTracing && console.log("resp type", typeof resp.data);
+      return {
+        responseJson: resp.data,
+        status: resp.status,
+      };
+    } catch (e) {
+      throw e;
+    }
   }
 
   async postJson(
@@ -72,37 +76,22 @@ export class NodeHttpLib implements HttpRequestLibrary {
     body: any,
   ): Promise<import("../http").HttpResponse> {
     enableTracing && console.log("making POST request to", url);
-    const resp = await Axios({
-      method: "post",
-      url: url,
-      responseType: "json",
-      data: body,
-    });
-    enableTracing && console.log("got response", resp.data);
-    enableTracing && console.log("resp type", typeof resp.data);
-    return {
-      responseJson: resp.data,
-      status: resp.status,
-    };
-  }
-
-  async postForm(
-    url: string,
-    form: any,
-  ): Promise<import("../http").HttpResponse> {
-    enableTracing && console.log("making POST request to", url);
-    const resp = await Axios({
-      method: "post",
-      url: url,
-      data: querystring.stringify(form),
-      responseType: "json",
-    });
-    enableTracing && console.log("got response", resp.data);
-    enableTracing && console.log("resp type", typeof resp.data);
-    return {
-      responseJson: resp.data,
-      status: resp.status,
-    };
+    try {
+      const resp = await Axios({
+        method: "post",
+        url: url,
+        responseType: "json",
+        data: body,
+      });
+      enableTracing && console.log("got response", resp.data);
+      enableTracing && console.log("resp type", typeof resp.data);
+      return {
+        responseJson: resp.data,
+        status: resp.status,
+      };
+    } catch (e) {
+      throw e;
+    }
   }
 }
 
@@ -221,6 +210,7 @@ export async function withdrawTestBalance(
   const reserveResponse = await myWallet.createReserve({
     amount: amounts.parseOrThrow(amount),
     exchange: exchangeBaseUrl,
+    exchangeWire: "payto://unknown",
   });
 
   const bank = new Bank(bankBaseUrl);
diff --git a/src/headless/taler-wallet-cli.ts b/src/headless/taler-wallet-cli.ts
index 4a1f5d91..659cffe6 100644
--- a/src/headless/taler-wallet-cli.ts
+++ b/src/headless/taler-wallet-cli.ts
@@ -103,15 +103,14 @@ program
     console.log("created new order with order ID", orderResp.orderId);
     const checkPayResp = await merchantBackend.checkPayment(orderResp.orderId);
     const qrcode = qrcodeGenerator(0, "M");
-    const contractUrl = checkPayResp.contract_url;
-    if (typeof contractUrl !== "string") {
-      console.error("fata: no contract url received from backend");
+    const talerPayUri = checkPayResp.taler_pay_uri;
+    if (!talerPayUri) {
+      console.error("fatal: no taler pay URI received from backend");
       process.exit(1);
       return;
     }
-    const url = "talerpay:" + querystring.escape(contractUrl);
-    console.log("contract url:", url);
-    qrcode.addData(url);
+    console.log("taler pay URI:", talerPayUri);
+    qrcode.addData(talerPayUri);
     qrcode.make();
     console.log(qrcode.createASCII());
     console.log("waiting for payment ...");
@@ -128,6 +127,45 @@ program
   });
 
 program
+  .command("withdraw-url <withdraw-url>")
+  .action(async (withdrawUrl, cmdObj) => {
+    applyVerbose(program.verbose);
+    console.log("withdrawing", withdrawUrl);
+    const wallet = await getDefaultNodeWallet({
+      persistentStoragePath: walletDbPath,
+    });
+
+    const withdrawInfo = await wallet.downloadWithdrawInfo(withdrawUrl);
+
+    console.log("withdraw info", withdrawInfo);
+
+    const selectedExchange = withdrawInfo.suggestedExchange;
+    if (!selectedExchange) {
+      console.error("no suggested exchange!");
+      process.exit(1);
+      return;
+    }
+
+    const {
+      reservePub,
+      confirmTransferUrl,
+    } = await wallet.acceptWithdrawal(
+      withdrawUrl,
+      selectedExchange,
+    );
+
+    if (confirmTransferUrl) {
+      console.log("please confirm the transfer at", confirmTransferUrl);
+    }
+
+    await wallet.processReserve(reservePub);
+
+    console.log("finished withdrawing");
+
+    wallet.stop();
+  });
+
+program
   .command("pay-url <pay-url>")
   .option("-y, --yes", "automatically answer yes to prompts")
   .action(async (payUrl, cmdObj) => {
@@ -179,7 +217,7 @@ program
 
     if (pay) {
       const payRes = await wallet.confirmPay(result.proposalId!, undefined);
-      console.log("paid!");      
+      console.log("paid!");
     } else {
       console.log("not paying");
     }
diff --git a/src/http.ts b/src/http.ts
index f450d847..8c1f772d 100644
--- a/src/http.ts
+++ b/src/http.ts
@@ -27,7 +27,6 @@ export interface HttpResponse {
   responseJson: object & any;
 }
 
-
 /**
  * The request library is bundled into an interface to make mocking easy.
  */
@@ -37,15 +36,16 @@ export interface HttpRequestLibrary {
   postJson(url: string, body: any): Promise<HttpResponse>;
 }
 
-
 /**
  * An implementation of the [[HttpRequestLibrary]] using the
  * browser's XMLHttpRequest.
  */
 export class BrowserHttpLib implements HttpRequestLibrary {
-  private req(method: string,
-              url: string,
-              options?: any): Promise<HttpResponse> {
+  private req(
+    method: string,
+    url: string,
+    options?: any,
+  ): Promise<HttpResponse> {
     return new Promise<HttpResponse>((resolve, reject) => {
       const myRequest = new XMLHttpRequest();
       myRequest.open(method, url);
@@ -54,11 +54,36 @@ export class BrowserHttpLib implements HttpRequestLibrary {
       } else {
         myRequest.send();
       }
-      myRequest.addEventListener("readystatechange", (e) => {
+
+      myRequest.onerror = e => {
+        console.error("http request error");
+        reject(Error("could not make XMLHttpRequest"));
+      };
+
+      myRequest.addEventListener("readystatechange", e => {
         if (myRequest.readyState === XMLHttpRequest.DONE) {
-          const responseJson = JSON.parse(myRequest.responseText);
+          if (myRequest.status === 0) {
+            reject(Error("HTTP Request failed (status code 0, maybe URI scheme 
is wrong?)"))
+            return;
+          }
+          if (myRequest.status != 200) {
+            reject(
+              Error(
+                `HTTP Response with unexpected status code 
${myRequest.status}: ${myRequest.statusText}`,
+              ),
+            );
+            return;
+          }
+          let responseJson;
+          try {
+            responseJson = JSON.parse(myRequest.responseText);
+          } catch (e) {
+            reject(Error("Invalid JSON from HTTP response"));
+            return;
+          }
           if (responseJson === null || typeof responseJson !== "object") {
             reject(Error("Invalid JSON from HTTP response"));
+            return;
           }
           const resp = {
             responseJson: responseJson,
@@ -70,27 +95,22 @@ export class BrowserHttpLib implements HttpRequestLibrary {
     });
   }
 
-
   get(url: string) {
     return this.req("get", url);
   }
 
-
   postJson(url: string, body: any) {
-    return this.req("post", url, {req: JSON.stringify(body)});
+    return this.req("post", url, { req: JSON.stringify(body) });
   }
 
-
   postForm(url: string, form: any) {
-    return this.req("post", url, {req: form});
+    return this.req("post", url, { req: form });
   }
 }
 
-
 /**
  * Exception thrown on request errors.
  */
 export class RequestException {
-  constructor(public detail: any) {
-  }
+  constructor(public detail: any) {}
 }
diff --git a/src/i18n.tsx b/src/i18n.tsx
index 29df1c5a..67df6c51 100644
--- a/src/i18n.tsx
+++ b/src/i18n.tsx
@@ -31,6 +31,8 @@ import * as React from "react";
 
 const jed = setupJed();
 
+let enableTracing = false;
+
 
 /**
  * Set up jed library for internationalization,
@@ -94,7 +96,7 @@ function stringifyChildren(children: any): string {
     return `%${n++}$s`;
   });
   const s = ss.join("").replace(/ +/g, " ").trim();
-  console.log("translation lookup", JSON.stringify(s));
+  enableTracing && console.log("translation lookup", JSON.stringify(s));
   return s;
 }
 
diff --git a/src/i18n/de.po b/src/i18n/de.po
index 6bfda670..fa55b7e9 100644
--- a/src/i18n/de.po
+++ b/src/i18n/de.po
@@ -37,28 +37,28 @@ msgstr ""
 msgid "time (ms/op)"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:78
+#: src/webex/pages/pay.tsx:78
 #, c-format
 msgid "show more details"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:92
+#: src/webex/pages/pay.tsx:92
 #, c-format
 msgid "Accepted exchanges:"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:97
+#: src/webex/pages/pay.tsx:97
 #, c-format
 msgid "Exchanges in the wallet:"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:219
+#: src/webex/pages/pay.tsx:219
 #, c-format
 msgid "You have insufficient funds of the requested currency in your wallet."
 msgstr ""
 
 #. tslint:disable-next-line:max-line-length
-#: src/webex/pages/confirm-contract.tsx:221
+#: src/webex/pages/pay.tsx:221
 #, c-format
 msgid ""
 "You do not have any funds from an exchange that is accepted by this "
@@ -66,180 +66,58 @@ msgid ""
 "wallet."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:322
+#: src/webex/pages/pay.tsx:322
 #, fuzzy, c-format
 msgid "Confirm payment"
 msgstr "Bezahlung bestätigen"
 
-#: src/webex/pages/confirm-contract.tsx:332
+#: src/webex/pages/pay.tsx:332
 #, fuzzy, c-format
 msgid "Submitting payment"
 msgstr "Bezahlung bestätigen"
 
-#: src/webex/pages/confirm-contract.tsx:343
+#: src/webex/pages/pay.tsx:343
 #, c-format
 msgid ""
 "You already paid for this, clicking \"Confirm payment\" will not cost money "
 "again."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:357
+#: src/webex/pages/pay.tsx:357
 #, fuzzy, c-format
 msgid "Aborting payment ..."
 msgstr "Bezahlung bestätigen"
 
-#: src/webex/pages/confirm-contract.tsx:359
+#: src/webex/pages/pay.tsx:359
 #, c-format
 msgid "Payment aborted!"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:362
+#: src/webex/pages/pay.tsx:362
 #, fuzzy, c-format
 msgid "Retry Payment"
 msgstr "Bezahlung bestätigen"
 
-#: src/webex/pages/confirm-contract.tsx:365
+#: src/webex/pages/pay.tsx:365
 #, fuzzy, c-format
 msgid "Abort Payment"
 msgstr "Bezahlung bestätigen"
 
-#: src/webex/pages/confirm-contract.tsx:374
+#: src/webex/pages/pay.tsx:374
 #, fuzzy, c-format
 msgid "The merchant %1$s offers you to purchase:"
 msgstr "Der Händler %1$s möchte einen Vertrag über %2$s mit Ihnen abschließen."
 
-#: src/webex/pages/confirm-contract.tsx:383
+#: src/webex/pages/pay.tsx:383
 #, c-format
 msgid "The total price is %1$s (plus %2$s fees)."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:387
+#: src/webex/pages/pay.tsx:387
 #, c-format
 msgid "The total price is %1$s."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:128
-#, c-format
-msgid "Select"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:145
-#, c-format
-msgid "Error: URL may not be relative"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:160
-#, c-format
-msgid "Invalid exchange URL (%1$s)"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:210
-#, c-format
-msgid "The exchange is trusted by the wallet."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:216
-#, c-format
-msgid "The exchange is audited by a trusted auditor."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:222
-#, c-format
-msgid ""
-"Warning: The exchange is neither directly trusted nor audited by a trusted "
-"auditor. If you withdraw from this exchange, it will be trusted in the "
-"future."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:231
-#, c-format
-msgid ""
-"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:243
-#, c-format
-msgid "Waiting for a response from %1$s %2$s"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:260
-#, c-format
-msgid ""
-"Information about fees will be available when an exchange provider is "
-"selected."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:279
-#, c-format
-msgid ""
-"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
-"a higher, incompatible protocol version (%3$s)."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:290
-#, c-format
-msgid ""
-"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
-"exchange has a lower, incompatible protocol version than your wallet "
-"(protocol version %3$s)."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:309
-#, c-format
-msgid "Accept fees and withdraw"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:314
-#, c-format
-msgid "Change Exchange Provider"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:335
-#, c-format
-msgid ""
-"Please select an exchange.  You can review the details before after your "
-"selection."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:341
-#: src/webex/pages/confirm-create-reserve.tsx:353
-#, c-format
-msgid "Select %1$s"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:370
-#, c-format
-msgid "You are about to withdraw %1$s from your bank account into your wallet."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:459
-#, c-format
-msgid ""
-"Oops, something went wrong. The wallet responded with error status (%1$s)."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:468
-#, c-format
-msgid "Checking URL, please wait ..."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:482
-#, c-format
-msgid "Can't parse amount: %1$s"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:489
-#, c-format
-msgid "Can't parse wire_types: %1$s"
-msgstr ""
-
-#. #-#-#-#-#  - (PACKAGE VERSION)  #-#-#-#-#
-#. TODO:generic error reporting function or component.
-#: src/webex/pages/confirm-create-reserve.tsx:519 src/webex/pages/tip.tsx:180
-#, c-format
-msgid "Fatal error: \"%1$s\"."
-msgstr ""
-
 #: src/webex/pages/popup.tsx:165
 #, c-format
 msgid "Balance"
@@ -379,6 +257,127 @@ msgstr "Bezahlung bestätigen"
 msgid "Cancel"
 msgstr "Saldo"
 
+#. #-#-#-#-#  - (PACKAGE VERSION)  #-#-#-#-#
+#. TODO:generic error reporting function or component.
+#: src/webex/pages/tip.tsx:180 src/webex/pages/withdraw.tsx:519
+#, c-format
+msgid "Fatal error: \"%1$s\"."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:128
+#, c-format
+msgid "Select"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:145
+#, c-format
+msgid "Error: URL may not be relative"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:160
+#, c-format
+msgid "Invalid exchange URL (%1$s)"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:210
+#, c-format
+msgid "The exchange is trusted by the wallet."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:216
+#, c-format
+msgid "The exchange is audited by a trusted auditor."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:222
+#, c-format
+msgid ""
+"Warning: The exchange is neither directly trusted nor audited by a trusted "
+"auditor. If you withdraw from this exchange, it will be trusted in the "
+"future."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:231
+#, c-format
+msgid ""
+"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:243
+#, c-format
+msgid "Waiting for a response from %1$s %2$s"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:260
+#, c-format
+msgid ""
+"Information about fees will be available when an exchange provider is "
+"selected."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:279
+#, c-format
+msgid ""
+"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
+"a higher, incompatible protocol version (%3$s)."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:290
+#, c-format
+msgid ""
+"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
+"exchange has a lower, incompatible protocol version than your wallet "
+"(protocol version %3$s)."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:309
+#, c-format
+msgid "Accept fees and withdraw"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:314
+#, c-format
+msgid "Change Exchange Provider"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:335
+#, c-format
+msgid ""
+"Please select an exchange.  You can review the details before after your "
+"selection."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:341 src/webex/pages/withdraw.tsx:353
+#, c-format
+msgid "Select %1$s"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:370
+#, c-format
+msgid "You are about to withdraw %1$s from your bank account into your wallet."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:459
+#, c-format
+msgid ""
+"Oops, something went wrong. The wallet responded with error status (%1$s)."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:468
+#, c-format
+msgid "Checking URL, please wait ..."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:482
+#, c-format
+msgid "Can't parse amount: %1$s"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:489
+#, c-format
+msgid "Can't parse wire_types: %1$s"
+msgstr ""
+
 #: src/webex/renderHtml.tsx:225
 #, fuzzy, c-format
 msgid "Withdrawal fees:"
diff --git a/src/i18n/en-US.po b/src/i18n/en-US.po
index 6d57e0ea..83f25dd3 100644
--- a/src/i18n/en-US.po
+++ b/src/i18n/en-US.po
@@ -37,28 +37,28 @@ msgstr ""
 msgid "time (ms/op)"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:78
+#: src/webex/pages/pay.tsx:78
 #, c-format
 msgid "show more details"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:92
+#: src/webex/pages/pay.tsx:92
 #, c-format
 msgid "Accepted exchanges:"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:97
+#: src/webex/pages/pay.tsx:97
 #, c-format
 msgid "Exchanges in the wallet:"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:219
+#: src/webex/pages/pay.tsx:219
 #, c-format
 msgid "You have insufficient funds of the requested currency in your wallet."
 msgstr ""
 
 #. tslint:disable-next-line:max-line-length
-#: src/webex/pages/confirm-contract.tsx:221
+#: src/webex/pages/pay.tsx:221
 #, c-format
 msgid ""
 "You do not have any funds from an exchange that is accepted by this "
@@ -66,308 +66,307 @@ msgid ""
 "wallet."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:322
+#: src/webex/pages/pay.tsx:322
 #, c-format
 msgid "Confirm payment"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:332
+#: src/webex/pages/pay.tsx:332
 #, c-format
 msgid "Submitting payment"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:343
+#: src/webex/pages/pay.tsx:343
 #, c-format
 msgid ""
 "You already paid for this, clicking \"Confirm payment\" will not cost money "
 "again."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:357
+#: src/webex/pages/pay.tsx:357
 #, c-format
 msgid "Aborting payment ..."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:359
+#: src/webex/pages/pay.tsx:359
 #, c-format
 msgid "Payment aborted!"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:362
+#: src/webex/pages/pay.tsx:362
 #, c-format
 msgid "Retry Payment"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:365
+#: src/webex/pages/pay.tsx:365
 #, c-format
 msgid "Abort Payment"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:374
+#: src/webex/pages/pay.tsx:374
 #, c-format
 msgid "The merchant %1$s offers you to purchase:"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:383
+#: src/webex/pages/pay.tsx:383
 #, c-format
 msgid "The total price is %1$s (plus %2$s fees)."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:387
+#: src/webex/pages/pay.tsx:387
 #, c-format
 msgid "The total price is %1$s."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:128
+#: src/webex/pages/popup.tsx:165
 #, c-format
-msgid "Select"
+msgid "Balance"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:145
+#: src/webex/pages/popup.tsx:168
 #, c-format
-msgid "Error: URL may not be relative"
+msgid "History"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:160
+#: src/webex/pages/popup.tsx:171
 #, c-format
-msgid "Invalid exchange URL (%1$s)"
+msgid "Debug"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:210
+#: src/webex/pages/popup.tsx:251
 #, c-format
-msgid "The exchange is trusted by the wallet."
+msgid "help"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:216
+#: src/webex/pages/popup.tsx:256
 #, c-format
-msgid "The exchange is audited by a trusted auditor."
+msgid "You have no balance to show. Need some %1$s getting started?"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:222
+#: src/webex/pages/popup.tsx:273
 #, c-format
-msgid ""
-"Warning: The exchange is neither directly trusted nor audited by a trusted "
-"auditor. If you withdraw from this exchange, it will be trusted in the "
-"future."
+msgid "%1$s incoming"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:231
+#: src/webex/pages/popup.tsx:286
 #, c-format
-msgid ""
-"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
+msgid "%1$s being spent"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:243
+#: src/webex/pages/popup.tsx:313
 #, c-format
-msgid "Waiting for a response from %1$s %2$s"
+msgid "Error: could not retrieve balance information."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:260
+#: src/webex/pages/popup.tsx:340
 #, c-format
-msgid ""
-"Information about fees will be available when an exchange provider is "
-"selected."
+msgid "Payback"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:279
+#: src/webex/pages/popup.tsx:341
 #, c-format
-msgid ""
-"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
-"a higher, incompatible protocol version (%3$s)."
+msgid "Return Electronic Cash to Bank Account"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:290
+#: src/webex/pages/popup.tsx:342
 #, c-format
-msgid ""
-"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
-"exchange has a lower, incompatible protocol version than your wallet "
-"(protocol version %3$s)."
+msgid "Manage Trusted Auditors and Exchanges"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:309
+#: src/webex/pages/popup.tsx:354
 #, c-format
-msgid "Accept fees and withdraw"
+msgid "Bank requested reserve (%1$s) for %2$s."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:314
+#: src/webex/pages/popup.tsx:364
 #, c-format
-msgid "Change Exchange Provider"
+msgid "Started to withdraw %1$s from %2$s (%3$s)."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:335
+#: src/webex/pages/popup.tsx:373
 #, c-format
-msgid ""
-"Please select an exchange.  You can review the details before after your "
-"selection."
+msgid "Merchant %1$s offered contract %2$s."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:341
-#: src/webex/pages/confirm-create-reserve.tsx:353
+#: src/webex/pages/popup.tsx:384
 #, c-format
-msgid "Select %1$s"
+msgid "Withdrew %1$s from %2$s (%3$s)."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:370
+#: src/webex/pages/popup.tsx:394
 #, c-format
-msgid "You are about to withdraw %1$s from your bank account into your wallet."
+msgid "Paid %1$s to merchant %2$s. %3$s (%4$s)"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:459
+#: src/webex/pages/popup.tsx:404
 #, c-format
-msgid ""
-"Oops, something went wrong. The wallet responded with error status (%1$s)."
+msgid "Merchant %1$s gave a refund over %2$s."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:468
+#: src/webex/pages/popup.tsx:414
 #, c-format
-msgid "Checking URL, please wait ..."
+msgid "tip"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:482
+#: src/webex/pages/popup.tsx:418
 #, c-format
-msgid "Can't parse amount: %1$s"
+msgid "Merchant %1$s gave a %2$s of %3$s."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:489
+#: src/webex/pages/popup.tsx:422
 #, c-format
-msgid "Can't parse wire_types: %1$s"
+msgid "You did not accept the tip yet."
 msgstr ""
 
-#. #-#-#-#-#  - (PACKAGE VERSION)  #-#-#-#-#
-#. TODO:generic error reporting function or component.
-#: src/webex/pages/confirm-create-reserve.tsx:519 src/webex/pages/tip.tsx:180
+#: src/webex/pages/popup.tsx:427
 #, c-format
-msgid "Fatal error: \"%1$s\"."
+msgid "Unknown event (%1$s)"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:165
+#: src/webex/pages/popup.tsx:470
 #, c-format
-msgid "Balance"
+msgid "Error: could not retrieve event history"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:168
+#: src/webex/pages/popup.tsx:495
 #, c-format
-msgid "History"
+msgid "Your wallet has no events recorded."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:171
+#: src/webex/pages/return-coins.tsx:105
 #, c-format
-msgid "Debug"
+msgid "Wire to bank account"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:251
+#: src/webex/pages/return-coins.tsx:173
 #, c-format
-msgid "help"
+msgid "Confirm"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:256
+#: src/webex/pages/return-coins.tsx:176
 #, c-format
-msgid "You have no balance to show. Need some %1$s getting started?"
+msgid "Cancel"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:273
+#. #-#-#-#-#  - (PACKAGE VERSION)  #-#-#-#-#
+#. TODO:generic error reporting function or component.
+#: src/webex/pages/tip.tsx:180 src/webex/pages/withdraw.tsx:519
 #, c-format
-msgid "%1$s incoming"
+msgid "Fatal error: \"%1$s\"."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:286
+#: src/webex/pages/withdraw.tsx:128
 #, c-format
-msgid "%1$s being spent"
+msgid "Select"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:313
+#: src/webex/pages/withdraw.tsx:145
 #, c-format
-msgid "Error: could not retrieve balance information."
+msgid "Error: URL may not be relative"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:340
+#: src/webex/pages/withdraw.tsx:160
 #, c-format
-msgid "Payback"
+msgid "Invalid exchange URL (%1$s)"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:341
+#: src/webex/pages/withdraw.tsx:210
 #, c-format
-msgid "Return Electronic Cash to Bank Account"
+msgid "The exchange is trusted by the wallet."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:342
+#: src/webex/pages/withdraw.tsx:216
 #, c-format
-msgid "Manage Trusted Auditors and Exchanges"
+msgid "The exchange is audited by a trusted auditor."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:354
+#: src/webex/pages/withdraw.tsx:222
 #, c-format
-msgid "Bank requested reserve (%1$s) for %2$s."
+msgid ""
+"Warning: The exchange is neither directly trusted nor audited by a trusted "
+"auditor. If you withdraw from this exchange, it will be trusted in the "
+"future."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:364
+#: src/webex/pages/withdraw.tsx:231
 #, c-format
-msgid "Started to withdraw %1$s from %2$s (%3$s)."
+msgid ""
+"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:373
+#: src/webex/pages/withdraw.tsx:243
 #, c-format
-msgid "Merchant %1$s offered contract %2$s."
+msgid "Waiting for a response from %1$s %2$s"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:384
+#: src/webex/pages/withdraw.tsx:260
 #, c-format
-msgid "Withdrew %1$s from %2$s (%3$s)."
+msgid ""
+"Information about fees will be available when an exchange provider is "
+"selected."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:394
+#: src/webex/pages/withdraw.tsx:279
 #, c-format
-msgid "Paid %1$s to merchant %2$s. %3$s (%4$s)"
+msgid ""
+"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
+"a higher, incompatible protocol version (%3$s)."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:404
+#: src/webex/pages/withdraw.tsx:290
 #, c-format
-msgid "Merchant %1$s gave a refund over %2$s."
+msgid ""
+"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
+"exchange has a lower, incompatible protocol version than your wallet "
+"(protocol version %3$s)."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:414
+#: src/webex/pages/withdraw.tsx:309
 #, c-format
-msgid "tip"
+msgid "Accept fees and withdraw"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:418
+#: src/webex/pages/withdraw.tsx:314
 #, c-format
-msgid "Merchant %1$s gave a %2$s of %3$s."
+msgid "Change Exchange Provider"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:422
+#: src/webex/pages/withdraw.tsx:335
 #, c-format
-msgid "You did not accept the tip yet."
+msgid ""
+"Please select an exchange.  You can review the details before after your "
+"selection."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:427
+#: src/webex/pages/withdraw.tsx:341 src/webex/pages/withdraw.tsx:353
 #, c-format
-msgid "Unknown event (%1$s)"
+msgid "Select %1$s"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:470
+#: src/webex/pages/withdraw.tsx:370
 #, c-format
-msgid "Error: could not retrieve event history"
+msgid "You are about to withdraw %1$s from your bank account into your wallet."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:495
+#: src/webex/pages/withdraw.tsx:459
 #, c-format
-msgid "Your wallet has no events recorded."
+msgid ""
+"Oops, something went wrong. The wallet responded with error status (%1$s)."
 msgstr ""
 
-#: src/webex/pages/return-coins.tsx:105
+#: src/webex/pages/withdraw.tsx:468
 #, c-format
-msgid "Wire to bank account"
+msgid "Checking URL, please wait ..."
 msgstr ""
 
-#: src/webex/pages/return-coins.tsx:173
+#: src/webex/pages/withdraw.tsx:482
 #, c-format
-msgid "Confirm"
+msgid "Can't parse amount: %1$s"
 msgstr ""
 
-#: src/webex/pages/return-coins.tsx:176
+#: src/webex/pages/withdraw.tsx:489
 #, c-format
-msgid "Cancel"
+msgid "Can't parse wire_types: %1$s"
 msgstr ""
 
 #: src/webex/renderHtml.tsx:225
diff --git a/src/i18n/fr.po b/src/i18n/fr.po
index e7615e41..1f0dc2a4 100644
--- a/src/i18n/fr.po
+++ b/src/i18n/fr.po
@@ -37,28 +37,28 @@ msgstr ""
 msgid "time (ms/op)"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:78
+#: src/webex/pages/pay.tsx:78
 #, c-format
 msgid "show more details"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:92
+#: src/webex/pages/pay.tsx:92
 #, c-format
 msgid "Accepted exchanges:"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:97
+#: src/webex/pages/pay.tsx:97
 #, c-format
 msgid "Exchanges in the wallet:"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:219
+#: src/webex/pages/pay.tsx:219
 #, c-format
 msgid "You have insufficient funds of the requested currency in your wallet."
 msgstr ""
 
 #. tslint:disable-next-line:max-line-length
-#: src/webex/pages/confirm-contract.tsx:221
+#: src/webex/pages/pay.tsx:221
 #, c-format
 msgid ""
 "You do not have any funds from an exchange that is accepted by this "
@@ -66,308 +66,307 @@ msgid ""
 "wallet."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:322
+#: src/webex/pages/pay.tsx:322
 #, c-format
 msgid "Confirm payment"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:332
+#: src/webex/pages/pay.tsx:332
 #, c-format
 msgid "Submitting payment"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:343
+#: src/webex/pages/pay.tsx:343
 #, c-format
 msgid ""
 "You already paid for this, clicking \"Confirm payment\" will not cost money "
 "again."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:357
+#: src/webex/pages/pay.tsx:357
 #, c-format
 msgid "Aborting payment ..."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:359
+#: src/webex/pages/pay.tsx:359
 #, c-format
 msgid "Payment aborted!"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:362
+#: src/webex/pages/pay.tsx:362
 #, c-format
 msgid "Retry Payment"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:365
+#: src/webex/pages/pay.tsx:365
 #, c-format
 msgid "Abort Payment"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:374
+#: src/webex/pages/pay.tsx:374
 #, c-format
 msgid "The merchant %1$s offers you to purchase:"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:383
+#: src/webex/pages/pay.tsx:383
 #, c-format
 msgid "The total price is %1$s (plus %2$s fees)."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:387
+#: src/webex/pages/pay.tsx:387
 #, c-format
 msgid "The total price is %1$s."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:128
+#: src/webex/pages/popup.tsx:165
 #, c-format
-msgid "Select"
+msgid "Balance"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:145
+#: src/webex/pages/popup.tsx:168
 #, c-format
-msgid "Error: URL may not be relative"
+msgid "History"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:160
+#: src/webex/pages/popup.tsx:171
 #, c-format
-msgid "Invalid exchange URL (%1$s)"
+msgid "Debug"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:210
+#: src/webex/pages/popup.tsx:251
 #, c-format
-msgid "The exchange is trusted by the wallet."
+msgid "help"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:216
+#: src/webex/pages/popup.tsx:256
 #, c-format
-msgid "The exchange is audited by a trusted auditor."
+msgid "You have no balance to show. Need some %1$s getting started?"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:222
+#: src/webex/pages/popup.tsx:273
 #, c-format
-msgid ""
-"Warning: The exchange is neither directly trusted nor audited by a trusted "
-"auditor. If you withdraw from this exchange, it will be trusted in the "
-"future."
+msgid "%1$s incoming"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:231
+#: src/webex/pages/popup.tsx:286
 #, c-format
-msgid ""
-"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
+msgid "%1$s being spent"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:243
+#: src/webex/pages/popup.tsx:313
 #, c-format
-msgid "Waiting for a response from %1$s %2$s"
+msgid "Error: could not retrieve balance information."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:260
+#: src/webex/pages/popup.tsx:340
 #, c-format
-msgid ""
-"Information about fees will be available when an exchange provider is "
-"selected."
+msgid "Payback"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:279
+#: src/webex/pages/popup.tsx:341
 #, c-format
-msgid ""
-"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
-"a higher, incompatible protocol version (%3$s)."
+msgid "Return Electronic Cash to Bank Account"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:290
+#: src/webex/pages/popup.tsx:342
 #, c-format
-msgid ""
-"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
-"exchange has a lower, incompatible protocol version than your wallet "
-"(protocol version %3$s)."
+msgid "Manage Trusted Auditors and Exchanges"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:309
+#: src/webex/pages/popup.tsx:354
 #, c-format
-msgid "Accept fees and withdraw"
+msgid "Bank requested reserve (%1$s) for %2$s."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:314
+#: src/webex/pages/popup.tsx:364
 #, c-format
-msgid "Change Exchange Provider"
+msgid "Started to withdraw %1$s from %2$s (%3$s)."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:335
+#: src/webex/pages/popup.tsx:373
 #, c-format
-msgid ""
-"Please select an exchange.  You can review the details before after your "
-"selection."
+msgid "Merchant %1$s offered contract %2$s."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:341
-#: src/webex/pages/confirm-create-reserve.tsx:353
+#: src/webex/pages/popup.tsx:384
 #, c-format
-msgid "Select %1$s"
+msgid "Withdrew %1$s from %2$s (%3$s)."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:370
+#: src/webex/pages/popup.tsx:394
 #, c-format
-msgid "You are about to withdraw %1$s from your bank account into your wallet."
+msgid "Paid %1$s to merchant %2$s. %3$s (%4$s)"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:459
+#: src/webex/pages/popup.tsx:404
 #, c-format
-msgid ""
-"Oops, something went wrong. The wallet responded with error status (%1$s)."
+msgid "Merchant %1$s gave a refund over %2$s."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:468
+#: src/webex/pages/popup.tsx:414
 #, c-format
-msgid "Checking URL, please wait ..."
+msgid "tip"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:482
+#: src/webex/pages/popup.tsx:418
 #, c-format
-msgid "Can't parse amount: %1$s"
+msgid "Merchant %1$s gave a %2$s of %3$s."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:489
+#: src/webex/pages/popup.tsx:422
 #, c-format
-msgid "Can't parse wire_types: %1$s"
+msgid "You did not accept the tip yet."
 msgstr ""
 
-#. #-#-#-#-#  - (PACKAGE VERSION)  #-#-#-#-#
-#. TODO:generic error reporting function or component.
-#: src/webex/pages/confirm-create-reserve.tsx:519 src/webex/pages/tip.tsx:180
+#: src/webex/pages/popup.tsx:427
 #, c-format
-msgid "Fatal error: \"%1$s\"."
+msgid "Unknown event (%1$s)"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:165
+#: src/webex/pages/popup.tsx:470
 #, c-format
-msgid "Balance"
+msgid "Error: could not retrieve event history"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:168
+#: src/webex/pages/popup.tsx:495
 #, c-format
-msgid "History"
+msgid "Your wallet has no events recorded."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:171
+#: src/webex/pages/return-coins.tsx:105
 #, c-format
-msgid "Debug"
+msgid "Wire to bank account"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:251
+#: src/webex/pages/return-coins.tsx:173
 #, c-format
-msgid "help"
+msgid "Confirm"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:256
+#: src/webex/pages/return-coins.tsx:176
 #, c-format
-msgid "You have no balance to show. Need some %1$s getting started?"
+msgid "Cancel"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:273
+#. #-#-#-#-#  - (PACKAGE VERSION)  #-#-#-#-#
+#. TODO:generic error reporting function or component.
+#: src/webex/pages/tip.tsx:180 src/webex/pages/withdraw.tsx:519
 #, c-format
-msgid "%1$s incoming"
+msgid "Fatal error: \"%1$s\"."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:286
+#: src/webex/pages/withdraw.tsx:128
 #, c-format
-msgid "%1$s being spent"
+msgid "Select"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:313
+#: src/webex/pages/withdraw.tsx:145
 #, c-format
-msgid "Error: could not retrieve balance information."
+msgid "Error: URL may not be relative"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:340
+#: src/webex/pages/withdraw.tsx:160
 #, c-format
-msgid "Payback"
+msgid "Invalid exchange URL (%1$s)"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:341
+#: src/webex/pages/withdraw.tsx:210
 #, c-format
-msgid "Return Electronic Cash to Bank Account"
+msgid "The exchange is trusted by the wallet."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:342
+#: src/webex/pages/withdraw.tsx:216
 #, c-format
-msgid "Manage Trusted Auditors and Exchanges"
+msgid "The exchange is audited by a trusted auditor."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:354
+#: src/webex/pages/withdraw.tsx:222
 #, c-format
-msgid "Bank requested reserve (%1$s) for %2$s."
+msgid ""
+"Warning: The exchange is neither directly trusted nor audited by a trusted "
+"auditor. If you withdraw from this exchange, it will be trusted in the "
+"future."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:364
+#: src/webex/pages/withdraw.tsx:231
 #, c-format
-msgid "Started to withdraw %1$s from %2$s (%3$s)."
+msgid ""
+"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:373
+#: src/webex/pages/withdraw.tsx:243
 #, c-format
-msgid "Merchant %1$s offered contract %2$s."
+msgid "Waiting for a response from %1$s %2$s"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:384
+#: src/webex/pages/withdraw.tsx:260
 #, c-format
-msgid "Withdrew %1$s from %2$s (%3$s)."
+msgid ""
+"Information about fees will be available when an exchange provider is "
+"selected."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:394
+#: src/webex/pages/withdraw.tsx:279
 #, c-format
-msgid "Paid %1$s to merchant %2$s. %3$s (%4$s)"
+msgid ""
+"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
+"a higher, incompatible protocol version (%3$s)."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:404
+#: src/webex/pages/withdraw.tsx:290
 #, c-format
-msgid "Merchant %1$s gave a refund over %2$s."
+msgid ""
+"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
+"exchange has a lower, incompatible protocol version than your wallet "
+"(protocol version %3$s)."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:414
+#: src/webex/pages/withdraw.tsx:309
 #, c-format
-msgid "tip"
+msgid "Accept fees and withdraw"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:418
+#: src/webex/pages/withdraw.tsx:314
 #, c-format
-msgid "Merchant %1$s gave a %2$s of %3$s."
+msgid "Change Exchange Provider"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:422
+#: src/webex/pages/withdraw.tsx:335
 #, c-format
-msgid "You did not accept the tip yet."
+msgid ""
+"Please select an exchange.  You can review the details before after your "
+"selection."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:427
+#: src/webex/pages/withdraw.tsx:341 src/webex/pages/withdraw.tsx:353
 #, c-format
-msgid "Unknown event (%1$s)"
+msgid "Select %1$s"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:470
+#: src/webex/pages/withdraw.tsx:370
 #, c-format
-msgid "Error: could not retrieve event history"
+msgid "You are about to withdraw %1$s from your bank account into your wallet."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:495
+#: src/webex/pages/withdraw.tsx:459
 #, c-format
-msgid "Your wallet has no events recorded."
+msgid ""
+"Oops, something went wrong. The wallet responded with error status (%1$s)."
 msgstr ""
 
-#: src/webex/pages/return-coins.tsx:105
+#: src/webex/pages/withdraw.tsx:468
 #, c-format
-msgid "Wire to bank account"
+msgid "Checking URL, please wait ..."
 msgstr ""
 
-#: src/webex/pages/return-coins.tsx:173
+#: src/webex/pages/withdraw.tsx:482
 #, c-format
-msgid "Confirm"
+msgid "Can't parse amount: %1$s"
 msgstr ""
 
-#: src/webex/pages/return-coins.tsx:176
+#: src/webex/pages/withdraw.tsx:489
 #, c-format
-msgid "Cancel"
+msgid "Can't parse wire_types: %1$s"
 msgstr ""
 
 #: src/webex/renderHtml.tsx:225
diff --git a/src/i18n/it.po b/src/i18n/it.po
index e7615e41..1f0dc2a4 100644
--- a/src/i18n/it.po
+++ b/src/i18n/it.po
@@ -37,28 +37,28 @@ msgstr ""
 msgid "time (ms/op)"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:78
+#: src/webex/pages/pay.tsx:78
 #, c-format
 msgid "show more details"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:92
+#: src/webex/pages/pay.tsx:92
 #, c-format
 msgid "Accepted exchanges:"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:97
+#: src/webex/pages/pay.tsx:97
 #, c-format
 msgid "Exchanges in the wallet:"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:219
+#: src/webex/pages/pay.tsx:219
 #, c-format
 msgid "You have insufficient funds of the requested currency in your wallet."
 msgstr ""
 
 #. tslint:disable-next-line:max-line-length
-#: src/webex/pages/confirm-contract.tsx:221
+#: src/webex/pages/pay.tsx:221
 #, c-format
 msgid ""
 "You do not have any funds from an exchange that is accepted by this "
@@ -66,308 +66,307 @@ msgid ""
 "wallet."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:322
+#: src/webex/pages/pay.tsx:322
 #, c-format
 msgid "Confirm payment"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:332
+#: src/webex/pages/pay.tsx:332
 #, c-format
 msgid "Submitting payment"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:343
+#: src/webex/pages/pay.tsx:343
 #, c-format
 msgid ""
 "You already paid for this, clicking \"Confirm payment\" will not cost money "
 "again."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:357
+#: src/webex/pages/pay.tsx:357
 #, c-format
 msgid "Aborting payment ..."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:359
+#: src/webex/pages/pay.tsx:359
 #, c-format
 msgid "Payment aborted!"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:362
+#: src/webex/pages/pay.tsx:362
 #, c-format
 msgid "Retry Payment"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:365
+#: src/webex/pages/pay.tsx:365
 #, c-format
 msgid "Abort Payment"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:374
+#: src/webex/pages/pay.tsx:374
 #, c-format
 msgid "The merchant %1$s offers you to purchase:"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:383
+#: src/webex/pages/pay.tsx:383
 #, c-format
 msgid "The total price is %1$s (plus %2$s fees)."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:387
+#: src/webex/pages/pay.tsx:387
 #, c-format
 msgid "The total price is %1$s."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:128
+#: src/webex/pages/popup.tsx:165
 #, c-format
-msgid "Select"
+msgid "Balance"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:145
+#: src/webex/pages/popup.tsx:168
 #, c-format
-msgid "Error: URL may not be relative"
+msgid "History"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:160
+#: src/webex/pages/popup.tsx:171
 #, c-format
-msgid "Invalid exchange URL (%1$s)"
+msgid "Debug"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:210
+#: src/webex/pages/popup.tsx:251
 #, c-format
-msgid "The exchange is trusted by the wallet."
+msgid "help"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:216
+#: src/webex/pages/popup.tsx:256
 #, c-format
-msgid "The exchange is audited by a trusted auditor."
+msgid "You have no balance to show. Need some %1$s getting started?"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:222
+#: src/webex/pages/popup.tsx:273
 #, c-format
-msgid ""
-"Warning: The exchange is neither directly trusted nor audited by a trusted "
-"auditor. If you withdraw from this exchange, it will be trusted in the "
-"future."
+msgid "%1$s incoming"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:231
+#: src/webex/pages/popup.tsx:286
 #, c-format
-msgid ""
-"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
+msgid "%1$s being spent"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:243
+#: src/webex/pages/popup.tsx:313
 #, c-format
-msgid "Waiting for a response from %1$s %2$s"
+msgid "Error: could not retrieve balance information."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:260
+#: src/webex/pages/popup.tsx:340
 #, c-format
-msgid ""
-"Information about fees will be available when an exchange provider is "
-"selected."
+msgid "Payback"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:279
+#: src/webex/pages/popup.tsx:341
 #, c-format
-msgid ""
-"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
-"a higher, incompatible protocol version (%3$s)."
+msgid "Return Electronic Cash to Bank Account"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:290
+#: src/webex/pages/popup.tsx:342
 #, c-format
-msgid ""
-"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
-"exchange has a lower, incompatible protocol version than your wallet "
-"(protocol version %3$s)."
+msgid "Manage Trusted Auditors and Exchanges"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:309
+#: src/webex/pages/popup.tsx:354
 #, c-format
-msgid "Accept fees and withdraw"
+msgid "Bank requested reserve (%1$s) for %2$s."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:314
+#: src/webex/pages/popup.tsx:364
 #, c-format
-msgid "Change Exchange Provider"
+msgid "Started to withdraw %1$s from %2$s (%3$s)."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:335
+#: src/webex/pages/popup.tsx:373
 #, c-format
-msgid ""
-"Please select an exchange.  You can review the details before after your "
-"selection."
+msgid "Merchant %1$s offered contract %2$s."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:341
-#: src/webex/pages/confirm-create-reserve.tsx:353
+#: src/webex/pages/popup.tsx:384
 #, c-format
-msgid "Select %1$s"
+msgid "Withdrew %1$s from %2$s (%3$s)."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:370
+#: src/webex/pages/popup.tsx:394
 #, c-format
-msgid "You are about to withdraw %1$s from your bank account into your wallet."
+msgid "Paid %1$s to merchant %2$s. %3$s (%4$s)"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:459
+#: src/webex/pages/popup.tsx:404
 #, c-format
-msgid ""
-"Oops, something went wrong. The wallet responded with error status (%1$s)."
+msgid "Merchant %1$s gave a refund over %2$s."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:468
+#: src/webex/pages/popup.tsx:414
 #, c-format
-msgid "Checking URL, please wait ..."
+msgid "tip"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:482
+#: src/webex/pages/popup.tsx:418
 #, c-format
-msgid "Can't parse amount: %1$s"
+msgid "Merchant %1$s gave a %2$s of %3$s."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:489
+#: src/webex/pages/popup.tsx:422
 #, c-format
-msgid "Can't parse wire_types: %1$s"
+msgid "You did not accept the tip yet."
 msgstr ""
 
-#. #-#-#-#-#  - (PACKAGE VERSION)  #-#-#-#-#
-#. TODO:generic error reporting function or component.
-#: src/webex/pages/confirm-create-reserve.tsx:519 src/webex/pages/tip.tsx:180
+#: src/webex/pages/popup.tsx:427
 #, c-format
-msgid "Fatal error: \"%1$s\"."
+msgid "Unknown event (%1$s)"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:165
+#: src/webex/pages/popup.tsx:470
 #, c-format
-msgid "Balance"
+msgid "Error: could not retrieve event history"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:168
+#: src/webex/pages/popup.tsx:495
 #, c-format
-msgid "History"
+msgid "Your wallet has no events recorded."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:171
+#: src/webex/pages/return-coins.tsx:105
 #, c-format
-msgid "Debug"
+msgid "Wire to bank account"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:251
+#: src/webex/pages/return-coins.tsx:173
 #, c-format
-msgid "help"
+msgid "Confirm"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:256
+#: src/webex/pages/return-coins.tsx:176
 #, c-format
-msgid "You have no balance to show. Need some %1$s getting started?"
+msgid "Cancel"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:273
+#. #-#-#-#-#  - (PACKAGE VERSION)  #-#-#-#-#
+#. TODO:generic error reporting function or component.
+#: src/webex/pages/tip.tsx:180 src/webex/pages/withdraw.tsx:519
 #, c-format
-msgid "%1$s incoming"
+msgid "Fatal error: \"%1$s\"."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:286
+#: src/webex/pages/withdraw.tsx:128
 #, c-format
-msgid "%1$s being spent"
+msgid "Select"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:313
+#: src/webex/pages/withdraw.tsx:145
 #, c-format
-msgid "Error: could not retrieve balance information."
+msgid "Error: URL may not be relative"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:340
+#: src/webex/pages/withdraw.tsx:160
 #, c-format
-msgid "Payback"
+msgid "Invalid exchange URL (%1$s)"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:341
+#: src/webex/pages/withdraw.tsx:210
 #, c-format
-msgid "Return Electronic Cash to Bank Account"
+msgid "The exchange is trusted by the wallet."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:342
+#: src/webex/pages/withdraw.tsx:216
 #, c-format
-msgid "Manage Trusted Auditors and Exchanges"
+msgid "The exchange is audited by a trusted auditor."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:354
+#: src/webex/pages/withdraw.tsx:222
 #, c-format
-msgid "Bank requested reserve (%1$s) for %2$s."
+msgid ""
+"Warning: The exchange is neither directly trusted nor audited by a trusted "
+"auditor. If you withdraw from this exchange, it will be trusted in the "
+"future."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:364
+#: src/webex/pages/withdraw.tsx:231
 #, c-format
-msgid "Started to withdraw %1$s from %2$s (%3$s)."
+msgid ""
+"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:373
+#: src/webex/pages/withdraw.tsx:243
 #, c-format
-msgid "Merchant %1$s offered contract %2$s."
+msgid "Waiting for a response from %1$s %2$s"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:384
+#: src/webex/pages/withdraw.tsx:260
 #, c-format
-msgid "Withdrew %1$s from %2$s (%3$s)."
+msgid ""
+"Information about fees will be available when an exchange provider is "
+"selected."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:394
+#: src/webex/pages/withdraw.tsx:279
 #, c-format
-msgid "Paid %1$s to merchant %2$s. %3$s (%4$s)"
+msgid ""
+"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
+"a higher, incompatible protocol version (%3$s)."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:404
+#: src/webex/pages/withdraw.tsx:290
 #, c-format
-msgid "Merchant %1$s gave a refund over %2$s."
+msgid ""
+"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
+"exchange has a lower, incompatible protocol version than your wallet "
+"(protocol version %3$s)."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:414
+#: src/webex/pages/withdraw.tsx:309
 #, c-format
-msgid "tip"
+msgid "Accept fees and withdraw"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:418
+#: src/webex/pages/withdraw.tsx:314
 #, c-format
-msgid "Merchant %1$s gave a %2$s of %3$s."
+msgid "Change Exchange Provider"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:422
+#: src/webex/pages/withdraw.tsx:335
 #, c-format
-msgid "You did not accept the tip yet."
+msgid ""
+"Please select an exchange.  You can review the details before after your "
+"selection."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:427
+#: src/webex/pages/withdraw.tsx:341 src/webex/pages/withdraw.tsx:353
 #, c-format
-msgid "Unknown event (%1$s)"
+msgid "Select %1$s"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:470
+#: src/webex/pages/withdraw.tsx:370
 #, c-format
-msgid "Error: could not retrieve event history"
+msgid "You are about to withdraw %1$s from your bank account into your wallet."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:495
+#: src/webex/pages/withdraw.tsx:459
 #, c-format
-msgid "Your wallet has no events recorded."
+msgid ""
+"Oops, something went wrong. The wallet responded with error status (%1$s)."
 msgstr ""
 
-#: src/webex/pages/return-coins.tsx:105
+#: src/webex/pages/withdraw.tsx:468
 #, c-format
-msgid "Wire to bank account"
+msgid "Checking URL, please wait ..."
 msgstr ""
 
-#: src/webex/pages/return-coins.tsx:173
+#: src/webex/pages/withdraw.tsx:482
 #, c-format
-msgid "Confirm"
+msgid "Can't parse amount: %1$s"
 msgstr ""
 
-#: src/webex/pages/return-coins.tsx:176
+#: src/webex/pages/withdraw.tsx:489
 #, c-format
-msgid "Cancel"
+msgid "Can't parse wire_types: %1$s"
 msgstr ""
 
 #: src/webex/renderHtml.tsx:225
diff --git a/src/i18n/strings.ts b/src/i18n/strings.ts
index 9c2947c6..066becf1 100644
--- a/src/i18n/strings.ts
+++ b/src/i18n/strings.ts
@@ -92,193 +92,193 @@ strings['de'] = {
         null,
         ""
       ],
-      "Select": [
+      "Balance": [
         null,
-        ""
+        "Saldo"
       ],
-      "Error: URL may not be relative": [
+      "History": [
         null,
-        ""
+        "Verlauf"
       ],
-      "Invalid exchange URL (%1$s)": [
+      "Debug": [
         null,
-        ""
+        "Debug"
       ],
-      "The exchange is trusted by the wallet.": [
+      "help": [
         null,
         ""
       ],
-      "The exchange is audited by a trusted auditor.": [
+      "You have no balance to show. Need some %1$s getting started?": [
         null,
-        ""
+        "Sie haben kein Digitalgeld. Wollen Sie %1$s? abheben?"
       ],
-      "Warning: The exchange is neither directly trusted nor audited by a 
trusted auditor. If you withdraw from this exchange, it will be trusted in the 
future.": [
+      "%1$s incoming": [
         null,
         ""
       ],
-      "Using exchange provider %1$s. The exchange provider will charge %2$s in 
fees.": [
+      "%1$s being spent": [
         null,
         ""
       ],
-      "Waiting for a response from %1$s %2$s": [
+      "Error: could not retrieve balance information.": [
         null,
         ""
       ],
-      "Information about fees will be available when an exchange provider is 
selected.": [
+      "Payback": [
         null,
         ""
       ],
-      "Your wallet (protocol version %1$s) might be outdated.%2$s The exchange 
has a higher, incompatible protocol version (%3$s).": [
+      "Return Electronic Cash to Bank Account": [
         null,
         ""
       ],
-      "The chosen exchange (protocol version %1$s might be outdated.%2$s The 
exchange has a lower, incompatible protocol version than your wallet (protocol 
version %3$s).": [
+      "Manage Trusted Auditors and Exchanges": [
         null,
         ""
       ],
-      "Accept fees and withdraw": [
+      "Bank requested reserve (%1$s) for %2$s.": [
         null,
-        ""
+        "Bank bestätig anlegen der Reserve (%1$s) bei %2$s"
       ],
-      "Change Exchange Provider": [
+      "Started to withdraw %1$s from %2$s (%3$s).": [
         null,
-        ""
+        "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
       ],
-      "Please select an exchange.  You can review the details before after 
your selection.": [
+      "Merchant %1$s offered contract %2$s.": [
         null,
-        ""
+        "%1$s\n               möchte einen Vertrag über %2$s\n               
mit Ihnen abschließen."
       ],
-      "Select %1$s": [
+      "Withdrew %1$s from %2$s (%3$s).": [
         null,
-        ""
+        "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
       ],
-      "You are about to withdraw %1$s from your bank account into your 
wallet.": [
+      "Paid %1$s to merchant %2$s. %3$s (%4$s)": [
         null,
-        ""
+        "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
       ],
-      "Oops, something went wrong. The wallet responded with error status 
(%1$s).": [
+      "Merchant %1$s gave a refund over %2$s.": [
         null,
-        ""
+        "%1$s\n               möchte einen Vertrag über %2$s\n               
mit Ihnen abschließen."
       ],
-      "Checking URL, please wait ...": [
+      "tip": [
         null,
         ""
       ],
-      "Can't parse amount: %1$s": [
+      "Merchant %1$s gave a %2$s of %3$s.": [
         null,
-        ""
+        "%1$s\n               möchte einen Vertrag über %2$s\n               
mit Ihnen abschließen."
       ],
-      "Can't parse wire_types: %1$s": [
+      "You did not accept the tip yet.": [
         null,
         ""
       ],
-      "Fatal error: \"%1$s\".": [
+      "Unknown event (%1$s)": [
         null,
         ""
       ],
-      "Balance": [
+      "Error: could not retrieve event history": [
         null,
-        "Saldo"
+        ""
       ],
-      "History": [
+      "Your wallet has no events recorded.": [
         null,
-        "Verlauf"
+        "Ihre Geldbörse verzeichnet keine Vorkommnisse."
       ],
-      "Debug": [
+      "Wire to bank account": [
         null,
-        "Debug"
+        ""
       ],
-      "help": [
+      "Confirm": [
         null,
-        ""
+        "Bezahlung bestätigen"
       ],
-      "You have no balance to show. Need some %1$s getting started?": [
+      "Cancel": [
         null,
-        "Sie haben kein Digitalgeld. Wollen Sie %1$s? abheben?"
+        "Saldo"
       ],
-      "%1$s incoming": [
+      "Fatal error: \"%1$s\".": [
         null,
         ""
       ],
-      "%1$s being spent": [
+      "Select": [
         null,
         ""
       ],
-      "Error: could not retrieve balance information.": [
+      "Error: URL may not be relative": [
         null,
         ""
       ],
-      "Payback": [
+      "Invalid exchange URL (%1$s)": [
         null,
         ""
       ],
-      "Return Electronic Cash to Bank Account": [
+      "The exchange is trusted by the wallet.": [
         null,
         ""
       ],
-      "Manage Trusted Auditors and Exchanges": [
+      "The exchange is audited by a trusted auditor.": [
         null,
         ""
       ],
-      "Bank requested reserve (%1$s) for %2$s.": [
+      "Warning: The exchange is neither directly trusted nor audited by a 
trusted auditor. If you withdraw from this exchange, it will be trusted in the 
future.": [
         null,
-        "Bank bestätig anlegen der Reserve (%1$s) bei %2$s"
+        ""
       ],
-      "Started to withdraw %1$s from %2$s (%3$s).": [
+      "Using exchange provider %1$s. The exchange provider will charge %2$s in 
fees.": [
         null,
-        "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
+        ""
       ],
-      "Merchant %1$s offered contract %2$s.": [
+      "Waiting for a response from %1$s %2$s": [
         null,
-        "%1$s\n               möchte einen Vertrag über %2$s\n               
mit Ihnen abschließen."
+        ""
       ],
-      "Withdrew %1$s from %2$s (%3$s).": [
+      "Information about fees will be available when an exchange provider is 
selected.": [
         null,
-        "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
+        ""
       ],
-      "Paid %1$s to merchant %2$s. %3$s (%4$s)": [
+      "Your wallet (protocol version %1$s) might be outdated.%2$s The exchange 
has a higher, incompatible protocol version (%3$s).": [
         null,
-        "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
+        ""
       ],
-      "Merchant %1$s gave a refund over %2$s.": [
+      "The chosen exchange (protocol version %1$s might be outdated.%2$s The 
exchange has a lower, incompatible protocol version than your wallet (protocol 
version %3$s).": [
         null,
-        "%1$s\n               möchte einen Vertrag über %2$s\n               
mit Ihnen abschließen."
+        ""
       ],
-      "tip": [
+      "Accept fees and withdraw": [
         null,
         ""
       ],
-      "Merchant %1$s gave a %2$s of %3$s.": [
+      "Change Exchange Provider": [
         null,
-        "%1$s\n               möchte einen Vertrag über %2$s\n               
mit Ihnen abschließen."
+        ""
       ],
-      "You did not accept the tip yet.": [
+      "Please select an exchange.  You can review the details before after 
your selection.": [
         null,
         ""
       ],
-      "Unknown event (%1$s)": [
+      "Select %1$s": [
         null,
         ""
       ],
-      "Error: could not retrieve event history": [
+      "You are about to withdraw %1$s from your bank account into your 
wallet.": [
         null,
         ""
       ],
-      "Your wallet has no events recorded.": [
+      "Oops, something went wrong. The wallet responded with error status 
(%1$s).": [
         null,
-        "Ihre Geldbörse verzeichnet keine Vorkommnisse."
+        ""
       ],
-      "Wire to bank account": [
+      "Checking URL, please wait ...": [
         null,
         ""
       ],
-      "Confirm": [
+      "Can't parse amount: %1$s": [
         null,
-        "Bezahlung bestätigen"
+        ""
       ],
-      "Cancel": [
+      "Can't parse wire_types: %1$s": [
         null,
-        "Saldo"
+        ""
       ],
       "Withdrawal fees:": [
         null,
@@ -408,191 +408,191 @@ strings['en-US'] = {
         null,
         ""
       ],
-      "Select": [
+      "Balance": [
         null,
         ""
       ],
-      "Error: URL may not be relative": [
+      "History": [
         null,
         ""
       ],
-      "Invalid exchange URL (%1$s)": [
+      "Debug": [
         null,
         ""
       ],
-      "The exchange is trusted by the wallet.": [
+      "help": [
         null,
         ""
       ],
-      "The exchange is audited by a trusted auditor.": [
+      "You have no balance to show. Need some %1$s getting started?": [
         null,
         ""
       ],
-      "Warning: The exchange is neither directly trusted nor audited by a 
trusted auditor. If you withdraw from this exchange, it will be trusted in the 
future.": [
+      "%1$s incoming": [
         null,
         ""
       ],
-      "Using exchange provider %1$s. The exchange provider will charge %2$s in 
fees.": [
+      "%1$s being spent": [
         null,
         ""
       ],
-      "Waiting for a response from %1$s %2$s": [
+      "Error: could not retrieve balance information.": [
         null,
         ""
       ],
-      "Information about fees will be available when an exchange provider is 
selected.": [
+      "Payback": [
         null,
         ""
       ],
-      "Your wallet (protocol version %1$s) might be outdated.%2$s The exchange 
has a higher, incompatible protocol version (%3$s).": [
+      "Return Electronic Cash to Bank Account": [
         null,
         ""
       ],
-      "The chosen exchange (protocol version %1$s might be outdated.%2$s The 
exchange has a lower, incompatible protocol version than your wallet (protocol 
version %3$s).": [
+      "Manage Trusted Auditors and Exchanges": [
         null,
         ""
       ],
-      "Accept fees and withdraw": [
+      "Bank requested reserve (%1$s) for %2$s.": [
         null,
         ""
       ],
-      "Change Exchange Provider": [
+      "Started to withdraw %1$s from %2$s (%3$s).": [
         null,
         ""
       ],
-      "Please select an exchange.  You can review the details before after 
your selection.": [
+      "Merchant %1$s offered contract %2$s.": [
         null,
         ""
       ],
-      "Select %1$s": [
+      "Withdrew %1$s from %2$s (%3$s).": [
         null,
         ""
       ],
-      "You are about to withdraw %1$s from your bank account into your 
wallet.": [
+      "Paid %1$s to merchant %2$s. %3$s (%4$s)": [
         null,
         ""
       ],
-      "Oops, something went wrong. The wallet responded with error status 
(%1$s).": [
+      "Merchant %1$s gave a refund over %2$s.": [
         null,
         ""
       ],
-      "Checking URL, please wait ...": [
+      "tip": [
         null,
         ""
       ],
-      "Can't parse amount: %1$s": [
+      "Merchant %1$s gave a %2$s of %3$s.": [
         null,
         ""
       ],
-      "Can't parse wire_types: %1$s": [
+      "You did not accept the tip yet.": [
         null,
         ""
       ],
-      "Fatal error: \"%1$s\".": [
+      "Unknown event (%1$s)": [
         null,
         ""
       ],
-      "Balance": [
+      "Error: could not retrieve event history": [
         null,
         ""
       ],
-      "History": [
+      "Your wallet has no events recorded.": [
         null,
         ""
       ],
-      "Debug": [
+      "Wire to bank account": [
         null,
         ""
       ],
-      "help": [
+      "Confirm": [
         null,
         ""
       ],
-      "You have no balance to show. Need some %1$s getting started?": [
+      "Cancel": [
         null,
         ""
       ],
-      "%1$s incoming": [
+      "Fatal error: \"%1$s\".": [
         null,
         ""
       ],
-      "%1$s being spent": [
+      "Select": [
         null,
         ""
       ],
-      "Error: could not retrieve balance information.": [
+      "Error: URL may not be relative": [
         null,
         ""
       ],
-      "Payback": [
+      "Invalid exchange URL (%1$s)": [
         null,
         ""
       ],
-      "Return Electronic Cash to Bank Account": [
+      "The exchange is trusted by the wallet.": [
         null,
         ""
       ],
-      "Manage Trusted Auditors and Exchanges": [
+      "The exchange is audited by a trusted auditor.": [
         null,
         ""
       ],
-      "Bank requested reserve (%1$s) for %2$s.": [
+      "Warning: The exchange is neither directly trusted nor audited by a 
trusted auditor. If you withdraw from this exchange, it will be trusted in the 
future.": [
         null,
         ""
       ],
-      "Started to withdraw %1$s from %2$s (%3$s).": [
+      "Using exchange provider %1$s. The exchange provider will charge %2$s in 
fees.": [
         null,
         ""
       ],
-      "Merchant %1$s offered contract %2$s.": [
+      "Waiting for a response from %1$s %2$s": [
         null,
         ""
       ],
-      "Withdrew %1$s from %2$s (%3$s).": [
+      "Information about fees will be available when an exchange provider is 
selected.": [
         null,
         ""
       ],
-      "Paid %1$s to merchant %2$s. %3$s (%4$s)": [
+      "Your wallet (protocol version %1$s) might be outdated.%2$s The exchange 
has a higher, incompatible protocol version (%3$s).": [
         null,
         ""
       ],
-      "Merchant %1$s gave a refund over %2$s.": [
+      "The chosen exchange (protocol version %1$s might be outdated.%2$s The 
exchange has a lower, incompatible protocol version than your wallet (protocol 
version %3$s).": [
         null,
         ""
       ],
-      "tip": [
+      "Accept fees and withdraw": [
         null,
         ""
       ],
-      "Merchant %1$s gave a %2$s of %3$s.": [
+      "Change Exchange Provider": [
         null,
         ""
       ],
-      "You did not accept the tip yet.": [
+      "Please select an exchange.  You can review the details before after 
your selection.": [
         null,
         ""
       ],
-      "Unknown event (%1$s)": [
+      "Select %1$s": [
         null,
         ""
       ],
-      "Error: could not retrieve event history": [
+      "You are about to withdraw %1$s from your bank account into your 
wallet.": [
         null,
         ""
       ],
-      "Your wallet has no events recorded.": [
+      "Oops, something went wrong. The wallet responded with error status 
(%1$s).": [
         null,
         ""
       ],
-      "Wire to bank account": [
+      "Checking URL, please wait ...": [
         null,
         ""
       ],
-      "Confirm": [
+      "Can't parse amount: %1$s": [
         null,
         ""
       ],
-      "Cancel": [
+      "Can't parse wire_types: %1$s": [
         null,
         ""
       ],
@@ -724,191 +724,191 @@ strings['fr'] = {
         null,
         ""
       ],
-      "Select": [
+      "Balance": [
         null,
         ""
       ],
-      "Error: URL may not be relative": [
+      "History": [
         null,
         ""
       ],
-      "Invalid exchange URL (%1$s)": [
+      "Debug": [
         null,
         ""
       ],
-      "The exchange is trusted by the wallet.": [
+      "help": [
         null,
         ""
       ],
-      "The exchange is audited by a trusted auditor.": [
+      "You have no balance to show. Need some %1$s getting started?": [
         null,
         ""
       ],
-      "Warning: The exchange is neither directly trusted nor audited by a 
trusted auditor. If you withdraw from this exchange, it will be trusted in the 
future.": [
+      "%1$s incoming": [
         null,
         ""
       ],
-      "Using exchange provider %1$s. The exchange provider will charge %2$s in 
fees.": [
+      "%1$s being spent": [
         null,
         ""
       ],
-      "Waiting for a response from %1$s %2$s": [
+      "Error: could not retrieve balance information.": [
         null,
         ""
       ],
-      "Information about fees will be available when an exchange provider is 
selected.": [
+      "Payback": [
         null,
         ""
       ],
-      "Your wallet (protocol version %1$s) might be outdated.%2$s The exchange 
has a higher, incompatible protocol version (%3$s).": [
+      "Return Electronic Cash to Bank Account": [
         null,
         ""
       ],
-      "The chosen exchange (protocol version %1$s might be outdated.%2$s The 
exchange has a lower, incompatible protocol version than your wallet (protocol 
version %3$s).": [
+      "Manage Trusted Auditors and Exchanges": [
         null,
         ""
       ],
-      "Accept fees and withdraw": [
+      "Bank requested reserve (%1$s) for %2$s.": [
         null,
         ""
       ],
-      "Change Exchange Provider": [
+      "Started to withdraw %1$s from %2$s (%3$s).": [
         null,
         ""
       ],
-      "Please select an exchange.  You can review the details before after 
your selection.": [
+      "Merchant %1$s offered contract %2$s.": [
         null,
         ""
       ],
-      "Select %1$s": [
+      "Withdrew %1$s from %2$s (%3$s).": [
         null,
         ""
       ],
-      "You are about to withdraw %1$s from your bank account into your 
wallet.": [
+      "Paid %1$s to merchant %2$s. %3$s (%4$s)": [
         null,
         ""
       ],
-      "Oops, something went wrong. The wallet responded with error status 
(%1$s).": [
+      "Merchant %1$s gave a refund over %2$s.": [
         null,
         ""
       ],
-      "Checking URL, please wait ...": [
+      "tip": [
         null,
         ""
       ],
-      "Can't parse amount: %1$s": [
+      "Merchant %1$s gave a %2$s of %3$s.": [
         null,
         ""
       ],
-      "Can't parse wire_types: %1$s": [
+      "You did not accept the tip yet.": [
         null,
         ""
       ],
-      "Fatal error: \"%1$s\".": [
+      "Unknown event (%1$s)": [
         null,
         ""
       ],
-      "Balance": [
+      "Error: could not retrieve event history": [
         null,
         ""
       ],
-      "History": [
+      "Your wallet has no events recorded.": [
         null,
         ""
       ],
-      "Debug": [
+      "Wire to bank account": [
         null,
         ""
       ],
-      "help": [
+      "Confirm": [
         null,
         ""
       ],
-      "You have no balance to show. Need some %1$s getting started?": [
+      "Cancel": [
         null,
         ""
       ],
-      "%1$s incoming": [
+      "Fatal error: \"%1$s\".": [
         null,
         ""
       ],
-      "%1$s being spent": [
+      "Select": [
         null,
         ""
       ],
-      "Error: could not retrieve balance information.": [
+      "Error: URL may not be relative": [
         null,
         ""
       ],
-      "Payback": [
+      "Invalid exchange URL (%1$s)": [
         null,
         ""
       ],
-      "Return Electronic Cash to Bank Account": [
+      "The exchange is trusted by the wallet.": [
         null,
         ""
       ],
-      "Manage Trusted Auditors and Exchanges": [
+      "The exchange is audited by a trusted auditor.": [
         null,
         ""
       ],
-      "Bank requested reserve (%1$s) for %2$s.": [
+      "Warning: The exchange is neither directly trusted nor audited by a 
trusted auditor. If you withdraw from this exchange, it will be trusted in the 
future.": [
         null,
         ""
       ],
-      "Started to withdraw %1$s from %2$s (%3$s).": [
+      "Using exchange provider %1$s. The exchange provider will charge %2$s in 
fees.": [
         null,
         ""
       ],
-      "Merchant %1$s offered contract %2$s.": [
+      "Waiting for a response from %1$s %2$s": [
         null,
         ""
       ],
-      "Withdrew %1$s from %2$s (%3$s).": [
+      "Information about fees will be available when an exchange provider is 
selected.": [
         null,
         ""
       ],
-      "Paid %1$s to merchant %2$s. %3$s (%4$s)": [
+      "Your wallet (protocol version %1$s) might be outdated.%2$s The exchange 
has a higher, incompatible protocol version (%3$s).": [
         null,
         ""
       ],
-      "Merchant %1$s gave a refund over %2$s.": [
+      "The chosen exchange (protocol version %1$s might be outdated.%2$s The 
exchange has a lower, incompatible protocol version than your wallet (protocol 
version %3$s).": [
         null,
         ""
       ],
-      "tip": [
+      "Accept fees and withdraw": [
         null,
         ""
       ],
-      "Merchant %1$s gave a %2$s of %3$s.": [
+      "Change Exchange Provider": [
         null,
         ""
       ],
-      "You did not accept the tip yet.": [
+      "Please select an exchange.  You can review the details before after 
your selection.": [
         null,
         ""
       ],
-      "Unknown event (%1$s)": [
+      "Select %1$s": [
         null,
         ""
       ],
-      "Error: could not retrieve event history": [
+      "You are about to withdraw %1$s from your bank account into your 
wallet.": [
         null,
         ""
       ],
-      "Your wallet has no events recorded.": [
+      "Oops, something went wrong. The wallet responded with error status 
(%1$s).": [
         null,
         ""
       ],
-      "Wire to bank account": [
+      "Checking URL, please wait ...": [
         null,
         ""
       ],
-      "Confirm": [
+      "Can't parse amount: %1$s": [
         null,
         ""
       ],
-      "Cancel": [
+      "Can't parse wire_types: %1$s": [
         null,
         ""
       ],
@@ -1040,191 +1040,191 @@ strings['it'] = {
         null,
         ""
       ],
-      "Select": [
+      "Balance": [
         null,
         ""
       ],
-      "Error: URL may not be relative": [
+      "History": [
         null,
         ""
       ],
-      "Invalid exchange URL (%1$s)": [
+      "Debug": [
         null,
         ""
       ],
-      "The exchange is trusted by the wallet.": [
+      "help": [
         null,
         ""
       ],
-      "The exchange is audited by a trusted auditor.": [
+      "You have no balance to show. Need some %1$s getting started?": [
         null,
         ""
       ],
-      "Warning: The exchange is neither directly trusted nor audited by a 
trusted auditor. If you withdraw from this exchange, it will be trusted in the 
future.": [
+      "%1$s incoming": [
         null,
         ""
       ],
-      "Using exchange provider %1$s. The exchange provider will charge %2$s in 
fees.": [
+      "%1$s being spent": [
         null,
         ""
       ],
-      "Waiting for a response from %1$s %2$s": [
+      "Error: could not retrieve balance information.": [
         null,
         ""
       ],
-      "Information about fees will be available when an exchange provider is 
selected.": [
+      "Payback": [
         null,
         ""
       ],
-      "Your wallet (protocol version %1$s) might be outdated.%2$s The exchange 
has a higher, incompatible protocol version (%3$s).": [
+      "Return Electronic Cash to Bank Account": [
         null,
         ""
       ],
-      "The chosen exchange (protocol version %1$s might be outdated.%2$s The 
exchange has a lower, incompatible protocol version than your wallet (protocol 
version %3$s).": [
+      "Manage Trusted Auditors and Exchanges": [
         null,
         ""
       ],
-      "Accept fees and withdraw": [
+      "Bank requested reserve (%1$s) for %2$s.": [
         null,
         ""
       ],
-      "Change Exchange Provider": [
+      "Started to withdraw %1$s from %2$s (%3$s).": [
         null,
         ""
       ],
-      "Please select an exchange.  You can review the details before after 
your selection.": [
+      "Merchant %1$s offered contract %2$s.": [
         null,
         ""
       ],
-      "Select %1$s": [
+      "Withdrew %1$s from %2$s (%3$s).": [
         null,
         ""
       ],
-      "You are about to withdraw %1$s from your bank account into your 
wallet.": [
+      "Paid %1$s to merchant %2$s. %3$s (%4$s)": [
         null,
         ""
       ],
-      "Oops, something went wrong. The wallet responded with error status 
(%1$s).": [
+      "Merchant %1$s gave a refund over %2$s.": [
         null,
         ""
       ],
-      "Checking URL, please wait ...": [
+      "tip": [
         null,
         ""
       ],
-      "Can't parse amount: %1$s": [
+      "Merchant %1$s gave a %2$s of %3$s.": [
         null,
         ""
       ],
-      "Can't parse wire_types: %1$s": [
+      "You did not accept the tip yet.": [
         null,
         ""
       ],
-      "Fatal error: \"%1$s\".": [
+      "Unknown event (%1$s)": [
         null,
         ""
       ],
-      "Balance": [
+      "Error: could not retrieve event history": [
         null,
         ""
       ],
-      "History": [
+      "Your wallet has no events recorded.": [
         null,
         ""
       ],
-      "Debug": [
+      "Wire to bank account": [
         null,
         ""
       ],
-      "help": [
+      "Confirm": [
         null,
         ""
       ],
-      "You have no balance to show. Need some %1$s getting started?": [
+      "Cancel": [
         null,
         ""
       ],
-      "%1$s incoming": [
+      "Fatal error: \"%1$s\".": [
         null,
         ""
       ],
-      "%1$s being spent": [
+      "Select": [
         null,
         ""
       ],
-      "Error: could not retrieve balance information.": [
+      "Error: URL may not be relative": [
         null,
         ""
       ],
-      "Payback": [
+      "Invalid exchange URL (%1$s)": [
         null,
         ""
       ],
-      "Return Electronic Cash to Bank Account": [
+      "The exchange is trusted by the wallet.": [
         null,
         ""
       ],
-      "Manage Trusted Auditors and Exchanges": [
+      "The exchange is audited by a trusted auditor.": [
         null,
         ""
       ],
-      "Bank requested reserve (%1$s) for %2$s.": [
+      "Warning: The exchange is neither directly trusted nor audited by a 
trusted auditor. If you withdraw from this exchange, it will be trusted in the 
future.": [
         null,
         ""
       ],
-      "Started to withdraw %1$s from %2$s (%3$s).": [
+      "Using exchange provider %1$s. The exchange provider will charge %2$s in 
fees.": [
         null,
         ""
       ],
-      "Merchant %1$s offered contract %2$s.": [
+      "Waiting for a response from %1$s %2$s": [
         null,
         ""
       ],
-      "Withdrew %1$s from %2$s (%3$s).": [
+      "Information about fees will be available when an exchange provider is 
selected.": [
         null,
         ""
       ],
-      "Paid %1$s to merchant %2$s. %3$s (%4$s)": [
+      "Your wallet (protocol version %1$s) might be outdated.%2$s The exchange 
has a higher, incompatible protocol version (%3$s).": [
         null,
         ""
       ],
-      "Merchant %1$s gave a refund over %2$s.": [
+      "The chosen exchange (protocol version %1$s might be outdated.%2$s The 
exchange has a lower, incompatible protocol version than your wallet (protocol 
version %3$s).": [
         null,
         ""
       ],
-      "tip": [
+      "Accept fees and withdraw": [
         null,
         ""
       ],
-      "Merchant %1$s gave a %2$s of %3$s.": [
+      "Change Exchange Provider": [
         null,
         ""
       ],
-      "You did not accept the tip yet.": [
+      "Please select an exchange.  You can review the details before after 
your selection.": [
         null,
         ""
       ],
-      "Unknown event (%1$s)": [
+      "Select %1$s": [
         null,
         ""
       ],
-      "Error: could not retrieve event history": [
+      "You are about to withdraw %1$s from your bank account into your 
wallet.": [
         null,
         ""
       ],
-      "Your wallet has no events recorded.": [
+      "Oops, something went wrong. The wallet responded with error status 
(%1$s).": [
         null,
         ""
       ],
-      "Wire to bank account": [
+      "Checking URL, please wait ...": [
         null,
         ""
       ],
-      "Confirm": [
+      "Can't parse amount: %1$s": [
         null,
         ""
       ],
-      "Cancel": [
+      "Can't parse wire_types: %1$s": [
         null,
         ""
       ],
@@ -1356,193 +1356,193 @@ strings['sv'] = {
         null,
         "Det totala priset är %1$s."
       ],
-      "Select": [
+      "Balance": [
         null,
-        "Välj"
+        "Balans"
       ],
-      "Error: URL may not be relative": [
+      "History": [
         null,
-        ""
+        "Historia"
       ],
-      "Invalid exchange URL (%1$s)": [
+      "Debug": [
         null,
         ""
       ],
-      "The exchange is trusted by the wallet.": [
+      "help": [
         null,
-        "Tjänsteleverantörer i plånboken:"
+        "hjälp"
       ],
-      "The exchange is audited by a trusted auditor.": [
+      "You have no balance to show. Need some %1$s getting started?": [
         null,
-        ""
+        "Du har ingen balans att visa. Behöver du\n %1$s att börja?\n"
       ],
-      "Warning: The exchange is neither directly trusted nor audited by a 
trusted auditor. If you withdraw from this exchange, it will be trusted in the 
future.": [
+      "%1$s incoming": [
         null,
-        ""
+        "%1$s inkommande"
       ],
-      "Using exchange provider %1$s. The exchange provider will charge %2$s in 
fees.": [
+      "%1$s being spent": [
         null,
         ""
       ],
-      "Waiting for a response from %1$s %2$s": [
+      "Error: could not retrieve balance information.": [
         null,
         ""
       ],
-      "Information about fees will be available when an exchange provider is 
selected.": [
+      "Payback": [
         null,
-        ""
+        "Återbetalning"
       ],
-      "Your wallet (protocol version %1$s) might be outdated.%2$s The exchange 
has a higher, incompatible protocol version (%3$s).": [
+      "Return Electronic Cash to Bank Account": [
         null,
-        "tjänsteleverantörer plånboken"
+        "Återlämna elektroniska pengar till bank konto"
       ],
-      "The chosen exchange (protocol version %1$s might be outdated.%2$s The 
exchange has a lower, incompatible protocol version than your wallet (protocol 
version %3$s).": [
+      "Manage Trusted Auditors and Exchanges": [
         null,
-        "tjänsteleverantörer plånboken"
+        ""
       ],
-      "Accept fees and withdraw": [
+      "Bank requested reserve (%1$s) for %2$s.": [
         null,
-        "Acceptera avgifter och utbetala"
+        ""
       ],
-      "Change Exchange Provider": [
+      "Started to withdraw %1$s from %2$s (%3$s).": [
         null,
-        "Ändra tjänsteleverantörer"
+        ""
       ],
-      "Please select an exchange.  You can review the details before after 
your selection.": [
+      "Merchant %1$s offered contract %2$s.": [
         null,
-        ""
+        "Säljaren %1$s erbjöd kontrakt %2$s.\n"
       ],
-      "Select %1$s": [
+      "Withdrew %1$s from %2$s (%3$s).": [
         null,
-        "Välj %1$s"
+        ""
       ],
-      "You are about to withdraw %1$s from your bank account into your 
wallet.": [
+      "Paid %1$s to merchant %2$s. %3$s (%4$s)": [
         null,
-        "Du är på väg att ta ut\n %1$s från ditt bankkonto till din plånbok.\n"
+        ""
       ],
-      "Oops, something went wrong. The wallet responded with error status 
(%1$s).": [
+      "Merchant %1$s gave a refund over %2$s.": [
         null,
-        "plånboken"
+        "Säljaren %1$sgav en återbetalning på %2$s.\n"
       ],
-      "Checking URL, please wait ...": [
+      "tip": [
         null,
         ""
       ],
-      "Can't parse amount: %1$s": [
+      "Merchant %1$s gave a %2$s of %3$s.": [
         null,
-        ""
+        "Säljaren %1$sgav en återbetalning på %2$s.\n"
       ],
-      "Can't parse wire_types: %1$s": [
+      "You did not accept the tip yet.": [
         null,
         ""
       ],
-      "Fatal error: \"%1$s\".": [
+      "Unknown event (%1$s)": [
         null,
         ""
       ],
-      "Balance": [
+      "Error: could not retrieve event history": [
         null,
-        "Balans"
+        ""
       ],
-      "History": [
+      "Your wallet has no events recorded.": [
         null,
-        "Historia"
+        "plånboken"
       ],
-      "Debug": [
+      "Wire to bank account": [
         null,
-        ""
+        "Övervisa till bank konto"
       ],
-      "help": [
+      "Confirm": [
         null,
-        "hjälp"
+        "Bekräfta"
       ],
-      "You have no balance to show. Need some %1$s getting started?": [
+      "Cancel": [
         null,
-        "Du har ingen balans att visa. Behöver du\n %1$s att börja?\n"
+        "Avbryt"
       ],
-      "%1$s incoming": [
+      "Fatal error: \"%1$s\".": [
         null,
-        "%1$s inkommande"
+        ""
       ],
-      "%1$s being spent": [
+      "Select": [
         null,
-        ""
+        "Välj"
       ],
-      "Error: could not retrieve balance information.": [
+      "Error: URL may not be relative": [
         null,
         ""
       ],
-      "Payback": [
+      "Invalid exchange URL (%1$s)": [
         null,
-        "Återbetalning"
+        ""
       ],
-      "Return Electronic Cash to Bank Account": [
+      "The exchange is trusted by the wallet.": [
         null,
-        "Återlämna elektroniska pengar till bank konto"
+        "Tjänsteleverantörer i plånboken:"
       ],
-      "Manage Trusted Auditors and Exchanges": [
+      "The exchange is audited by a trusted auditor.": [
         null,
         ""
       ],
-      "Bank requested reserve (%1$s) for %2$s.": [
+      "Warning: The exchange is neither directly trusted nor audited by a 
trusted auditor. If you withdraw from this exchange, it will be trusted in the 
future.": [
         null,
         ""
       ],
-      "Started to withdraw %1$s from %2$s (%3$s).": [
+      "Using exchange provider %1$s. The exchange provider will charge %2$s in 
fees.": [
         null,
         ""
       ],
-      "Merchant %1$s offered contract %2$s.": [
+      "Waiting for a response from %1$s %2$s": [
         null,
-        "Säljaren %1$s erbjöd kontrakt %2$s.\n"
+        ""
       ],
-      "Withdrew %1$s from %2$s (%3$s).": [
+      "Information about fees will be available when an exchange provider is 
selected.": [
         null,
         ""
       ],
-      "Paid %1$s to merchant %2$s. %3$s (%4$s)": [
+      "Your wallet (protocol version %1$s) might be outdated.%2$s The exchange 
has a higher, incompatible protocol version (%3$s).": [
         null,
-        ""
+        "tjänsteleverantörer plånboken"
       ],
-      "Merchant %1$s gave a refund over %2$s.": [
+      "The chosen exchange (protocol version %1$s might be outdated.%2$s The 
exchange has a lower, incompatible protocol version than your wallet (protocol 
version %3$s).": [
         null,
-        "Säljaren %1$sgav en återbetalning på %2$s.\n"
+        "tjänsteleverantörer plånboken"
       ],
-      "tip": [
+      "Accept fees and withdraw": [
         null,
-        ""
+        "Acceptera avgifter och utbetala"
       ],
-      "Merchant %1$s gave a %2$s of %3$s.": [
+      "Change Exchange Provider": [
         null,
-        "Säljaren %1$sgav en återbetalning på %2$s.\n"
+        "Ändra tjänsteleverantörer"
       ],
-      "You did not accept the tip yet.": [
+      "Please select an exchange.  You can review the details before after 
your selection.": [
         null,
         ""
       ],
-      "Unknown event (%1$s)": [
+      "Select %1$s": [
         null,
-        ""
+        "Välj %1$s"
       ],
-      "Error: could not retrieve event history": [
+      "You are about to withdraw %1$s from your bank account into your 
wallet.": [
         null,
-        ""
+        "Du är på väg att ta ut\n %1$s från ditt bankkonto till din plånbok.\n"
       ],
-      "Your wallet has no events recorded.": [
+      "Oops, something went wrong. The wallet responded with error status 
(%1$s).": [
         null,
         "plånboken"
       ],
-      "Wire to bank account": [
+      "Checking URL, please wait ...": [
         null,
-        "Övervisa till bank konto"
+        ""
       ],
-      "Confirm": [
+      "Can't parse amount: %1$s": [
         null,
-        "Bekräfta"
+        ""
       ],
-      "Cancel": [
+      "Can't parse wire_types: %1$s": [
         null,
-        "Avbryt"
+        ""
       ],
       "Withdrawal fees:": [
         null,
diff --git a/src/i18n/sv.po b/src/i18n/sv.po
index 1b99a13a..7e3ec516 100644
--- a/src/i18n/sv.po
+++ b/src/i18n/sv.po
@@ -37,28 +37,28 @@ msgstr ""
 msgid "time (ms/op)"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:78
+#: src/webex/pages/pay.tsx:78
 #, fuzzy, c-format
 msgid "show more details"
 msgstr "visa mer"
 
-#: src/webex/pages/confirm-contract.tsx:92
+#: src/webex/pages/pay.tsx:92
 #, c-format
 msgid "Accepted exchanges:"
 msgstr "Accepterade tjänsteleverantörer:"
 
-#: src/webex/pages/confirm-contract.tsx:97
+#: src/webex/pages/pay.tsx:97
 #, c-format
 msgid "Exchanges in the wallet:"
 msgstr "Tjänsteleverantörer i plånboken:"
 
-#: src/webex/pages/confirm-contract.tsx:219
+#: src/webex/pages/pay.tsx:219
 #, c-format
 msgid "You have insufficient funds of the requested currency in your wallet."
 msgstr "plånboken"
 
 #. tslint:disable-next-line:max-line-length
-#: src/webex/pages/confirm-contract.tsx:221
+#: src/webex/pages/pay.tsx:221
 #, c-format
 msgid ""
 "You do not have any funds from an exchange that is accepted by this "
@@ -66,17 +66,17 @@ msgid ""
 "wallet."
 msgstr "plånboken"
 
-#: src/webex/pages/confirm-contract.tsx:322
+#: src/webex/pages/pay.tsx:322
 #, c-format
 msgid "Confirm payment"
 msgstr "Godkän betalning"
 
-#: src/webex/pages/confirm-contract.tsx:332
+#: src/webex/pages/pay.tsx:332
 #, c-format
 msgid "Submitting payment"
 msgstr "Bekräftar betalning"
 
-#: src/webex/pages/confirm-contract.tsx:343
+#: src/webex/pages/pay.tsx:343
 #, c-format
 msgid ""
 "You already paid for this, clicking \"Confirm payment\" will not cost money "
@@ -85,165 +85,41 @@ msgstr ""
 "Du har redan betalat för det här, om du trycker \"Godkän betalning\" "
 "debiteras du inte igen"
 
-#: src/webex/pages/confirm-contract.tsx:357
+#: src/webex/pages/pay.tsx:357
 #, fuzzy, c-format
 msgid "Aborting payment ..."
 msgstr "Bekräftar betalning"
 
-#: src/webex/pages/confirm-contract.tsx:359
+#: src/webex/pages/pay.tsx:359
 #, c-format
 msgid "Payment aborted!"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:362
+#: src/webex/pages/pay.tsx:362
 #, c-format
 msgid "Retry Payment"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:365
+#: src/webex/pages/pay.tsx:365
 #, fuzzy, c-format
 msgid "Abort Payment"
 msgstr "Godkän betalning"
 
-#: src/webex/pages/confirm-contract.tsx:374
+#: src/webex/pages/pay.tsx:374
 #, fuzzy, c-format
 msgid "The merchant %1$s offers you to purchase:"
 msgstr "Säljaren %1$s erbjuder följande:"
 
-#: src/webex/pages/confirm-contract.tsx:383
+#: src/webex/pages/pay.tsx:383
 #, fuzzy, c-format
 msgid "The total price is %1$s (plus %2$s fees)."
 msgstr "Det totala priset är %1$s (plus %2$s avgifter).\n"
 
-#: src/webex/pages/confirm-contract.tsx:387
+#: src/webex/pages/pay.tsx:387
 #, fuzzy, c-format
 msgid "The total price is %1$s."
 msgstr "Det totala priset är %1$s."
 
-#: src/webex/pages/confirm-create-reserve.tsx:128
-#, c-format
-msgid "Select"
-msgstr "Välj"
-
-#: src/webex/pages/confirm-create-reserve.tsx:145
-#, c-format
-msgid "Error: URL may not be relative"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:160
-#, c-format
-msgid "Invalid exchange URL (%1$s)"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:210
-#, fuzzy, c-format
-msgid "The exchange is trusted by the wallet."
-msgstr "Tjänsteleverantörer i plånboken:"
-
-#: src/webex/pages/confirm-create-reserve.tsx:216
-#, c-format
-msgid "The exchange is audited by a trusted auditor."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:222
-#, c-format
-msgid ""
-"Warning: The exchange is neither directly trusted nor audited by a trusted "
-"auditor. If you withdraw from this exchange, it will be trusted in the "
-"future."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:231
-#, c-format
-msgid ""
-"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:243
-#, c-format
-msgid "Waiting for a response from %1$s %2$s"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:260
-#, c-format
-msgid ""
-"Information about fees will be available when an exchange provider is "
-"selected."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:279
-#, fuzzy, c-format
-msgid ""
-"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
-"a higher, incompatible protocol version (%3$s)."
-msgstr "tjänsteleverantörer plånboken"
-
-#: src/webex/pages/confirm-create-reserve.tsx:290
-#, fuzzy, c-format
-msgid ""
-"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
-"exchange has a lower, incompatible protocol version than your wallet "
-"(protocol version %3$s)."
-msgstr "tjänsteleverantörer plånboken"
-
-#: src/webex/pages/confirm-create-reserve.tsx:309
-#, c-format
-msgid "Accept fees and withdraw"
-msgstr "Acceptera avgifter och utbetala"
-
-#: src/webex/pages/confirm-create-reserve.tsx:314
-#, c-format
-msgid "Change Exchange Provider"
-msgstr "Ändra tjänsteleverantörer"
-
-#: src/webex/pages/confirm-create-reserve.tsx:335
-#, c-format
-msgid ""
-"Please select an exchange.  You can review the details before after your "
-"selection."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:341
-#: src/webex/pages/confirm-create-reserve.tsx:353
-#, fuzzy, c-format
-msgid "Select %1$s"
-msgstr "Välj %1$s"
-
-#: src/webex/pages/confirm-create-reserve.tsx:370
-#, fuzzy, c-format
-msgid "You are about to withdraw %1$s from your bank account into your wallet."
-msgstr ""
-"Du är på väg att ta ut\n"
-" %1$s från ditt bankkonto till din plånbok.\n"
-
-#: src/webex/pages/confirm-create-reserve.tsx:459
-#, fuzzy, c-format
-msgid ""
-"Oops, something went wrong. The wallet responded with error status (%1$s)."
-msgstr "plånboken"
-
-#: src/webex/pages/confirm-create-reserve.tsx:468
-#, c-format
-msgid "Checking URL, please wait ..."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:482
-#, c-format
-msgid "Can't parse amount: %1$s"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:489
-#, c-format
-msgid "Can't parse wire_types: %1$s"
-msgstr ""
-
-#. #-#-#-#-#  - (PACKAGE VERSION)  #-#-#-#-#
-#. TODO:generic error reporting function or component.
-#: src/webex/pages/confirm-create-reserve.tsx:519 src/webex/pages/tip.tsx:180
-#, c-format
-msgid "Fatal error: \"%1$s\"."
-msgstr ""
-
 #: src/webex/pages/popup.tsx:165
 #, c-format
 msgid "Balance"
@@ -376,6 +252,129 @@ msgstr "Bekräfta"
 msgid "Cancel"
 msgstr "Avbryt"
 
+#. #-#-#-#-#  - (PACKAGE VERSION)  #-#-#-#-#
+#. TODO:generic error reporting function or component.
+#: src/webex/pages/tip.tsx:180 src/webex/pages/withdraw.tsx:519
+#, c-format
+msgid "Fatal error: \"%1$s\"."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:128
+#, c-format
+msgid "Select"
+msgstr "Välj"
+
+#: src/webex/pages/withdraw.tsx:145
+#, c-format
+msgid "Error: URL may not be relative"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:160
+#, c-format
+msgid "Invalid exchange URL (%1$s)"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:210
+#, fuzzy, c-format
+msgid "The exchange is trusted by the wallet."
+msgstr "Tjänsteleverantörer i plånboken:"
+
+#: src/webex/pages/withdraw.tsx:216
+#, c-format
+msgid "The exchange is audited by a trusted auditor."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:222
+#, c-format
+msgid ""
+"Warning: The exchange is neither directly trusted nor audited by a trusted "
+"auditor. If you withdraw from this exchange, it will be trusted in the "
+"future."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:231
+#, c-format
+msgid ""
+"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:243
+#, c-format
+msgid "Waiting for a response from %1$s %2$s"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:260
+#, c-format
+msgid ""
+"Information about fees will be available when an exchange provider is "
+"selected."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:279
+#, fuzzy, c-format
+msgid ""
+"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
+"a higher, incompatible protocol version (%3$s)."
+msgstr "tjänsteleverantörer plånboken"
+
+#: src/webex/pages/withdraw.tsx:290
+#, fuzzy, c-format
+msgid ""
+"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
+"exchange has a lower, incompatible protocol version than your wallet "
+"(protocol version %3$s)."
+msgstr "tjänsteleverantörer plånboken"
+
+#: src/webex/pages/withdraw.tsx:309
+#, c-format
+msgid "Accept fees and withdraw"
+msgstr "Acceptera avgifter och utbetala"
+
+#: src/webex/pages/withdraw.tsx:314
+#, c-format
+msgid "Change Exchange Provider"
+msgstr "Ändra tjänsteleverantörer"
+
+#: src/webex/pages/withdraw.tsx:335
+#, c-format
+msgid ""
+"Please select an exchange.  You can review the details before after your "
+"selection."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:341 src/webex/pages/withdraw.tsx:353
+#, fuzzy, c-format
+msgid "Select %1$s"
+msgstr "Välj %1$s"
+
+#: src/webex/pages/withdraw.tsx:370
+#, fuzzy, c-format
+msgid "You are about to withdraw %1$s from your bank account into your wallet."
+msgstr ""
+"Du är på väg att ta ut\n"
+" %1$s från ditt bankkonto till din plånbok.\n"
+
+#: src/webex/pages/withdraw.tsx:459
+#, fuzzy, c-format
+msgid ""
+"Oops, something went wrong. The wallet responded with error status (%1$s)."
+msgstr "plånboken"
+
+#: src/webex/pages/withdraw.tsx:468
+#, c-format
+msgid "Checking URL, please wait ..."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:482
+#, c-format
+msgid "Can't parse amount: %1$s"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:489
+#, c-format
+msgid "Can't parse wire_types: %1$s"
+msgstr ""
+
 #: src/webex/renderHtml.tsx:225
 #, c-format
 msgid "Withdrawal fees:"
diff --git a/src/i18n/taler-wallet-webex.pot b/src/i18n/taler-wallet-webex.pot
index e7615e41..1f0dc2a4 100644
--- a/src/i18n/taler-wallet-webex.pot
+++ b/src/i18n/taler-wallet-webex.pot
@@ -37,28 +37,28 @@ msgstr ""
 msgid "time (ms/op)"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:78
+#: src/webex/pages/pay.tsx:78
 #, c-format
 msgid "show more details"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:92
+#: src/webex/pages/pay.tsx:92
 #, c-format
 msgid "Accepted exchanges:"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:97
+#: src/webex/pages/pay.tsx:97
 #, c-format
 msgid "Exchanges in the wallet:"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:219
+#: src/webex/pages/pay.tsx:219
 #, c-format
 msgid "You have insufficient funds of the requested currency in your wallet."
 msgstr ""
 
 #. tslint:disable-next-line:max-line-length
-#: src/webex/pages/confirm-contract.tsx:221
+#: src/webex/pages/pay.tsx:221
 #, c-format
 msgid ""
 "You do not have any funds from an exchange that is accepted by this "
@@ -66,308 +66,307 @@ msgid ""
 "wallet."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:322
+#: src/webex/pages/pay.tsx:322
 #, c-format
 msgid "Confirm payment"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:332
+#: src/webex/pages/pay.tsx:332
 #, c-format
 msgid "Submitting payment"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:343
+#: src/webex/pages/pay.tsx:343
 #, c-format
 msgid ""
 "You already paid for this, clicking \"Confirm payment\" will not cost money "
 "again."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:357
+#: src/webex/pages/pay.tsx:357
 #, c-format
 msgid "Aborting payment ..."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:359
+#: src/webex/pages/pay.tsx:359
 #, c-format
 msgid "Payment aborted!"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:362
+#: src/webex/pages/pay.tsx:362
 #, c-format
 msgid "Retry Payment"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:365
+#: src/webex/pages/pay.tsx:365
 #, c-format
 msgid "Abort Payment"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:374
+#: src/webex/pages/pay.tsx:374
 #, c-format
 msgid "The merchant %1$s offers you to purchase:"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:383
+#: src/webex/pages/pay.tsx:383
 #, c-format
 msgid "The total price is %1$s (plus %2$s fees)."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:387
+#: src/webex/pages/pay.tsx:387
 #, c-format
 msgid "The total price is %1$s."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:128
+#: src/webex/pages/popup.tsx:165
 #, c-format
-msgid "Select"
+msgid "Balance"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:145
+#: src/webex/pages/popup.tsx:168
 #, c-format
-msgid "Error: URL may not be relative"
+msgid "History"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:160
+#: src/webex/pages/popup.tsx:171
 #, c-format
-msgid "Invalid exchange URL (%1$s)"
+msgid "Debug"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:210
+#: src/webex/pages/popup.tsx:251
 #, c-format
-msgid "The exchange is trusted by the wallet."
+msgid "help"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:216
+#: src/webex/pages/popup.tsx:256
 #, c-format
-msgid "The exchange is audited by a trusted auditor."
+msgid "You have no balance to show. Need some %1$s getting started?"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:222
+#: src/webex/pages/popup.tsx:273
 #, c-format
-msgid ""
-"Warning: The exchange is neither directly trusted nor audited by a trusted "
-"auditor. If you withdraw from this exchange, it will be trusted in the "
-"future."
+msgid "%1$s incoming"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:231
+#: src/webex/pages/popup.tsx:286
 #, c-format
-msgid ""
-"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
+msgid "%1$s being spent"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:243
+#: src/webex/pages/popup.tsx:313
 #, c-format
-msgid "Waiting for a response from %1$s %2$s"
+msgid "Error: could not retrieve balance information."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:260
+#: src/webex/pages/popup.tsx:340
 #, c-format
-msgid ""
-"Information about fees will be available when an exchange provider is "
-"selected."
+msgid "Payback"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:279
+#: src/webex/pages/popup.tsx:341
 #, c-format
-msgid ""
-"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
-"a higher, incompatible protocol version (%3$s)."
+msgid "Return Electronic Cash to Bank Account"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:290
+#: src/webex/pages/popup.tsx:342
 #, c-format
-msgid ""
-"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
-"exchange has a lower, incompatible protocol version than your wallet "
-"(protocol version %3$s)."
+msgid "Manage Trusted Auditors and Exchanges"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:309
+#: src/webex/pages/popup.tsx:354
 #, c-format
-msgid "Accept fees and withdraw"
+msgid "Bank requested reserve (%1$s) for %2$s."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:314
+#: src/webex/pages/popup.tsx:364
 #, c-format
-msgid "Change Exchange Provider"
+msgid "Started to withdraw %1$s from %2$s (%3$s)."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:335
+#: src/webex/pages/popup.tsx:373
 #, c-format
-msgid ""
-"Please select an exchange.  You can review the details before after your "
-"selection."
+msgid "Merchant %1$s offered contract %2$s."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:341
-#: src/webex/pages/confirm-create-reserve.tsx:353
+#: src/webex/pages/popup.tsx:384
 #, c-format
-msgid "Select %1$s"
+msgid "Withdrew %1$s from %2$s (%3$s)."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:370
+#: src/webex/pages/popup.tsx:394
 #, c-format
-msgid "You are about to withdraw %1$s from your bank account into your wallet."
+msgid "Paid %1$s to merchant %2$s. %3$s (%4$s)"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:459
+#: src/webex/pages/popup.tsx:404
 #, c-format
-msgid ""
-"Oops, something went wrong. The wallet responded with error status (%1$s)."
+msgid "Merchant %1$s gave a refund over %2$s."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:468
+#: src/webex/pages/popup.tsx:414
 #, c-format
-msgid "Checking URL, please wait ..."
+msgid "tip"
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:482
+#: src/webex/pages/popup.tsx:418
 #, c-format
-msgid "Can't parse amount: %1$s"
+msgid "Merchant %1$s gave a %2$s of %3$s."
 msgstr ""
 
-#: src/webex/pages/confirm-create-reserve.tsx:489
+#: src/webex/pages/popup.tsx:422
 #, c-format
-msgid "Can't parse wire_types: %1$s"
+msgid "You did not accept the tip yet."
 msgstr ""
 
-#. #-#-#-#-#  - (PACKAGE VERSION)  #-#-#-#-#
-#. TODO:generic error reporting function or component.
-#: src/webex/pages/confirm-create-reserve.tsx:519 src/webex/pages/tip.tsx:180
+#: src/webex/pages/popup.tsx:427
 #, c-format
-msgid "Fatal error: \"%1$s\"."
+msgid "Unknown event (%1$s)"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:165
+#: src/webex/pages/popup.tsx:470
 #, c-format
-msgid "Balance"
+msgid "Error: could not retrieve event history"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:168
+#: src/webex/pages/popup.tsx:495
 #, c-format
-msgid "History"
+msgid "Your wallet has no events recorded."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:171
+#: src/webex/pages/return-coins.tsx:105
 #, c-format
-msgid "Debug"
+msgid "Wire to bank account"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:251
+#: src/webex/pages/return-coins.tsx:173
 #, c-format
-msgid "help"
+msgid "Confirm"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:256
+#: src/webex/pages/return-coins.tsx:176
 #, c-format
-msgid "You have no balance to show. Need some %1$s getting started?"
+msgid "Cancel"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:273
+#. #-#-#-#-#  - (PACKAGE VERSION)  #-#-#-#-#
+#. TODO:generic error reporting function or component.
+#: src/webex/pages/tip.tsx:180 src/webex/pages/withdraw.tsx:519
 #, c-format
-msgid "%1$s incoming"
+msgid "Fatal error: \"%1$s\"."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:286
+#: src/webex/pages/withdraw.tsx:128
 #, c-format
-msgid "%1$s being spent"
+msgid "Select"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:313
+#: src/webex/pages/withdraw.tsx:145
 #, c-format
-msgid "Error: could not retrieve balance information."
+msgid "Error: URL may not be relative"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:340
+#: src/webex/pages/withdraw.tsx:160
 #, c-format
-msgid "Payback"
+msgid "Invalid exchange URL (%1$s)"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:341
+#: src/webex/pages/withdraw.tsx:210
 #, c-format
-msgid "Return Electronic Cash to Bank Account"
+msgid "The exchange is trusted by the wallet."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:342
+#: src/webex/pages/withdraw.tsx:216
 #, c-format
-msgid "Manage Trusted Auditors and Exchanges"
+msgid "The exchange is audited by a trusted auditor."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:354
+#: src/webex/pages/withdraw.tsx:222
 #, c-format
-msgid "Bank requested reserve (%1$s) for %2$s."
+msgid ""
+"Warning: The exchange is neither directly trusted nor audited by a trusted "
+"auditor. If you withdraw from this exchange, it will be trusted in the "
+"future."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:364
+#: src/webex/pages/withdraw.tsx:231
 #, c-format
-msgid "Started to withdraw %1$s from %2$s (%3$s)."
+msgid ""
+"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:373
+#: src/webex/pages/withdraw.tsx:243
 #, c-format
-msgid "Merchant %1$s offered contract %2$s."
+msgid "Waiting for a response from %1$s %2$s"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:384
+#: src/webex/pages/withdraw.tsx:260
 #, c-format
-msgid "Withdrew %1$s from %2$s (%3$s)."
+msgid ""
+"Information about fees will be available when an exchange provider is "
+"selected."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:394
+#: src/webex/pages/withdraw.tsx:279
 #, c-format
-msgid "Paid %1$s to merchant %2$s. %3$s (%4$s)"
+msgid ""
+"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
+"a higher, incompatible protocol version (%3$s)."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:404
+#: src/webex/pages/withdraw.tsx:290
 #, c-format
-msgid "Merchant %1$s gave a refund over %2$s."
+msgid ""
+"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
+"exchange has a lower, incompatible protocol version than your wallet "
+"(protocol version %3$s)."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:414
+#: src/webex/pages/withdraw.tsx:309
 #, c-format
-msgid "tip"
+msgid "Accept fees and withdraw"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:418
+#: src/webex/pages/withdraw.tsx:314
 #, c-format
-msgid "Merchant %1$s gave a %2$s of %3$s."
+msgid "Change Exchange Provider"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:422
+#: src/webex/pages/withdraw.tsx:335
 #, c-format
-msgid "You did not accept the tip yet."
+msgid ""
+"Please select an exchange.  You can review the details before after your "
+"selection."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:427
+#: src/webex/pages/withdraw.tsx:341 src/webex/pages/withdraw.tsx:353
 #, c-format
-msgid "Unknown event (%1$s)"
+msgid "Select %1$s"
 msgstr ""
 
-#: src/webex/pages/popup.tsx:470
+#: src/webex/pages/withdraw.tsx:370
 #, c-format
-msgid "Error: could not retrieve event history"
+msgid "You are about to withdraw %1$s from your bank account into your wallet."
 msgstr ""
 
-#: src/webex/pages/popup.tsx:495
+#: src/webex/pages/withdraw.tsx:459
 #, c-format
-msgid "Your wallet has no events recorded."
+msgid ""
+"Oops, something went wrong. The wallet responded with error status (%1$s)."
 msgstr ""
 
-#: src/webex/pages/return-coins.tsx:105
+#: src/webex/pages/withdraw.tsx:468
 #, c-format
-msgid "Wire to bank account"
+msgid "Checking URL, please wait ..."
 msgstr ""
 
-#: src/webex/pages/return-coins.tsx:173
+#: src/webex/pages/withdraw.tsx:482
 #, c-format
-msgid "Confirm"
+msgid "Can't parse amount: %1$s"
 msgstr ""
 
-#: src/webex/pages/return-coins.tsx:176
+#: src/webex/pages/withdraw.tsx:489
 #, c-format
-msgid "Cancel"
+msgid "Can't parse wire_types: %1$s"
 msgstr ""
 
 #: src/webex/renderHtml.tsx:225
diff --git a/src/talerTypes.ts b/src/talerTypes.ts
index 9176daf7..360be333 100644
--- a/src/talerTypes.ts
+++ b/src/talerTypes.ts
@@ -924,6 +924,9 @@ export class CheckPaymentResponse {
   contract_terms: ContractTerms | undefined;
 
   @Checkable.Optional(Checkable.String())
+  taler_pay_uri: string | undefined;
+
+  @Checkable.Optional(Checkable.String())
   contract_url: string | undefined;
 
   /**
@@ -931,4 +934,37 @@ export class CheckPaymentResponse {
    * member.
    */
   static checked: (obj: any) => CheckPaymentResponse;
+}
+
+/**
+ * Response from the bank.
+ */
+@Checkable.Class({extra: true})
+export class WithdrawOperationStatusResponse {
+  @Checkable.Boolean()
+  selection_done: boolean;
+
+  @Checkable.Boolean()
+  transfer_done: boolean;
+
+  @Checkable.String()
+  amount: string;
+
+  @Checkable.Optional(Checkable.String())
+  sender_wire?: string;
+
+  @Checkable.Optional(Checkable.String())
+  suggested_exchange?: string;
+
+  @Checkable.Optional(Checkable.String())
+  confirm_transfer_url?: string;
+
+  @Checkable.List(Checkable.String())
+  wire_types: string[];
+
+  /**
+   * Verify that a value matches the schema of this class and convert it into a
+   * member.
+   */
+  static checked: (obj: any) => WithdrawOperationStatusResponse;
 }
\ No newline at end of file
diff --git a/src/taleruri-test.ts b/src/taleruri-test.ts
new file mode 100644
index 00000000..27cd7d18
--- /dev/null
+++ b/src/taleruri-test.ts
@@ -0,0 +1,89 @@
+/*
+ This file is part of 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 test from "ava";
+import { parsePayUri, parseWithdrawUri } from "./taleruri";
+
+test("taler pay url parsing: http(s)", (t) => {
+  const url1 = "https://example.com/bar?spam=eggs";;
+  const r1 = parsePayUri(url1);
+  if (!r1) {
+    t.fail();
+    return;
+  }
+  t.is(r1.downloadUrl, url1);
+  t.is(r1.sessionId, undefined);
+  const url2 = "http://example.com/bar?spam=eggs";;
+  const r2 = parsePayUri(url2);
+  if (!r2) {
+    t.fail();
+    return;
+  }
+});
+
+
+test("taler pay url parsing: wrong scheme", (t) => {
+  const url1 = "talerfoo://";
+  const r1 = parsePayUri(url1);
+  t.is(r1, undefined);
+
+  const url2 = "taler://refund/a/b/c/d/e/f";
+  const r2 = parsePayUri(url1);
+  t.is(r2, undefined);
+});
+
+
+test("taler pay url parsing: defaults", (t) => {
+  const url1 = "taler://pay/example.com/-/-/myorder";
+  const r1 = parsePayUri(url1);
+  if (!r1) {
+    t.fail();
+    return;
+  }
+  t.is(r1.downloadUrl, 
"https://example.com/public/proposal?instance=default&order_id=myorder";);
+  t.is(r1.sessionId, undefined);
+
+  const url2 = "taler://pay/example.com/-/-/myorder/mysession";
+  const r2 = parsePayUri(url2);
+  if (!r2) {
+    t.fail();
+    return;
+  }
+  t.is(r2.downloadUrl, 
"https://example.com/public/proposal?instance=default&order_id=myorder";);
+  t.is(r2.sessionId, "mysession");
+});
+
+
+test("taler pay url parsing: trailing parts", (t) => {
+  const url1 = "taler://pay/example.com/-/-/myorder/mysession/spam/eggs";
+  const r1 = parsePayUri(url1);
+  if (!r1) {
+    t.fail();
+    return;
+  }
+  t.is(r1.downloadUrl, 
"https://example.com/public/proposal?instance=default&order_id=myorder";);
+  t.is(r1.sessionId, "mysession");
+});
+
+test("taler withdraw uri parsing", (t) => {
+  const url1 = "taler://withdraw/bank.example.com/-/12345";
+  const r1 = parseWithdrawUri(url1);
+  if (!r1) {
+    t.fail();
+    return;
+  }
+  t.is(r1.statusUrl, "https://bank.example.com/api/withdraw-operation/12345";);
+});
\ No newline at end of file
diff --git a/src/taleruri.ts b/src/taleruri.ts
new file mode 100644
index 00000000..fa305d1d
--- /dev/null
+++ b/src/taleruri.ts
@@ -0,0 +1,106 @@
+/*
+ This file is part of 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 URI = require("urijs");
+import { string } from "prop-types";
+
+export interface PayUriResult {
+  downloadUrl: string;
+  sessionId?: string;
+}
+
+export interface WithdrawUriResult {
+  statusUrl: string;
+}
+
+export function parseWithdrawUri(s: string): WithdrawUriResult | undefined {
+  const parsedUri = new URI(s);
+  if (parsedUri.scheme() !== "taler") {
+    return undefined;
+  }
+  if (parsedUri.authority() != "withdraw") {
+    return undefined;
+  }
+
+  let [host, path, withdrawId] = parsedUri.segmentCoded();
+
+  if (path === "-") {
+    path = "/api/withdraw-operation";
+  }
+
+  return {
+    statusUrl: new URI({ protocol: "https", hostname: host, path: path })
+      .segmentCoded(withdrawId)
+      .href(),
+  };
+}
+
+export function parsePayUri(s: string): PayUriResult | undefined {
+  const parsedUri = new URI(s);
+  if (parsedUri.scheme() === "http" || parsedUri.scheme() === "https") {
+    return {
+      downloadUrl: s,
+      sessionId: undefined,
+    };
+  }
+  if (parsedUri.scheme() != "taler") {
+    return undefined;
+  }
+  if (parsedUri.authority() != "pay") {
+    return undefined;
+  }
+
+  let [
+    _,
+    host,
+    maybePath,
+    maybeInstance,
+    orderId,
+    maybeSessionid,
+  ] = parsedUri.path().split("/");
+
+  if (!host) {
+    return undefined;
+  }
+
+  if (!maybePath) {
+    return undefined;
+  }
+
+  if (!orderId) {
+    return undefined;
+  }
+
+  if (maybePath === "-") {
+    maybePath = "public/proposal";
+  } else {
+    maybePath = decodeURIComponent(maybePath);
+  }
+  if (maybeInstance === "-") {
+    maybeInstance = "default";
+  }
+
+  const downloadUrl = new URI(
+    "https://"; + host + "/" + decodeURIComponent(maybePath),
+  )
+    .addQuery({ instance: maybeInstance, order_id: orderId })
+    .href();
+
+  return {
+    downloadUrl,
+    sessionId: maybeSessionid,
+  };
+}
diff --git a/src/wallet.ts b/src/wallet.ts
index faced994..e476c94f 100644
--- a/src/wallet.ts
+++ b/src/wallet.ts
@@ -81,6 +81,7 @@ import {
   TipPlanchetDetail,
   TipResponse,
   TipToken,
+  WithdrawOperationStatusResponse,
 } from "./talerTypes";
 import {
   Badge,
@@ -103,9 +104,12 @@ import {
   WalletBalance,
   WalletBalanceEntry,
   PreparePayResult,
+  DownloadedWithdrawInfo,
+  WithdrawDetails,
+  AcceptWithdrawalResponse,
 } from "./walletTypes";
 import { openPromise } from "./promiseUtils";
-import Axios from "axios";
+import { parsePayUri, parseWithdrawUri } from "./taleruri";
 
 interface SpeculativePayData {
   payCoinInfo: PayCoinInfo;
@@ -183,12 +187,13 @@ export function getTotalRefreshCost(
     ...withdrawDenoms.map(d => d.value),
   ).amount;
   const totalCost = Amounts.sub(amountLeft, resultingAmount).amount;
-  Wallet.enableTracing && console.log(
-    "total refresh cost for",
-    amountToPretty(amountLeft),
-    "is",
-    amountToPretty(totalCost),
-  );
+  Wallet.enableTracing &&
+    console.log(
+      "total refresh cost for",
+      amountToPretty(amountLeft),
+      "is",
+      amountToPretty(totalCost),
+    );
   return totalCost;
 }
 
@@ -255,7 +260,8 @@ export function selectPayCoins(
       const depositFeeToCover = Amounts.sub(accDepositFee, depositFeeLimit)
         .amount;
       leftAmount = Amounts.sub(leftAmount, depositFeeToCover).amount;
-      Wallet.enableTracing && console.log("deposit fee to cover", 
amountToPretty(depositFeeToCover));
+      Wallet.enableTracing &&
+        console.log("deposit fee to cover", amountToPretty(depositFeeToCover));
 
       let totalFees: AmountJson = Amounts.getZero(currency);
       if (coversAmountWithFee && !isBelowFee) {
@@ -713,18 +719,29 @@ export class Wallet {
     return t;
   }
 
+  getNextUrl(contractTerms: ContractTerms): string {
+    const fu = new URI(contractTerms.fulfillment_url);
+    fu.addSearch("order_id", contractTerms.order_id);
+    return fu.href();
+  }
+
   async preparePay(url: string): Promise<PreparePayResult> {
-    const talerpayPrefix = "talerpay:";
-    let downloadSessionId: string | undefined;
-    if (url.startsWith(talerpayPrefix)) {
-      let [p1, p2] = url.substring(talerpayPrefix.length).split(";");
-      url = decodeURIComponent(p1);
-      downloadSessionId = p2;
+    const uriResult = parsePayUri(url);
+
+    if (!uriResult) {
+      return {
+        status: "error",
+        error: "URI not supported",
+      };
     }
+
     let proposalId: number;
     let checkResult: CheckPayResult;
     try {
-      proposalId = await this.downloadProposal(url, downloadSessionId);
+      proposalId = await this.downloadProposal(
+        uriResult.downloadUrl,
+        uriResult.sessionId,
+      );
       checkResult = await this.checkPay(proposalId);
     } catch (e) {
       return {
@@ -736,11 +753,35 @@ export class Wallet {
     if (!proposal) {
       throw Error("could not get proposal");
     }
+
+    console.log("proposal", proposal);
+
+    if (uriResult.sessionId) {
+      const existingPayment = await this.q().getIndexed(
+        Stores.purchases.fulfillmentUrlIndex,
+        proposal.contractTerms.fulfillment_url,
+      );
+      if (existingPayment) {
+        console.log("existing payment", existingPayment);
+        await this.submitPay(
+          existingPayment.contractTermsHash,
+          uriResult.sessionId,
+        );
+        return {
+          status: "paid",
+          contractTerms: existingPayment.contractTerms,
+          nextUrl: this.getNextUrl(existingPayment.contractTerms),
+        };
+      }
+    }
+
     if (checkResult.status === "paid") {
+      const nextUrl = this.getNextUrl(proposal.contractTerms);
       return {
         status: "paid",
         contractTerms: proposal.contractTerms,
         proposalId: proposal.id!,
+        nextUrl,
       };
     }
     if (checkResult.status === "insufficient-balance") {
@@ -882,14 +923,6 @@ export class Wallet {
       modifiedCoins.push(c);
     }
 
-    const fu = new URI(purchase.contractTerms.fulfillment_url);
-    fu.addSearch("order_id", purchase.contractTerms.order_id);
-    if (merchantResp.session_sig) {
-      purchase.lastSessionSig = merchantResp.session_sig;
-      purchase.lastSessionId = sessionId;
-      fu.addSearch("session_sig", merchantResp.session_sig);
-    }
-
     await this.q()
       .putAll(Stores.coins, modifiedCoins)
       .put(Stores.purchases, purchase)
@@ -898,7 +931,7 @@ export class Wallet {
       this.refresh(c.coin_pub);
     }
 
-    const nextUrl = fu.href();
+    const nextUrl = this.getNextUrl(purchase.contractTerms);
     this.cachedNextUrl[purchase.contractTerms.fulfillment_url] = {
       nextUrl,
       lastSessionId: sessionId,
@@ -1120,6 +1153,54 @@ export class Wallet {
     return t;
   }
 
+  private async sendReserveInfoToBank(reservePub: string) {
+    const reserve = await this.q().get<ReserveRecord>(
+      Stores.reserves,
+      reservePub,
+    );
+    if (!reserve) {
+      throw Error("reserve not in db");
+    }
+
+    const bankStatusUrl = reserve.bankWithdrawStatusUrl;
+    if (!bankStatusUrl) {
+      throw Error("reserve not confirmed yet, and no status URL available.");
+    }
+
+    const now = new Date().getTime();
+    let status;
+    try {
+      const statusResp = await this.http.get(bankStatusUrl);
+      status = 
WithdrawOperationStatusResponse.checked(statusResp.responseJson);
+    } catch (e) {
+      console.log("bank error response", e);
+      throw e;
+    }
+
+    if (status.transfer_done) {
+      await this.q().mutate(Stores.reserves, reservePub, r => {
+        r.timestamp_confirmed = now;
+        return r;
+      });
+    } else if (reserve.timestamp_reserve_info_posted === 0) {
+      try {
+        if (!status.selection_done) {
+          const bankResp = await this.http.postJson(bankStatusUrl, {
+            reserve_pub: reservePub,
+            selected_exchange: reserve.exchangeWire,
+          });
+        }
+      } catch (e) {
+        console.log("bank error response", e);
+        throw e;
+      }
+      await this.q().mutate(Stores.reserves, reservePub, r => {
+        r.timestamp_reserve_info_posted = now;
+        return r;
+      });
+    }
+  }
+
   /**
    * First fetch information requred to withdraw from the reserve,
    * then deplete the reserve, withdrawing coins until it is empty.
@@ -1139,21 +1220,47 @@ export class Wallet {
     const op = openPromise<void>();
 
     const processReserveInternal = async (retryDelayMs: number = 250) => {
+      let isHardError = false;
+      // By default, do random, exponential backoff truncated at 3 minutes.
+      // Sometimes though, we want to try again faster.
+      let maxTimeout = 3000 * 60;
       try {
-        const reserve = await this.updateReserve(reservePub);
-        await this.depleteReserve(reserve);
+        const reserve = await this.q().get<ReserveRecord>(
+          Stores.reserves,
+          reservePub,
+        );
+        if (!reserve) {
+          isHardError = true;
+          throw Error("reserve not in db");
+        }
+
+        if (reserve.timestamp_confirmed === 0) {
+          const bankStatusUrl = reserve.bankWithdrawStatusUrl;
+          if (!bankStatusUrl) {
+            isHardError = true;
+            throw Error(
+              "reserve not confirmed yet, and no status URL available.",
+            );
+          }
+          maxTimeout = 2000;
+          /* This path is only taken if the wallet crashed after a withdraw 
was accepted,
+           * and before the information could be sent to the bank. */
+          await this.sendReserveInfoToBank(reservePub);
+          throw Error("waiting for reserve to be confirmed");
+        }
+
+        const updatedReserve = await this.updateReserve(reservePub);
+        await this.depleteReserve(updatedReserve);
         op.resolve();
       } catch (e) {
-        // random, exponential backoff truncated at 3 minutes
+        if (isHardError) {
+          op.reject(e);
+        }
         const nextDelay = Math.min(
           2 * retryDelayMs + retryDelayMs * Math.random(),
-          3000 * 60,
+          maxTimeout,
         );
-        Wallet.enableTracing &&
-          console.warn(
-            `Failed to deplete reserve, trying again in ${retryDelayMs} ms`,
-          );
-        Wallet.enableTracing && console.info("Cause for retry was:", e);
+
         this.timerGroup.after(retryDelayMs, () =>
           processReserveInternal(nextDelay),
         );
@@ -1346,7 +1453,10 @@ export class Wallet {
       reserve_pub: keypair.pub,
       senderWire: req.senderWire,
       timestamp_confirmed: 0,
+      timestamp_reserve_info_posted: 0,
       timestamp_depleted: 0,
+      bankWithdrawStatusUrl: req.bankWithdrawStatusUrl,
+      exchangeWire: req.exchangeWire,
     };
 
     const senderWire = req.senderWire;
@@ -1387,6 +1497,10 @@ export class Wallet {
       .put(Stores.reserves, reserveRecord)
       .finish();
 
+    if (req.bankWithdrawStatusUrl) {
+      this.processReserve(keypair.pub);
+    }
+
     const r: CreateReserveResponse = {
       exchange: canonExchange,
       reservePub: keypair.pub,
@@ -1513,6 +1627,7 @@ export class Wallet {
       }
 
       const preCoin = await this.cryptoApi.createPreCoin(denom, reserve);
+
       // This will fail and throw an exception if the remaining amount in the
       // reserve is too low to create a pre-coin.
       try {
@@ -1520,6 +1635,7 @@ export class Wallet {
           .put(Stores.precoins, preCoin)
           .mutate(Stores.reserves, reserve.reserve_pub, mutateReserve)
           .finish();
+        console.log("created precoin", preCoin.coinPub);
       } catch (e) {
         console.log("can't create pre-coin:", e.name, e.message);
         return;
@@ -1542,6 +1658,11 @@ export class Wallet {
     if (!reserve) {
       throw Error("reserve not in db");
     }
+
+    if (reserve.timestamp_confirmed === 0) {
+      throw Error("");
+    }
+
     const reqUrl = new URI("reserve/status").absoluteTo(
       reserve.exchange_base_url,
     );
@@ -1735,6 +1856,24 @@ export class Wallet {
     return { isTrusted, isAudited };
   }
 
+  async getWithdrawDetails(
+    talerPayUri: string,
+    maybeSelectedExchange?: string,
+  ): Promise<WithdrawDetails> {
+    const info = await this.downloadWithdrawInfo(talerPayUri);
+    let rci: ReserveCreationInfo | undefined = undefined;
+    if (maybeSelectedExchange) {
+      rci = await this.getReserveCreationInfo(
+        maybeSelectedExchange,
+        info.amount,
+      );
+    }
+    return {
+      withdrawInfo: info,
+      reserveCreationInfo: rci,
+    };
+  }
+
   async getReserveCreationInfo(
     baseUrl: string,
     amount: AmountJson,
@@ -2462,7 +2601,14 @@ export class Wallet {
       refreshSession.exchangeBaseUrl,
     );
     Wallet.enableTracing && console.log("reveal request:", req);
-    const resp = await this.http.postJson(reqUrl.href(), req);
+
+    let resp;
+    try {
+      resp = await this.http.postJson(reqUrl.href(), req);
+    } catch (e) {
+      console.error("got error during /refresh/reveal request");
+      return;
+    }
 
     Wallet.enableTracing && console.log("session:", refreshSession);
     Wallet.enableTracing && console.log("reveal response:", resp);
@@ -3407,16 +3553,6 @@ export class Wallet {
   }
 
   /**
-   * Synchronously get the paid URL for a resource from the plain fulfillment
-   * URL.  Returns undefined if the fulfillment URL is not a resource that was
-   * payed for, or if it is not cached anymore.  Use the asynchronous
-   * queryPaymentByFulfillmentUrl to avoid false negatives.
-   */
-  getNextUrlFromResourceUrl(resourceUrl: string): NextUrlResult | undefined {
-    return this.cachedNextUrl[resourceUrl];
-  }
-
-  /**
    * Remove unreferenced / expired data from the wallet's database
    * based on the current system time.
    */
@@ -3427,6 +3563,58 @@ export class Wallet {
     // strategy to test it.
   }
 
+  async downloadWithdrawInfo(
+    talerWithdrawUri: string,
+  ): Promise<DownloadedWithdrawInfo> {
+    const uriResult = parseWithdrawUri(talerWithdrawUri);
+    if (!uriResult) {
+      throw Error("can't parse URL");
+    }
+    const resp = await this.http.get(uriResult.statusUrl);
+    console.log("resp:", resp.responseJson);
+    const status = WithdrawOperationStatusResponse.checked(resp.responseJson);
+    return {
+      amount: Amounts.parseOrThrow(status.amount),
+      confirmTransferUrl: status.confirm_transfer_url,
+      extractedStatusUrl: uriResult.statusUrl,
+      selectionDone: status.selection_done,
+      senderWire: status.sender_wire,
+      suggestedExchange: status.suggested_exchange,
+      transferDone: status.transfer_done,
+      wireTypes: status.wire_types,
+    };
+  }
+
+  async acceptWithdrawal(
+    talerWithdrawUri: string,
+    selectedExchange: string,
+  ): Promise<AcceptWithdrawalResponse> {
+    const withdrawInfo = await this.downloadWithdrawInfo(talerWithdrawUri);
+    const exchangeWire = await this.getExchangePaytoUri(
+      selectedExchange,
+      withdrawInfo.wireTypes,
+    );
+    const reserve = await this.createReserve({
+      amount: withdrawInfo.amount,
+      bankWithdrawStatusUrl: withdrawInfo.extractedStatusUrl,
+      exchange: selectedExchange,
+      senderWire: withdrawInfo.senderWire,
+      exchangeWire: exchangeWire,
+    });
+    await this.sendReserveInfoToBank(reserve.reservePub);
+    return {
+      reservePub: reserve.reservePub,
+      confirmTransferUrl: withdrawInfo.confirmTransferUrl,
+    };
+  }
+
+  /**
+   * Reset the retry timeouts for ongoing operations.
+   */
+  resetRetryTimeouts(): void {
+    // FIXME: implement
+  }
+
   clearNotification(): void {
     this.badge.clearNotification();
   }
diff --git a/src/walletTypes.ts b/src/walletTypes.ts
index a74f8113..c657ac02 100644
--- a/src/walletTypes.ts
+++ b/src/walletTypes.ts
@@ -37,12 +37,7 @@ import {
   ExchangeWireFeesRecord,
   TipRecord,
 } from "./dbTypes";
-import {
-  CoinPaySig,
-  ContractTerms,
-  PayReq,
-} from "./talerTypes";
-
+import { CoinPaySig, ContractTerms, PayReq } from "./talerTypes";
 
 /**
  * Response for the create reserve request to the wallet.
@@ -69,7 +64,6 @@ export class CreateReserveResponse {
   static checked: (obj: any) => CreateReserveResponse;
 }
 
-
 /**
  * Information about what will happen when creating a reserve.
  *
@@ -138,7 +132,7 @@ export interface ReserveCreationInfo {
    *
    * Older exchanges don't return version information.
    */
-  versionMatch: LibtoolVersion.VersionMatchResult|undefined;
+  versionMatch: LibtoolVersion.VersionMatchResult | undefined;
 
   /**
    * Libtool-style version string for the exchange or "unknown"
@@ -152,6 +146,10 @@ export interface ReserveCreationInfo {
   walletVersion: string;
 }
 
+export interface WithdrawDetails {
+  withdrawInfo: DownloadedWithdrawInfo;
+  reserveCreationInfo: ReserveCreationInfo | undefined;
+}
 
 /**
  * Mapping from currency/exchange to detailed balance
@@ -169,7 +167,6 @@ export interface WalletBalance {
   byCurrency: { [currency: string]: WalletBalanceEntry };
 }
 
-
 /**
  * Detailed wallet balance for a particular currency.
  */
@@ -192,7 +189,6 @@ export interface WalletBalanceEntry {
   paybackAmount: AmountJson;
 }
 
-
 /**
  * Coins used for a payment, with signatures authorizing the payment and the
  * coins with remaining value updated to accomodate for a payment.
@@ -203,7 +199,6 @@ export interface PayCoinInfo {
   sigs: CoinPaySig[];
 }
 
-
 /**
  * Listener for notifications from the wallet.
  */
@@ -214,15 +209,17 @@ export interface Notifier {
   notify(): void;
 }
 
-
 /**
  * For terseness.
  */
-export function mkAmount(value: number, fraction: number, currency: string): 
AmountJson {
-  return {value, fraction, currency};
+export function mkAmount(
+  value: number,
+  fraction: number,
+  currency: string,
+): AmountJson {
+  return { value, fraction, currency };
 }
 
-
 /**
  * Possible results for checkPay.
  */
@@ -231,7 +228,6 @@ export interface CheckPayResult {
   coinSelection?: CoinSelectionResult;
 }
 
-
 /**
  * Result for confirmPay
  */
@@ -239,7 +235,6 @@ export interface ConfirmPayResult {
   nextUrl: string;
 }
 
-
 /**
  * Activity history record.
  */
@@ -266,7 +261,6 @@ export interface HistoryRecord {
   detail: any;
 }
 
-
 /**
  * Query payment response when the payment was found.
  */
@@ -274,7 +268,6 @@ export interface QueryPaymentNotFound {
   found: false;
 }
 
-
 /**
  * Query payment response when the payment wasn't found.
  */
@@ -288,7 +281,6 @@ export interface QueryPaymentFound {
   proposalId: number;
 }
 
-
 /**
  * Information about all sender wire details known to the wallet,
  * as well as exchanges that accept these wire types.
@@ -306,7 +298,6 @@ export interface SenderWireInfos {
   senderWires: string[];
 }
 
-
 /**
  * Request to mark a reserve as confirmed.
  */
@@ -325,6 +316,13 @@ export class CreateReserveRequest {
   exchange: string;
 
   /**
+   * Payto URI that identifies the exchange's account that the funds
+   * for this reserve go into.
+   */
+  @Checkable.String()
+  exchangeWire: string;
+
+  /**
    * Wire details (as a payto URI) for the bank account that sent the funds to
    * the exchange.
    */
@@ -332,13 +330,18 @@ export class CreateReserveRequest {
   senderWire?: string;
 
   /**
+   * URL to fetch the withdraw status from the bank.
+   */
+  @Checkable.Optional(Checkable.String())
+  bankWithdrawStatusUrl?: string;
+
+  /**
    * Verify that a value matches the schema of this class and convert it into a
    * member.
    */
   static checked: (obj: any) => CreateReserveRequest;
 }
 
-
 /**
  * Request to mark a reserve as confirmed.
  */
@@ -358,7 +361,6 @@ export class ConfirmReserveRequest {
   static checked: (obj: any) => ConfirmReserveRequest;
 }
 
-
 /**
  * Wire coins to the user's own bank account.
  */
@@ -390,7 +392,6 @@ export class ReturnCoinsRequest {
   static checked: (obj: any) => ReturnCoinsRequest;
 }
 
-
 /**
  * Result of selecting coins, contains the exchange, and selected
  * coins with their denomination.
@@ -405,7 +406,6 @@ export interface CoinSelectionResult {
   totalAmount: AmountJson;
 }
 
-
 /**
  * Named tuple of coin and denomination.
  */
@@ -433,7 +433,6 @@ export interface TipStatus {
   tipRecord?: TipRecord;
 }
 
-
 /**
  * Badge that shows activity for the wallet.
  */
@@ -464,7 +463,6 @@ export interface BenchmarkResult {
   repetitions: number;
 }
 
-
 /**
  * Cached next URL for a particular session id.
  */
@@ -473,10 +471,50 @@ export interface NextUrlResult {
   lastSessionId: string | undefined;
 }
 
-export interface PreparePayResult {
-  status: "paid" | "insufficient-balance" | "payment-possible" | "error";
+export type PreparePayResult =
+  | PreparePayResultError
+  | PreparePayResultInsufficientBalance
+  | PreparePayResultPaid
+  | PreparePayResultPaymentPossible;
+
+export interface PreparePayResultPaymentPossible {
+  status: "payment-possible";
+  proposalId?: number;
   contractTerms?: ContractTerms;
-  error?: string;
+  totalFees?: AmountJson;
+}
+
+export interface PreparePayResultInsufficientBalance {
+  status: "insufficient-balance";
   proposalId?: number;
+  contractTerms?: ContractTerms;
   totalFees?: AmountJson;
-}
\ No newline at end of file
+}
+
+export interface PreparePayResultError {
+  status: "error";
+  error: string;
+}
+
+export interface PreparePayResultPaid {
+  status: "paid";
+  proposalId?: number;
+  contractTerms?: ContractTerms;
+  nextUrl: string;
+}
+
+export interface DownloadedWithdrawInfo {
+  selectionDone: boolean;
+  transferDone: boolean;
+  amount: AmountJson;
+  senderWire?: string;
+  suggestedExchange?: string;
+  confirmTransferUrl?: string;
+  wireTypes: string[];
+  extractedStatusUrl: string;
+}
+
+export interface AcceptWithdrawalResponse {
+  reservePub: string;
+  confirmTransferUrl?: string;
+}
diff --git a/src/webex/messages.ts b/src/webex/messages.ts
index 8bb9cafe..ca0e1c7e 100644
--- a/src/webex/messages.ts
+++ b/src/webex/messages.ts
@@ -32,12 +32,12 @@ import { UpgradeResponse } from "./wxApi";
  * Message type information.
  */
 export interface MessageMap {
-  "balances": {
-    request: { };
+  balances: {
+    request: {};
     response: walletTypes.WalletBalance;
   };
   "dump-db": {
-    request: { };
+    request: {};
     response: any;
   };
   "import-db": {
@@ -46,18 +46,18 @@ export interface MessageMap {
     };
     response: void;
   };
-  "ping": {
-    request: { };
+  ping: {
+    request: {};
     response: void;
   };
   "reset-db": {
-    request: { };
+    request: {};
     response: void;
   };
   "create-reserve": {
     request: {
       amount: AmountJson;
-      exchange: string
+      exchange: string;
     };
     response: void;
   };
@@ -70,11 +70,11 @@ export interface MessageMap {
     response: walletTypes.ConfirmPayResult;
   };
   "check-pay": {
-    request: { proposalId: number; };
+    request: { proposalId: number };
     response: walletTypes.CheckPayResult;
   };
   "query-payment": {
-    request: { };
+    request: {};
     response: dbTypes.PurchaseRecord;
   };
   "exchange-info": {
@@ -90,11 +90,11 @@ export interface MessageMap {
     response: string;
   };
   "reserve-creation-info": {
-    request: { baseUrl: string, amount: AmountJson };
+    request: { baseUrl: string; amount: AmountJson };
     response: walletTypes.ReserveCreationInfo;
   };
   "get-history": {
-    request: { };
+    request: {};
     response: walletTypes.HistoryRecord[];
   };
   "get-proposal": {
@@ -110,7 +110,7 @@ export interface MessageMap {
     response: any;
   };
   "get-currencies": {
-    request: { };
+    request: {};
     response: dbTypes.CurrencyRecord[];
   };
   "update-currency": {
@@ -118,7 +118,7 @@ export interface MessageMap {
     response: void;
   };
   "get-exchanges": {
-    request: { };
+    request: {};
     response: dbTypes.ExchangeRecord[];
   };
   "get-reserves": {
@@ -126,7 +126,7 @@ export interface MessageMap {
     response: dbTypes.ReserveRecord[];
   };
   "get-payback-reserves": {
-    request: { };
+    request: {};
     response: dbTypes.ReserveRecord[];
   };
   "withdraw-payback-reserve": {
@@ -146,15 +146,15 @@ export interface MessageMap {
     response: void;
   };
   "check-upgrade": {
-    request: { };
+    request: {};
     response: UpgradeResponse;
   };
   "get-sender-wire-infos": {
-    request: { };
+    request: {};
     response: walletTypes.SenderWireInfos;
   };
   "return-coins": {
-    request: { };
+    request: {};
     response: void;
   };
   "log-and-display-error": {
@@ -182,7 +182,7 @@ export interface MessageMap {
     response: walletTypes.TipStatus;
   };
   "clear-notification": {
-    request: { };
+    request: {};
     response: void;
   };
   "taler-pay": {
@@ -194,23 +194,36 @@ export interface MessageMap {
     response: number;
   };
   "submit-pay": {
-    request: { contractTermsHash: string, sessionId: string | undefined };
+    request: { contractTermsHash: string; sessionId: string | undefined };
     response: walletTypes.ConfirmPayResult;
   };
   "accept-refund": {
-    request: { refundUrl: string }
+    request: { refundUrl: string };
     response: string;
   };
   "abort-failed-payment": {
-    request: { contractTermsHash: string }
+    request: { contractTermsHash: string };
     response: void;
   };
   "benchmark-crypto": {
-    request: { repetitions: number }
+    request: { repetitions: number };
     response: walletTypes.BenchmarkResult;
   };
+  "get-withdraw-details": {
+    request: { talerWithdrawUri: string; maybeSelectedExchange: string | 
undefined };
+    response: walletTypes.WithdrawDetails;
+  };
+  "accept-withdrawal": {
+    request: { talerWithdrawUri: string; selectedExchange: string };
+    response: walletTypes.AcceptWithdrawalResponse;
+  };
+  "prepare-pay": {
+    request: { talerPayUri: string };
+    response: walletTypes.PreparePayResult;
+  };
 }
 
+
 /**
  * String literal types for messages.
  */
@@ -219,14 +232,19 @@ export type MessageType = keyof MessageMap;
 /**
  * Make a request whose details match the request type.
  */
-export function makeRequest<T extends MessageType>(type: T, details: 
MessageMap[T]["request"]) {
+export function makeRequest<T extends MessageType>(
+  type: T,
+  details: MessageMap[T]["request"],
+) {
   return { type, details };
 }
 
 /**
  * Make a response that matches the request type.
  */
-export function makeResponse<T extends MessageType>(type: T, response: 
MessageMap[T]["response"]) {
+export function makeResponse<T extends MessageType>(
+  type: T,
+  response: MessageMap[T]["response"],
+) {
   return response;
 }
-
diff --git a/src/webex/pages/confirm-contract.tsx 
b/src/webex/pages/confirm-contract.tsx
deleted file mode 100644
index d2461379..00000000
--- a/src/webex/pages/confirm-contract.tsx
+++ /dev/null
@@ -1,417 +0,0 @@
-/*
- This file is part of TALER
- (C) 2015 GNUnet e.V.
-
- 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.
-
- 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
- TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
- */
-
-/**
- * Page shown to the user to confirm entering
- * a contract.
- */
-
-
-/**
- * Imports.
- */
-import * as i18n from "../../i18n";
-
-import { runOnceWhenReady } from "./common";
-
-import {
-  ExchangeRecord,
-  ProposalDownloadRecord,
-} from "../../dbTypes";
-import { ContractTerms } from "../../talerTypes";
-import {
-  CheckPayResult,
-} from "../../walletTypes";
-
-import { renderAmount } from "../renderHtml";
-import * as wxApi from "../wxApi";
-
-import * as React from "react";
-import * as ReactDOM from "react-dom";
-import URI = require("urijs");
-import { WalletApiError } from "../wxApi";
-
-import * as Amounts from "../../amounts";
-
-
-interface DetailState {
-  collapsed: boolean;
-}
-
-interface DetailProps {
-  contractTerms: ContractTerms;
-  collapsed: boolean;
-  exchanges: ExchangeRecord[] | undefined;
-}
-
-
-class Details extends React.Component<DetailProps, DetailState> {
-  constructor(props: DetailProps) {
-    super(props);
-    console.log("new Details component created");
-    this.state = {
-      collapsed: props.collapsed,
-    };
-
-    console.log("initial state:", this.state);
-  }
-
-  render() {
-    if (this.state.collapsed) {
-      return (
-        <div>
-          <button className="linky"
-                  onClick={() => { this.setState({collapsed: false} as any); 
}}>
-          <i18n.Translate wrap="span">
-            show more details
-          </i18n.Translate>
-          </button>
-        </div>
-      );
-    } else {
-      return (
-        <div>
-          <button className="linky"
-                  onClick={() => this.setState({collapsed: true} as any)}>
-            i18n.str`show fewer details`
-          </button>
-          <div>
-            {i18n.str`Accepted exchanges:`}
-            <ul>
-              {this.props.contractTerms.exchanges.map(
-                (e) => <li>{`${e.url}: ${e.master_pub}`}</li>)}
-            </ul>
-            {i18n.str`Exchanges in the wallet:`}
-            <ul>
-              {(this.props.exchanges || []).map(
-                (e: ExchangeRecord) =>
-                  <li>{`${e.baseUrl}: ${e.masterPublicKey}`}</li>)}
-            </ul>
-          </div>
-        </div>);
-    }
-  }
-}
-
-interface ContractPromptProps {
-  proposalId?: number;
-  contractUrl?: string;
-  sessionId?: string;
-  resourceUrl?: string;
-}
-
-interface ContractPromptState {
-  proposalId: number | undefined;
-  proposal: ProposalDownloadRecord | undefined;
-  checkPayError: string | undefined;
-  confirmPayError: object | undefined;
-  payDisabled: boolean;
-  alreadyPaid: boolean;
-  exchanges: ExchangeRecord[] | undefined;
-  /**
-   * Don't request updates to proposal state while
-   * this is set to true, to avoid UI flickering
-   * when pressing pay.
-   */
-  holdCheck: boolean;
-  payStatus?: CheckPayResult;
-  replaying: boolean;
-  payInProgress: boolean;
-  payAttempt: number;
-  working: boolean;
-  abortDone: boolean;
-  abortStarted: boolean;
-}
-
-class ContractPrompt extends React.Component<ContractPromptProps, 
ContractPromptState> {
-  constructor(props: ContractPromptProps) {
-    super(props);
-    this.state = {
-      abortDone: false,
-      abortStarted: false,
-      alreadyPaid: false,
-      checkPayError: undefined,
-      confirmPayError: undefined,
-      exchanges: undefined,
-      holdCheck: false,
-      payAttempt: 0,
-      payDisabled: true,
-      payInProgress: false,
-      proposal: undefined,
-      proposalId: props.proposalId,
-      replaying: false,
-      working: false,
-    };
-  }
-
-  componentWillMount() {
-    this.update();
-  }
-
-  componentWillUnmount() {
-    // FIXME: abort running ops
-  }
-
-  async update() {
-    if (this.props.resourceUrl) {
-      const p = await 
wxApi.queryPaymentByFulfillmentUrl(this.props.resourceUrl);
-      console.log("query for resource url", this.props.resourceUrl, "result", 
p);
-      if (p && p.finished) {
-        if (p.lastSessionSig === undefined || p.lastSessionSig === 
this.props.sessionId) {
-          const nextUrl = new URI(p.contractTerms.fulfillment_url);
-          nextUrl.addSearch("order_id", p.contractTerms.order_id);
-          if (p.lastSessionSig) {
-            nextUrl.addSearch("session_sig", p.lastSessionSig);
-          }
-          location.replace(nextUrl.href());
-          return;
-        } else {
-          // We're in a new session
-          this.setState({ replaying: true });
-          // FIXME:  This could also go wrong.  However the payment
-          // was already successful once, so we can just retry and not refund 
it.
-          const payResult = await wxApi.submitPay(p.contractTermsHash, 
this.props.sessionId);
-          console.log("payResult", payResult);
-          location.replace(payResult.nextUrl);
-          return;
-        }
-      }
-    }
-    let proposalId = this.props.proposalId;
-    if (proposalId === undefined) {
-      if (this.props.contractUrl === undefined) {
-        // Nothing we can do ...
-        return;
-      }
-      proposalId = await wxApi.downloadProposal(this.props.contractUrl);
-    }
-    const proposal = await wxApi.getProposal(proposalId);
-    this.setState({ proposal, proposalId });
-    this.checkPayment();
-    const exchanges = await wxApi.getExchanges();
-    this.setState({ exchanges });
-  }
-
-  async checkPayment() {
-    window.setTimeout(() => this.checkPayment(), 500);
-    if (this.state.holdCheck) {
-      return;
-    }
-    const proposalId = this.state.proposalId;
-    if (proposalId === undefined) {
-      return;
-    }
-    const payStatus = await wxApi.checkPay(proposalId);
-    if (payStatus.status === "insufficient-balance") {
-      const msgInsufficient = i18n.str`You have insufficient funds of the 
requested currency in your wallet.`;
-      // tslint:disable-next-line:max-line-length
-      const msgNoMatch = i18n.str`You do not have any funds from an exchange 
that is accepted by this merchant. None of the exchanges accepted by the 
merchant is known to your wallet.`;
-      if (this.state.exchanges && this.state.proposal) {
-        const acceptedExchangePubs = 
this.state.proposal.contractTerms.exchanges.map((e) => e.master_pub);
-        const ex = this.state.exchanges.find((e) => 
acceptedExchangePubs.indexOf(e.masterPublicKey) >= 0);
-        if (ex) {
-          this.setState({ checkPayError: msgInsufficient });
-        } else {
-          this.setState({ checkPayError: msgNoMatch });
-        }
-      } else {
-        this.setState({ checkPayError: msgInsufficient });
-      }
-      this.setState({ payDisabled: true });
-    } else if (payStatus.status === "paid") {
-      this.setState({ alreadyPaid: true, payDisabled: false, checkPayError: 
undefined, payStatus });
-    } else {
-      this.setState({ payDisabled: false, checkPayError: undefined, payStatus 
});
-    }
-  }
-
-  async doPayment() {
-    const proposal = this.state.proposal;
-    this.setState({ holdCheck: true, payAttempt: this.state.payAttempt + 1});
-    if (!proposal) {
-      return;
-    }
-    const proposalId = proposal.id;
-    if (proposalId === undefined) {
-      console.error("proposal has no id");
-      return;
-    }
-    console.log("confirmPay with", proposalId, "and", this.props.sessionId);
-    let payResult;
-    this.setState({ working: true });
-    try {
-      payResult = await wxApi.confirmPay(proposalId, this.props.sessionId);
-    } catch (e) {
-      if (!(e instanceof WalletApiError)) {
-        throw e;
-      }
-      this.setState({ confirmPayError: e.detail });
-      return;
-    }
-    console.log("payResult", payResult);
-    document.location.replace(payResult.nextUrl);
-    this.setState({ holdCheck: true });
-  }
-
-
-  async abortPayment() {
-    const proposal = this.state.proposal;
-    this.setState({ holdCheck: true, abortStarted: true });
-    if (!proposal) {
-      return;
-    }
-    wxApi.abortFailedPayment(proposal.contractTermsHash);
-    this.setState({ abortDone: true });
-  }
-
-
-  render() {
-    if (this.props.contractUrl === undefined && this.props.proposalId === 
undefined) {
-      return <span>Error: either contractUrl or proposalId must be 
given</span>;
-    }
-    if (this.state.replaying) {
-      return <span>Re-submitting existing payment</span>;
-    }
-    if (this.state.proposalId === undefined) {
-      return <span>Downloading contract terms</span>;
-    }
-    if (!this.state.proposal) {
-      return <span>...</span>;
-    }
-    const c = this.state.proposal.contractTerms;
-    let merchantName;
-    if (c.merchant && c.merchant.name) {
-      merchantName = <strong>{c.merchant.name}</strong>;
-    } else {
-      merchantName = <strong>(pub: {c.merchant_pub})</strong>;
-    }
-    const amount = 
<strong>{renderAmount(Amounts.parseOrThrow(c.amount))}</strong>;
-    console.log("payStatus", this.state.payStatus);
-
-    let products = null;
-    if (c.products.length) {
-      products = (
-        <div>
-          <span>The following items are included:</span>
-          <ul>
-            {c.products.map(
-              (p: any, i: number) => (<li key={i}>{p.description}: 
{renderAmount(p.price)}</li>))
-            }
-          </ul>
-      </div>
-      );
-    }
-
-    const ConfirmButton = () => (
-      <button className="pure-button button-success"
-              disabled={this.state.payDisabled}
-              onClick={() => this.doPayment()}>
-        {i18n.str`Confirm payment`}
-      </button>
-    );
-
-    const WorkingButton = () => (
-      <div>
-      <button className="pure-button button-success"
-              disabled={this.state.payDisabled}
-              onClick={() => this.doPayment()}>
-        <span><object className="svg-icon svg-baseline" 
data="/img/spinner-bars.svg" /> </span>
-        {i18n.str`Submitting payment`}
-      </button>
-      </div>
-    );
-
-    const ConfirmPayDialog = () => (
-      <div>
-        {this.state.working ? WorkingButton() : ConfirmButton()}
-        <div>
-          {(this.state.alreadyPaid
-            ? <p className="okaybox">
-              {i18n.str`You already paid for this, clicking "Confirm payment" 
will not cost money again.`}
-              </p>
-            : <p />)}
-          {(this.state.checkPayError ? <p 
className="errorbox">{this.state.checkPayError}</p> : <p />)}
-        </div>
-        <Details exchanges={this.state.exchanges} contractTerms={c} 
collapsed={!this.state.checkPayError}/>
-      </div>
-    );
-
-    const PayErrorDialog = () => (
-      <div>
-        <p>There was an error paying (attempt #{this.state.payAttempt}):</p>
-        <pre>{JSON.stringify(this.state.confirmPayError)}</pre>
-        { this.state.abortStarted
-        ? <span>{i18n.str`Aborting payment ...`}</span>
-        : this.state.abortDone
-        ? <span>{i18n.str`Payment aborted!`}</span>
-        : <>
-            <button className="pure-button" onClick={() => this.doPayment()}>
-            {i18n.str`Retry Payment`}
-            </button>
-            <button className="pure-button" onClick={() => 
this.abortPayment()}>
-            {i18n.str`Abort Payment`}
-            </button>
-          </>
-        }
-      </div>
-    );
-
-    return (
-        <div>
-          <i18n.Translate wrap="p">
-            The merchant{" "}<span>{merchantName}</span> offers you to 
purchase:
-          </i18n.Translate>
-          <div style={{"textAlign": "center"}}>
-            <strong>{c.summary}</strong>
-          </div>
-          <strong></strong>
-          {products}
-          {(this.state.payStatus && this.state.payStatus.coinSelection)
-            ? <i18n.Translate wrap="p">
-                The total price is <span>{amount} </span>
-                (plus 
<span>{renderAmount(this.state.payStatus.coinSelection.totalFees)}</span> fees).
-              </i18n.Translate>
-            :
-            <i18n.Translate wrap="p">The total price is 
<span>{amount}</span>.</i18n.Translate>
-          }
-          { this.state.confirmPayError
-            ? PayErrorDialog()
-            : ConfirmPayDialog()
-          }
-        </div>
-    );
-  }
-}
-
-
-runOnceWhenReady(() => {
-  const url = new URI(document.location.href);
-  const query: any = URI.parseQuery(url.query());
-
-  let proposalId;
-  try {
-    proposalId = JSON.parse(query.proposalId);
-  } catch  {
-    // ignore error
-  }
-  const sessionId = query.sessionId;
-  const contractUrl = query.contractUrl;
-  const resourceUrl = query.resourceUrl;
-
-  ReactDOM.render(
-    <ContractPrompt {...{ proposalId, contractUrl, sessionId, resourceUrl }}/>,
-    document.getElementById("contract")!);
-});
diff --git a/src/webex/pages/confirm-create-reserve.tsx 
b/src/webex/pages/confirm-create-reserve.tsx
deleted file mode 100644
index 2d4f41df..00000000
--- a/src/webex/pages/confirm-create-reserve.tsx
+++ /dev/null
@@ -1,526 +0,0 @@
-/*
- This file is part of TALER
- (C) 2015-2016 GNUnet e.V.
-
- 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.
-
- 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
- TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
- */
-
-
-/**
- * Page shown to the user to confirm creation
- * of a reserve, usually requested by the bank.
- *
- * @author Florian Dold
- */
-
-import { canonicalizeBaseUrl } from "../../helpers";
-import * as i18n from "../../i18n";
-
-import { AmountJson } from "../../amounts";
-import * as Amounts from "../../amounts";
-
-import {
-  CurrencyRecord,
-} from "../../dbTypes";
-import {
-  CreateReserveResponse,
-  ReserveCreationInfo,
-} from "../../walletTypes";
-
-import { ImplicitStateComponent, StateHolder } from "../components";
-import {
-  WalletApiError,
-  createReserve,
-  getCurrency,
-  getExchangeInfo,
-  getReserveCreationInfo,
-} from "../wxApi";
-
-import {
-  WithdrawDetailView,
-  renderAmount,
-} from "../renderHtml";
-
-import * as React from "react";
-import * as ReactDOM from "react-dom";
-import URI = require("urijs");
-
-
-function delay<T>(delayMs: number, value: T): Promise<T> {
-  return new Promise<T>((resolve, reject) => {
-    setTimeout(() => resolve(value), delayMs);
-  });
-}
-
-class EventTrigger {
-  private triggerResolve: any;
-  private triggerPromise: Promise<boolean>;
-
-  constructor() {
-    this.reset();
-  }
-
-  private reset() {
-    this.triggerPromise = new Promise<boolean>((resolve, reject) => {
-      this.triggerResolve = resolve;
-    });
-  }
-
-  trigger() {
-    this.triggerResolve(false);
-    this.reset();
-  }
-
-  async wait(delayMs: number): Promise<boolean> {
-    return await Promise.race([this.triggerPromise, delay(delayMs, true)]);
-  }
-}
-
-
-interface ExchangeSelectionProps {
-  suggestedExchangeUrl: string;
-  amount: AmountJson;
-  callback_url: string;
-  wt_types: string[];
-  currencyRecord: CurrencyRecord|null;
-  sender_wire: string | undefined;
-}
-
-interface ManualSelectionProps {
-  onSelect(url: string): void;
-  initialUrl: string;
-}
-
-class ManualSelection extends ImplicitStateComponent<ManualSelectionProps> {
-  private url: StateHolder<string> = this.makeState("");
-  private errorMessage: StateHolder<string|null> = this.makeState(null);
-  private isOkay: StateHolder<boolean> = this.makeState(false);
-  private updateEvent = new EventTrigger();
-  constructor(p: ManualSelectionProps) {
-    super(p);
-    this.url(p.initialUrl);
-    this.update();
-  }
-  render() {
-    return (
-      <div className="pure-g pure-form pure-form-stacked">
-        <div className="pure-u-1">
-          <label>URL</label>
-          <input className="url" type="text" spellCheck={false}
-                 value={this.url()}
-                 key="exchange-url-input"
-                 onInput={(e) => this.onUrlChanged((e.target as 
HTMLInputElement).value)}
-                 onChange={(e) => this.onUrlChanged((e.target as 
HTMLInputElement).value)} />
-        </div>
-        <div className="pure-u-1">
-          <button className="pure-button button-success"
-                  disabled={!this.isOkay()}
-                  onClick={() => this.props.onSelect(this.url())}>
-            {i18n.str`Select`}
-          </button>
-          <span> </span>
-          {this.errorMessage()}
-        </div>
-      </div>
-    );
-  }
-
-  async update() {
-    this.errorMessage(null);
-    this.isOkay(false);
-    if (!this.url()) {
-      return;
-    }
-    const parsedUrl = new URI(this.url()!);
-    if (parsedUrl.is("relative")) {
-      this.errorMessage(i18n.str`Error: URL may not be relative`);
-      this.isOkay(false);
-      return;
-    }
-    try {
-      const url = canonicalizeBaseUrl(this.url()!);
-      await getExchangeInfo(url);
-      console.log("getExchangeInfo returned");
-      this.isOkay(true);
-    } catch (e) {
-      if (!(e instanceof WalletApiError)) {
-        // maybe it's something more serious, don't handle here!
-        throw e;
-      }
-      console.log(`got error "${e.message} "with detail`, e.detail);
-      this.errorMessage(i18n.str`Invalid exchange URL (${e.message})`);
-    }
-  }
-
-  async onUrlChanged(s: string) {
-    this.url(s);
-    this.errorMessage(null);
-    this.isOkay(false);
-    this.updateEvent.trigger();
-    const waited = await this.updateEvent.wait(200);
-    if (waited) {
-      // Run the actual update if nobody else preempted us.
-      this.update();
-    }
-  }
-}
-
-
-class ExchangeSelection extends ImplicitStateComponent<ExchangeSelectionProps> 
{
-  private statusString: StateHolder<string|null> = this.makeState(null);
-  private reserveCreationInfo: StateHolder<ReserveCreationInfo|null> = 
this.makeState(
-    null);
-  private url: StateHolder<string|null> = this.makeState(null);
-
-  private selectingExchange: StateHolder<boolean> = this.makeState(false);
-
-  constructor(props: ExchangeSelectionProps) {
-    super(props);
-    const prefilledExchangesUrls = [];
-    if (props.currencyRecord) {
-      const exchanges = props.currencyRecord.exchanges.map((x) => x.baseUrl);
-      prefilledExchangesUrls.push(...exchanges);
-    }
-    if (props.suggestedExchangeUrl) {
-      prefilledExchangesUrls.push(props.suggestedExchangeUrl);
-    }
-    if (prefilledExchangesUrls.length !== 0) {
-      this.url(prefilledExchangesUrls[0]);
-      this.forceReserveUpdate();
-    } else {
-      this.selectingExchange(true);
-    }
-  }
-
-  renderFeeStatus() {
-    const rci = this.reserveCreationInfo();
-    if (rci) {
-      const totalCost = Amounts.add(rci.overhead, rci.withdrawFee).amount;
-      let trustMessage;
-      if (rci.isTrusted) {
-        trustMessage = (
-          <i18n.Translate wrap="p">
-            The exchange is trusted by the wallet.
-          </i18n.Translate>
-        );
-      } else if (rci.isAudited) {
-        trustMessage = (
-          <i18n.Translate wrap="p">
-            The exchange is audited by a trusted auditor.
-          </i18n.Translate>
-        );
-      } else {
-        trustMessage = (
-          <i18n.Translate wrap="p">
-            Warning:  The exchange is neither directly trusted nor audited by 
a trusted auditor.
-            If you withdraw from this exchange, it will be trusted in the 
future.
-          </i18n.Translate>
-        );
-      }
-      return (
-        <div>
-        <i18n.Translate wrap="p">
-          Using exchange provider <strong>{this.url()}</strong>.
-          The exchange provider will charge
-          {" "}<span>{renderAmount(totalCost)}</span>{" "}
-          in fees.
-        </i18n.Translate>
-        {trustMessage}
-        </div>
-      );
-    }
-    if (this.url() && !this.statusString()) {
-      const shortName = new URI(this.url()!).host();
-      return (
-        <i18n.Translate wrap="p">
-          Waiting for a response from
-          <span> </span>
-          <em>{shortName}</em>
-        </i18n.Translate>
-      );
-    }
-    if (this.statusString()) {
-      return (
-        <p>
-          <strong style={{color: "red"}}>{this.statusString()}</strong>
-        </p>
-      );
-    }
-    return (
-      <p>
-        {i18n.str`Information about fees will be available when an exchange 
provider is selected.`}
-      </p>
-    );
-  }
-
-  renderUpdateStatus() {
-    const rci = this.reserveCreationInfo();
-    if (!rci) {
-      return null;
-    }
-    if (!rci.versionMatch) {
-      return null;
-    }
-    if (rci.versionMatch.compatible) {
-      return null;
-    }
-    if (rci.versionMatch.currentCmp === -1) {
-      return (
-        <p className="errorbox">
-          <i18n.Translate wrap="span">
-          Your wallet (protocol version <span>{rci.walletVersion}</span>) 
might be outdated.<span> </span>
-          The exchange has a higher, incompatible
-          protocol version (<span>{rci.exchangeVersion}</span>).
-          </i18n.Translate>
-        </p>
-      );
-    }
-    if (rci.versionMatch.currentCmp === 1) {
-      return (
-        <p className="errorbox">
-          <i18n.Translate wrap="span">
-          The chosen exchange (protocol version 
<span>{rci.exchangeVersion}</span> might be outdated.<span> </span>
-          The exchange has a lower, incompatible
-          protocol version than your wallet (protocol version 
<span>{rci.walletVersion}</span>).
-          </i18n.Translate>
-        </p>
-      );
-    }
-    throw Error("not reached");
-  }
-
-  renderConfirm() {
-    return (
-      <div>
-        {this.renderFeeStatus()}
-        <p>
-        <button className="pure-button button-success"
-                disabled={this.reserveCreationInfo() === null}
-                onClick={() => this.confirmReserve()}>
-          {i18n.str`Accept fees and withdraw`}
-        </button>
-        { " " }
-        <button className="pure-button button-secondary"
-                onClick={() => this.selectingExchange(true)}>
-          {i18n.str`Change Exchange Provider`}
-        </button>
-        </p>
-        {this.renderUpdateStatus()}
-        <WithdrawDetailView rci={this.reserveCreationInfo()} />
-      </div>
-    );
-  }
-
-  select(url: string) {
-    this.reserveCreationInfo(null);
-    this.url(url);
-    this.selectingExchange(false);
-    this.forceReserveUpdate();
-  }
-
-  renderSelect() {
-    const exchanges = (this.props.currencyRecord && 
this.props.currencyRecord.exchanges) || [];
-    console.log(exchanges);
-    return (
-      <div>
-        {i18n.str`Please select an exchange.  You can review the details 
before after your selection.`}
-
-        {this.props.suggestedExchangeUrl && (
-          <div>
-            <h2>Bank Suggestion</h2>
-            <button className="pure-button button-success" onClick={() => 
this.select(this.props.suggestedExchangeUrl)}>
-              <i18n.Translate wrap="span">
-              Select <strong>{this.props.suggestedExchangeUrl}</strong>
-              </i18n.Translate>
-            </button>
-          </div>
-        )}
-
-        {exchanges.length > 0 && (
-          <div>
-            <h2>Known Exchanges</h2>
-            {exchanges.map((e) => (
-              <button key={e.baseUrl} className="pure-button button-success" 
onClick={() => this.select(e.baseUrl)}>
-                <i18n.Translate>
-                Select <strong>{e.baseUrl}</strong>
-                </i18n.Translate>
-              </button>
-            ))}
-          </div>
-        )}
-
-        <h2>i18n.str`Manual Selection`</h2>
-        <ManualSelection initialUrl={this.url() || ""} onSelect={(url: string) 
=> this.select(url)} />
-      </div>
-    );
-  }
-
-  render(): JSX.Element {
-    return (
-      <div>
-        <i18n.Translate wrap="p">
-          You are about to withdraw
-          {" "}<strong>{renderAmount(this.props.amount)}</strong>{" "}
-          from your bank account into your wallet.
-        </i18n.Translate>
-        {this.selectingExchange() ? this.renderSelect() : this.renderConfirm()}
-      </div>
-    );
-  }
-
-
-  confirmReserve() {
-    this.confirmReserveImpl(this.reserveCreationInfo()!,
-                            this.url()!,
-                            this.props.amount,
-                            this.props.callback_url,
-                            this.props.sender_wire);
-  }
-
-  /**
-   * Do an update of the reserve creation info, without any debouncing.
-   */
-  async forceReserveUpdate() {
-    this.reserveCreationInfo(null);
-    try {
-      const url = canonicalizeBaseUrl(this.url()!);
-      const r = await getReserveCreationInfo(url,
-                                           this.props.amount);
-      console.log("get exchange info resolved");
-      this.reserveCreationInfo(r);
-      console.dir(r);
-    } catch (e) {
-      console.log("get exchange info rejected", e);
-      this.statusString(`Error: ${e.message}`);
-      // Re-try every 5 seconds as long as there is a problem
-      setTimeout(() => this.statusString() ? this.forceReserveUpdate() : 
undefined, 5000);
-    }
-  }
-
-  async confirmReserveImpl(rci: ReserveCreationInfo,
-                           exchange: string,
-                           amount: AmountJson,
-                           callback_url: string,
-                           sender_wire: string | undefined) {
-    const rawResp = await createReserve({
-      amount,
-      exchange: canonicalizeBaseUrl(exchange),
-      senderWire: sender_wire,
-    });
-    if (!rawResp) {
-      throw Error("empty response");
-    }
-    // FIXME: filter out types that bank/exchange don't have in common
-    const exchangeWireAccounts = [];
-
-    for (let acct of rci.exchangeWireAccounts) {
-      const payto = new URI(acct);
-      if (payto.scheme() != "payto") {
-        console.warn("unknown wire account URI scheme", acct);
-        continue;
-      }
-      if (this.props.wt_types.includes(payto.authority())) {
-        exchangeWireAccounts.push(acct);
-      }
-    }
-
-    const chosenAcct = exchangeWireAccounts[0];
-
-    if (!chosenAcct) {
-      throw Error("no exchange account matches the bank's supported types");
-    }
-
-    if (!rawResp.error) {
-      const resp = CreateReserveResponse.checked(rawResp);
-      const q: {[name: string]: string|number} = {
-        amount_currency: amount.currency,
-        amount_fraction: amount.fraction,
-        amount_value: amount.value,
-        exchange: resp.exchange,
-        exchange_wire_details: chosenAcct,
-        reserve_pub: resp.reservePub,
-      };
-      const url = new URI(callback_url).addQuery(q);
-      if (!url.is("absolute")) {
-        throw Error("callback url is not absolute");
-      }
-      console.log("going to", url.href());
-      document.location.href = url.href();
-    } else {
-      this.statusString(
-        i18n.str`Oops, something went wrong. The wallet responded with error 
status (${rawResp.error}).`);
-    }
-  }
-
-  renderStatus(): any {
-    if (this.statusString()) {
-      return <p><strong style={{color: 
"red"}}>{this.statusString()}</strong></p>;
-    } else if (!this.reserveCreationInfo()) {
-      return <p>{i18n.str`Checking URL, please wait ...`}</p>;
-    }
-    return "";
-  }
-}
-
-async function main() {
-  try {
-    const url = new URI(document.location.href);
-    const query: any = URI.parseQuery(url.query());
-    let amount;
-    try {
-      amount = AmountJson.checked(JSON.parse(query.amount));
-    } catch (e) {
-      throw Error(i18n.str`Can't parse amount: ${e.message}`);
-    }
-    const callback_url = query.callback_url;
-    let wt_types;
-    try {
-      wt_types = JSON.parse(query.wt_types);
-    } catch (e) {
-      throw Error(i18n.str`Can't parse wire_types: ${e.message}`);
-    }
-
-    let sender_wire;
-    if (query.sender_wire) {
-      let senderWireUri = new URI(query.sender_wire);
-      if (senderWireUri.scheme() != "payto") {
-        throw Error("sender wire info must be a payto URI");
-      }
-      sender_wire = query.sender_wire;
-    }
-
-    const suggestedExchangeUrl = query.suggested_exchange_url;
-    const currencyRecord = await getCurrency(amount.currency);
-
-    const args = {
-      amount,
-      callback_url,
-      currencyRecord,
-      sender_wire,
-      suggestedExchangeUrl,
-      wt_types,
-    };
-
-    ReactDOM.render(<ExchangeSelection {...args} />, document.getElementById(
-      "exchange-selection")!);
-
-  } catch (e) {
-    // TODO: provide more context information, maybe factor it out into a
-    // TODO:generic error reporting function or component.
-    document.body.innerText = i18n.str`Fatal error: "${e.message}".`;
-    console.error("got error", e);
-  }
-}
-
-document.addEventListener("DOMContentLoaded", () => {
-  main();
-});
diff --git a/src/webex/pages/confirm-contract.html b/src/webex/pages/pay.html
similarity index 96%
rename from src/webex/pages/confirm-contract.html
rename to src/webex/pages/pay.html
index 5a949159..d3bf992a 100644
--- a/src/webex/pages/confirm-contract.html
+++ b/src/webex/pages/pay.html
@@ -11,7 +11,7 @@
   <link rel="icon" href="/img/icon.png">
 
   <script src="/dist/page-common-bundle.js"></script>
-  <script src="/dist/confirm-contract-bundle.js"></script>
+  <script src="/dist/pay-bundle.js"></script>
 
   <style>
     button.accept {
diff --git a/src/webex/pages/pay.tsx b/src/webex/pages/pay.tsx
new file mode 100644
index 00000000..d929426c
--- /dev/null
+++ b/src/webex/pages/pay.tsx
@@ -0,0 +1,173 @@
+/*
+ This file is part of TALER
+ (C) 2015 GNUnet e.V.
+
+ 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.
+
+ 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
+ TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Page shown to the user to confirm entering
+ * a contract.
+ */
+
+/**
+ * Imports.
+ */
+import * as i18n from "../../i18n";
+
+import { runOnceWhenReady } from "./common";
+
+import { ExchangeRecord, ProposalDownloadRecord } from "../../dbTypes";
+import { ContractTerms } from "../../talerTypes";
+import { CheckPayResult, PreparePayResult } from "../../walletTypes";
+
+import { renderAmount } from "../renderHtml";
+import * as wxApi from "../wxApi";
+
+import React, { useState, useEffect } from "react";
+import * as ReactDOM from "react-dom";
+import URI = require("urijs");
+import { WalletApiError } from "../wxApi";
+
+import * as Amounts from "../../amounts";
+
+function TalerPayDialog({ talerPayUri }: { talerPayUri: string }) {
+  const [payStatus, setPayStatus] = useState<PreparePayResult | undefined>();
+  const [payErrMsg, setPayErrMsg] = useState<string | undefined>("");
+  const [numTries, setNumTries] = useState(0);
+  let totalFees: Amounts.AmountJson | undefined = undefined;
+
+  useEffect(() => {
+    const doFetch = async () => {
+      const p = await wxApi.preparePay(talerPayUri);
+      setPayStatus(p);
+    };
+    doFetch();
+  });
+
+  if (!payStatus) {
+    return <span>Loading payment information ...</span>;
+  }
+
+  if (payStatus.status === "error") {
+    return <span>Error: {payStatus.error}</span>;
+  }
+
+  if (payStatus.status === "payment-possible") {
+    totalFees = payStatus.totalFees;
+  }
+
+  if (payStatus.status === "paid" && numTries === 0) {
+    return (
+      <span>
+        You have already paid for this article. Click{" "}
+        <a href={payStatus.nextUrl}>here</a> to view it again.
+      </span>
+    );
+  }
+
+  const contractTerms = payStatus.contractTerms;
+
+  if (!contractTerms) {
+    return (
+      <span>
+        Error: did not get contract terms from merchant or wallet backend.
+      </span>
+    );
+  }
+
+  let merchantName: React.ReactElement;
+  if (contractTerms.merchant && contractTerms.merchant.name) {
+    merchantName = <strong>{contractTerms.merchant.name}</strong>;
+  } else {
+    merchantName = <strong>(pub: {contractTerms.merchant_pub})</strong>;
+  }
+
+  const amount = (
+    <strong>{renderAmount(Amounts.parseOrThrow(contractTerms.amount))}</strong>
+  );
+
+  const doPayment = async () => {
+    setNumTries(numTries + 1);
+    try {
+      const res = await wxApi.confirmPay(payStatus!.proposalId!, undefined);
+      document.location.href = res.nextUrl;
+    } catch (e) {
+      console.error(e);
+      setPayErrMsg(e.message);
+    }
+  };
+
+  return (
+    <div>
+      <p>
+        <i18n.Translate wrap="p">
+          The merchant <span>{merchantName}</span> offers you to purchase:
+        </i18n.Translate>
+        <div style={{ textAlign: "center" }}>
+          <strong>{contractTerms.summary}</strong>
+        </div>
+        {totalFees ? (
+          <i18n.Translate wrap="p">
+            The total price is <span>{amount} </span>
+            (plus <span>{renderAmount(totalFees)}</span> fees).
+          </i18n.Translate>
+        ) : (
+          <i18n.Translate wrap="p">
+            The total price is <span>{amount}</span>.
+          </i18n.Translate>
+        )}
+      </p>
+
+      {payErrMsg ? (
+        <div>
+          <p>Payment failed: {payErrMsg}</p>
+          <button
+            className="pure-button button-success"
+            onClick={() => doPayment()}
+          >
+            {i18n.str`Retry`}
+          </button>
+        </div>
+      ) : (
+        <div>
+          <button
+            className="pure-button button-success"
+            onClick={() => doPayment()}
+          >
+            {i18n.str`Confirm payment`}
+          </button>
+        </div>
+      )}
+    </div>
+  );
+}
+
+runOnceWhenReady(() => {
+  try {
+    const url = new URI(document.location.href);
+    const query: any = URI.parseQuery(url.query());
+
+    let talerPayUri = query.talerPayUri;
+
+    ReactDOM.render(
+      <TalerPayDialog talerPayUri={talerPayUri} />,
+      document.getElementById("contract")!,
+    );
+  } catch (e) {
+    ReactDOM.render(
+      <span>Fatal error: {e.message}</span>,
+      document.getElementById("contract")!,
+    );
+    console.error(e);
+  }
+});
diff --git a/src/webex/pages/confirm-create-reserve.html 
b/src/webex/pages/withdraw.html
similarity index 88%
rename from src/webex/pages/confirm-create-reserve.html
rename to src/webex/pages/withdraw.html
index 17daf4dd..8b1e59b1 100644
--- a/src/webex/pages/confirm-create-reserve.html
+++ b/src/webex/pages/withdraw.html
@@ -10,7 +10,7 @@
   <link rel="stylesheet" type="text/css" href="../style/wallet.css">
 
   <script src="/dist/page-common-bundle.js"></script>
-  <script src="/dist/confirm-create-reserve-bundle.js"></script>
+  <script src="/dist/withdraw-bundle.js"></script>
 
 </head>
 
diff --git a/src/webex/pages/withdraw.tsx b/src/webex/pages/withdraw.tsx
new file mode 100644
index 00000000..66617373
--- /dev/null
+++ b/src/webex/pages/withdraw.tsx
@@ -0,0 +1,231 @@
+/*
+ This file is part of TALER
+ (C) 2015-2016 GNUnet e.V.
+
+ 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.
+
+ 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
+ TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Page shown to the user to confirm creation
+ * of a reserve, usually requested by the bank.
+ *
+ * @author Florian Dold
+ */
+
+import { canonicalizeBaseUrl } from "../../helpers";
+import * as i18n from "../../i18n";
+
+import { AmountJson } from "../../amounts";
+import * as Amounts from "../../amounts";
+
+import { CurrencyRecord } from "../../dbTypes";
+import {
+  CreateReserveResponse,
+  ReserveCreationInfo,
+  WithdrawDetails,
+} from "../../walletTypes";
+
+import { ImplicitStateComponent, StateHolder } from "../components";
+
+import { WithdrawDetailView, renderAmount } from "../renderHtml";
+
+import React, { useState, useEffect } from "react";
+import * as ReactDOM from "react-dom";
+import URI = require("urijs");
+import { getWithdrawDetails, acceptWithdrawal } from "../wxApi";
+
+function NewExchangeSelection(props: { talerWithdrawUri: string }) {
+  const [details, setDetails] = useState<WithdrawDetails | undefined>();
+  const [selectedExchange, setSelectedExchange] = useState<
+    string | undefined
+  >();
+  const talerWithdrawUri = props.talerWithdrawUri;
+  const [cancelled, setCancelled] = useState(false);
+  const [selecting, setSelecting] = useState(false);
+  const [customUrl, setCustomUrl] = useState<string>("");
+  const [errMsg, setErrMsg] = useState<string | undefined>("");
+
+  useEffect(() => {
+    const fetchData = async () => {
+      console.log("getting from", talerWithdrawUri);
+      let d: WithdrawDetails | undefined = undefined;
+      try {
+        d = await getWithdrawDetails(talerWithdrawUri, selectedExchange);
+      } catch (e) {
+        console.error("error getting withdraw details", e);
+        setErrMsg(e.message);
+        return;
+      }
+      console.log("got withdrawDetails", d);
+      if (!selectedExchange && d.withdrawInfo.suggestedExchange) {
+        console.log("setting selected exchange");
+        setSelectedExchange(d.withdrawInfo.suggestedExchange);
+      }
+      setDetails(d);
+    };
+    fetchData();
+  }, [selectedExchange, errMsg, selecting]);
+
+  if (errMsg) {
+    return (
+      <div>
+        <i18n.Translate wrap="p">
+          Could not get details for withdraw operation:
+        </i18n.Translate>
+        <p style={{ color: "red" }}>{errMsg}</p>
+        <p>
+          <span
+            role="button"
+            tabIndex={0}
+            style={{ textDecoration: "underline", cursor: "pointer" }}
+            onClick={() => {
+              setSelecting(true);
+              setErrMsg(undefined);
+              setSelectedExchange(undefined);
+              setDetails(undefined);
+            }}
+          >
+            {i18n.str`Chose different exchange provider`}
+          </span>
+        </p>
+      </div>
+    );
+  }
+
+  if (!details) {
+    return <span>Loading...</span>;
+  }
+
+  if (cancelled) {
+    return <span>Withdraw operation has been cancelled.</span>;
+  }
+
+  if (selecting) {
+    const bankSuggestion = details && details.withdrawInfo.suggestedExchange;
+    return (
+      <div>
+        {i18n.str`Please select an exchange.  You can review the details 
before after your selection.`}
+        {bankSuggestion && (
+          <div>
+            <h2>Bank Suggestion</h2>
+            <button
+              className="pure-button button-success"
+              onClick={() => {
+                setDetails(undefined);
+                setSelectedExchange(bankSuggestion);
+                setSelecting(false);
+              }}
+            >
+              <i18n.Translate wrap="span">
+                Select <strong>{bankSuggestion}</strong>
+              </i18n.Translate>
+            </button>
+          </div>
+        )}
+        <h2>Custom Selection</h2>
+        <p>
+          <input
+            type="text"
+            onChange={e => setCustomUrl(e.target.value)}
+            value={customUrl}
+          />
+        </p>
+        <button
+          className="pure-button button-success"
+          onClick={() => {
+            setDetails(undefined);
+            setSelectedExchange(customUrl);
+            setSelecting(false);
+          }}
+        >
+          <i18n.Translate wrap="span">Select custom exchange</i18n.Translate>
+        </button>
+      </div>
+    );
+  }
+
+  const accept = async () => {
+    console.log("accepting exchange", selectedExchange);
+    const res = await acceptWithdrawal(talerWithdrawUri, selectedExchange!);
+    console.log("accept withdrawal response", res);
+    if (res.confirmTransferUrl) {
+      document.location.href = res.confirmTransferUrl;
+    }
+  };
+
+  return (
+    <div>
+      <i18n.Translate wrap="p">
+        You are about to withdraw{" "}
+        <strong>{renderAmount(details.withdrawInfo.amount)}</strong> from your
+        bank account into your wallet.
+      </i18n.Translate>
+      <div>
+        <button
+          className="pure-button button-success"
+          disabled={!selectedExchange}
+          onClick={() => accept()}
+        >
+          {i18n.str`Accept fees and withdraw`}
+        </button>
+        <p>
+          <span
+            role="button"
+            tabIndex={0}
+            style={{ textDecoration: "underline", cursor: "pointer" }}
+            onClick={() => setSelecting(true)}
+          >
+            {i18n.str`Chose different exchange provider`}
+          </span>
+          <br />
+          <span
+            role="button"
+            tabIndex={0}
+            style={{ textDecoration: "underline", cursor: "pointer" }}
+            onClick={() => setCancelled(true)}
+          >
+            {i18n.str`Cancel withdraw operation`}
+          </span>
+        </p>
+
+        {details.reserveCreationInfo ? (
+          <WithdrawDetailView rci={details.reserveCreationInfo} />
+        ) : null}
+      </div>
+    </div>
+  );
+}
+
+async function main() {
+  try {
+    const url = new URI(document.location.href);
+    const query: any = URI.parseQuery(url.query());
+    let talerWithdrawUri = query.talerWithdrawUri;
+    if (!talerWithdrawUri) {
+      throw Error("withdraw URI required");
+    }
+
+    ReactDOM.render(
+      <NewExchangeSelection talerWithdrawUri={talerWithdrawUri} />,
+      document.getElementById("exchange-selection")!,
+    );
+  } catch (e) {
+    // TODO: provide more context information, maybe factor it out into a
+    // TODO:generic error reporting function or component.
+    document.body.innerText = i18n.str`Fatal error: "${e.message}".`;
+    console.error("got error", e);
+  }
+}
+
+document.addEventListener("DOMContentLoaded", () => {
+  main();
+});
diff --git a/src/webex/style/wallet.css b/src/webex/style/wallet.css
index dde17e89..b4bfd6f6 100644
--- a/src/webex/style/wallet.css
+++ b/src/webex/style/wallet.css
@@ -137,6 +137,11 @@ button.linky {
     cursor:pointer;
 }
 
+.blacklink a:link, .blacklink a:visited, .blacklink a:hover, .blacklink 
a:active {
+  color: #000;
+}
+
+
 table, th, td {
     border: 1px solid black;
 }
diff --git a/src/webex/wxApi.ts b/src/webex/wxApi.ts
index 4f750036..feabc781 100644
--- a/src/webex/wxApi.ts
+++ b/src/webex/wxApi.ts
@@ -79,6 +79,8 @@ export interface UpgradeResponse {
 export class WalletApiError extends Error {
   constructor(message: string, public detail: any) {
     super(message);
+    // restore prototype chain
+    Object.setPrototypeOf(this, new.target.prototype);
   }
 }
 
@@ -401,3 +403,24 @@ export function abortFailedPayment(contractTermsHash: 
string) {
 export function benchmarkCrypto(repetitions: number): Promise<BenchmarkResult> 
{
   return callBackend("benchmark-crypto", { repetitions });
 }
+
+/**
+ * Get details about a withdraw operation.
+ */
+export function getWithdrawDetails(talerWithdrawUri: string, 
maybeSelectedExchange: string | undefined) {
+  return callBackend("get-withdraw-details", { talerWithdrawUri, 
maybeSelectedExchange });
+}
+
+/**
+ * Get details about a pay operation.
+ */
+export function preparePay(talerPayUri: string) {
+  return callBackend("prepare-pay", { talerPayUri });
+}
+
+/**
+ * Get details about a withdraw operation.
+ */
+export function acceptWithdrawal(talerWithdrawUri: string, selectedExchange: 
string) {
+  return callBackend("accept-withdrawal", { talerWithdrawUri, selectedExchange 
});
+}
\ No newline at end of file
diff --git a/src/webex/wxBackend.ts b/src/webex/wxBackend.ts
index 594418eb..d31ea388 100644
--- a/src/webex/wxBackend.ts
+++ b/src/webex/wxBackend.ts
@@ -339,6 +339,20 @@ function handleMessage(
       }
       return needsWallet().benchmarkCrypto(detail.repetitions);
     }
+    case "get-withdraw-details": {
+      return needsWallet().getWithdrawDetails(
+        detail.talerWithdrawUri,
+        detail.maybeSelectedExchange,
+      );
+    }
+    case "accept-withdrawal": {
+      return needsWallet().acceptWithdrawal(
+        detail.talerWithdrawUri,
+        detail.selectedExchange,
+      );
+    }
+    case "prepare-pay":
+      return needsWallet().preparePay(detail.talerPayUri);
     default:
       // Exhaustiveness check.
       // See https://www.typescriptlang.org/docs/handbook/advanced-types.html
@@ -523,190 +537,6 @@ function makeSyncWalletRedirect(
   return { redirectUrl: outerUrl.href() };
 }
 
-/**
- * Handle a HTTP response that has the "402 Payment Required" status.
- * In this callback we don't have access to the body, and must communicate via
- * shared state with the content script that will later be run later
- * in this tab.
- */
-function handleHttpPayment(
-  headerList: chrome.webRequest.HttpHeader[],
-  url: string,
-  tabId: number,
-): any {
-  if (!currentWallet) {
-    console.log("can't handle payment, no wallet");
-    return;
-  }
-
-  const headers: { [s: string]: string } = {};
-  for (const kv of headerList) {
-    if (kv.value) {
-      headers[kv.name.toLowerCase()] = kv.value;
-    }
-  }
-
-  const decodeIfDefined = (url?: string) =>
-    url ? decodeURIComponent(url) : undefined;
-
-  const fields = {
-    contract_url: decodeIfDefined(headers["taler-contract-url"]),
-    offer_url: decodeIfDefined(headers["taler-offer-url"]),
-    refund_url: decodeIfDefined(headers["taler-refund-url"]),
-    resource_url: decodeIfDefined(headers["taler-resource-url"]),
-    session_id: decodeIfDefined(headers["taler-session-id"]),
-    tip: decodeIfDefined(headers["taler-tip"]),
-  };
-
-  const talerHeaderFound =
-    Object.keys(fields).filter((x: any) => (fields as any)[x]).length !== 0;
-
-  if (!talerHeaderFound) {
-    // looks like it's not a taler request, it might be
-    // for a different payment system (or the shop is buggy)
-    console.log("ignoring non-taler 402 response");
-    return;
-  }
-
-  console.log("got pay detail", fields);
-
-  // Synchronous fast path for existing payment
-  if (fields.resource_url) {
-    const result = 
currentWallet.getNextUrlFromResourceUrl(fields.resource_url);
-    if (
-      result &&
-      (fields.session_id === undefined ||
-        fields.session_id === result.lastSessionId)
-    ) {
-      return { redirectUrl: result.nextUrl };
-    }
-  }
-  // Synchronous fast path for new contract
-  if (fields.contract_url) {
-    return makeSyncWalletRedirect("confirm-contract.html", tabId, url, {
-      contractUrl: fields.contract_url,
-      resourceUrl: fields.resource_url,
-      sessionId: fields.session_id,
-    });
-  }
-
-  // Synchronous fast path for tip
-  if (fields.tip) {
-    return makeSyncWalletRedirect("tip.html", tabId, url, {
-      tip_token: fields.tip,
-    });
-  }
-
-  // Synchronous fast path for refund
-  if (fields.refund_url) {
-    console.log("processing refund");
-    return makeSyncWalletRedirect("refund.html", tabId, url, {
-      refundUrl: fields.refund_url,
-    });
-  }
-
-  // We need to do some asynchronous operation, we can't directly redirect
-  talerPay(fields, url, tabId).then(nextUrl => {
-    if (nextUrl) {
-      // We use chrome.tabs.executeScript instead of chrome.tabs.update
-      // because the latter is buggy when it does not execute in the same
-      // (micro-?)task as the header callback.
-      chrome.tabs.executeScript({
-        code: `document.location.href = decodeURIComponent("${encodeURI(
-          nextUrl,
-        )}");`,
-        runAt: "document_start",
-      });
-    }
-  });
-
-  return;
-}
-
-function handleBankRequest(
-  wallet: Wallet,
-  headerList: chrome.webRequest.HttpHeader[],
-  url: string,
-  tabId: number,
-): any {
-  const headers: { [s: string]: string } = {};
-  for (const kv of headerList) {
-    if (kv.value) {
-      headers[kv.name.toLowerCase()] = kv.value;
-    }
-  }
-
-  const operation = headers["taler-operation"];
-
-  if (!operation) {
-    // Not a taler related request.
-    return;
-  }
-
-  if (operation === "confirm-reserve") {
-    const reservePub = headers["taler-reserve-pub"];
-    if (reservePub !== undefined) {
-      console.log(`confirming reserve ${reservePub} via 201`);
-      wallet.confirmReserve({ reservePub });
-    } else {
-      console.warn(
-        "got 'Taler-Operation: confirm-reserve' without 'Taler-Reserve-Pub'",
-      );
-    }
-    return;
-  }
-
-  if (operation === "create-reserve") {
-    const amount = headers["taler-amount"];
-    if (!amount) {
-      console.log("202 not understood (Taler-Amount missing)");
-      return;
-    }
-    const callbackUrl = headers["taler-callback-url"];
-    if (!callbackUrl) {
-      console.log("202 not understood (Taler-Callback-Url missing)");
-      return;
-    }
-    try {
-      JSON.parse(amount);
-    } catch (e) {
-      const errUri = new URI(
-        chrome.extension.getURL("/src/webex/pages/error.html"),
-      );
-      const p = {
-        message: `Can't parse amount ("${amount}"): ${e.message}`,
-      };
-      const errRedirectUrl = errUri.query(p).href();
-      // FIXME: use direct redirect when 
https://bugzilla.mozilla.org/show_bug.cgi?id=707624 is fixed
-      chrome.tabs.update(tabId, { url: errRedirectUrl });
-      return;
-    }
-    const wtTypes = headers["taler-wt-types"];
-    if (!wtTypes) {
-      console.log("202 not understood (Taler-Wt-Types missing)");
-      return;
-    }
-    const params = {
-      amount,
-      bank_url: url,
-      callback_url: new URI(callbackUrl).absoluteTo(url),
-      sender_wire: headers["taler-sender-wire"],
-      suggested_exchange_url: headers["taler-suggested-exchange"],
-      wt_types: wtTypes,
-    };
-    const uri = new URI(
-      chrome.extension.getURL("/src/webex/pages/confirm-create-reserve.html"),
-    );
-    const redirectUrl = uri.query(params).href();
-    console.log("redirecting to", redirectUrl);
-    // FIXME: use direct redirect when 
https://bugzilla.mozilla.org/show_bug.cgi?id=707624 is fixed
-    chrome.tabs.update(tabId, { url: redirectUrl });
-    return;
-  }
-
-  console.log("Ignoring unknown (X-)Taler-Operation:", operation);
-}
-
 // Rate limit cache for executePayment operations, to break redirect loops
 let rateLimitCache: { [n: number]: number } = {};
 
@@ -931,19 +761,59 @@ export async function wxMain() {
       }
       if (details.statusCode === 402) {
         console.log(`got 402 from ${details.url}`);
-        return handleHttpPayment(
-          details.responseHeaders || [],
-          details.url,
-          details.tabId,
-        );
-      } else if (details.statusCode === 202) {
-        return handleBankRequest(
-          wallet!,
-          details.responseHeaders || [],
-          details.url,
-          details.tabId,
-        );
+        for (let header of details.responseHeaders || []) {
+          if (header.name.toLowerCase() === "taler") {
+            const talerUri = header.value || "";
+            if (!talerUri.startsWith("taler://")) {
+              console.warn(
+                "Response with HTTP 402 has Taler header, but header value is 
not a taler:// URI.",
+              );
+              break;
+            }
+            if (talerUri.startsWith("taler://withdraw/")) {
+              return makeSyncWalletRedirect(
+                "withdraw.html",
+                details.tabId,
+                details.url,
+                {
+                  talerWithdrawUri: talerUri,
+                },
+              );
+            } else if (talerUri.startsWith("taler://pay/")) {
+              return makeSyncWalletRedirect(
+                "pay.html",
+                details.tabId,
+                details.url,
+                {
+                  talerPayUri: talerUri,
+                },
+              );
+            } else if (talerUri.startsWith("taler://tip/")) {
+              return makeSyncWalletRedirect(
+                "tip.html",
+                details.tabId,
+                details.url,
+                {
+                  talerTipUri: talerUri,
+                },
+              );
+            } else if (talerUri.startsWith("taler://refund/")) {
+              return makeSyncWalletRedirect(
+                "refund.html",
+                details.tabId,
+                details.url,
+                {
+                  talerRefundUri: talerUri,
+                },
+              );
+            } else {
+              console.warn("Unknown action in taler:// URI, ignoring.");
+            }
+            break;
+          }
+        }
       }
+      return {};
     },
     { urls: ["<all_urls>"] },
     ["responseHeaders", "blocking"],
diff --git a/tsconfig.json b/tsconfig.json
index 7c28dc38..7aca0791 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -19,7 +19,8 @@
     "noImplicitAny": true,
     "allowJs": true,
     "checkJs": true,
-    "incremental": true
+    "incremental": true,
+    "esModuleInterop": true
   },
   "files": [
     "src/amounts.ts",
@@ -55,6 +56,8 @@
     "src/promiseUtils.ts",
     "src/query.ts",
     "src/talerTypes.ts",
+    "src/taleruri-test.ts",
+    "src/taleruri.ts",
     "src/timer.ts",
     "src/types-test.ts",
     "src/wallet-test.ts",
@@ -70,10 +73,9 @@
     "src/webex/pages/auditors.tsx",
     "src/webex/pages/benchmark.tsx",
     "src/webex/pages/common.ts",
-    "src/webex/pages/confirm-contract.tsx",
-    "src/webex/pages/confirm-create-reserve.tsx",
     "src/webex/pages/error.tsx",
     "src/webex/pages/logs.tsx",
+    "src/webex/pages/pay.tsx",
     "src/webex/pages/payback.tsx",
     "src/webex/pages/popup.tsx",
     "src/webex/pages/redirect.js",
@@ -83,6 +85,7 @@
     "src/webex/pages/show-db.ts",
     "src/webex/pages/tip.tsx",
     "src/webex/pages/tree.tsx",
+    "src/webex/pages/withdraw.tsx",
     "src/webex/renderHtml.tsx",
     "src/webex/wxApi.ts",
     "src/webex/wxBackend.ts",
diff --git a/webpack.config.js b/webpack.config.js
index 55014618..df9ebbcf 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -77,8 +77,8 @@ module.exports = function (env) {
       "add-auditor": "./src/webex/pages/add-auditor.tsx",
       "auditors": "./src/webex/pages/auditors.tsx",
       "benchmark": "./src/webex/pages/benchmark.tsx",
-      "confirm-contract": "./src/webex/pages/confirm-contract.tsx",
-      "confirm-create-reserve": "./src/webex/pages/confirm-create-reserve.tsx",
+      "pay": "./src/webex/pages/pay.tsx",
+      "withdraw": "./src/webex/pages/withdraw.tsx",
       "error": "./src/webex/pages/error.tsx",
       "logs": "./src/webex/pages/logs.tsx",
       "payback": "./src/webex/pages/payback.tsx",
diff --git a/yarn.lock b/yarn.lock
index 54ad479d..584f081c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,40 +2,29 @@
 # yarn lockfile v1
 
 
-"@ava/babel-plugin-throws-helper@^3.0.0":
-  version "3.0.0"
-  resolved 
"https://registry.yarnpkg.com/@ava/babel-plugin-throws-helper/-/babel-plugin-throws-helper-3.0.0.tgz#2c933ec22da0c4ce1fc5369f2b95452c70420586";
-  integrity 
sha512-mN9UolOs4WX09QkheU1ELkVy2WPnwonlO3XMdN8JF8fQqRVgVTR21xDbvEOUsbwz6Zwjq7ji9yzyjuXqDPalxg==
+"@ava/babel-plugin-throws-helper@^4.0.0":
+  version "4.0.0"
+  resolved 
"https://registry.yarnpkg.com/@ava/babel-plugin-throws-helper/-/babel-plugin-throws-helper-4.0.0.tgz#8f5b45b7a0a79c6f4032de2101e0c221847efb62";
+  integrity 
sha512-3diBLIVBPPh3j4+hb5lo0I1D+S/O/VDJPI4Y502apBxmwEqjyXG4gTSPFUlm41sSZeZzMarT/Gzovw9kV7An0w==
 
-"@ava/babel-preset-stage-4@^2.0.0":
-  version "2.0.0"
-  resolved 
"https://registry.yarnpkg.com/@ava/babel-preset-stage-4/-/babel-preset-stage-4-2.0.0.tgz#2cd072ff818e4432b87fd4c5fd5c5d1a405a4343";
-  integrity 
sha512-OWqMYeTSZ16AfLx0Vn0Uj7tcu+uMRlbKmks+DVCFlln7vomVsOtst+Oz+HCussDSFGpE+30VtHAUHLy6pLDpHQ==
-  dependencies:
-    "@babel/plugin-proposal-async-generator-functions" "^7.0.0"
-    "@babel/plugin-proposal-object-rest-spread" "^7.0.0"
-    "@babel/plugin-proposal-optional-catch-binding" "^7.0.0"
-    "@babel/plugin-transform-async-to-generator" "^7.0.0"
-    "@babel/plugin-transform-dotall-regex" "^7.0.0"
-    "@babel/plugin-transform-exponentiation-operator" "^7.0.0"
-    "@babel/plugin-transform-modules-commonjs" "^7.0.0"
-
-"@ava/babel-preset-transform-test-files@^5.0.0":
-  version "5.0.0"
-  resolved 
"https://registry.yarnpkg.com/@ava/babel-preset-transform-test-files/-/babel-preset-transform-test-files-5.0.0.tgz#e06fc762069511e597531cc1120e22216aac6981";
-  integrity 
sha512-rqgyQwkT0+j2JzYP51dOv80u33rzAvjBtXRzUON+7+6u26mjoudRXci2+1s18rat8r4uOlZfbzm114YS6pwmYw==
+"@ava/babel-preset-stage-4@^4.0.0":
+  version "4.0.0"
+  resolved 
"https://registry.yarnpkg.com/@ava/babel-preset-stage-4/-/babel-preset-stage-4-4.0.0.tgz#9be5a59ead170062e228bb6ffd2b29f0489424fd";
+  integrity 
sha512-lZEV1ZANzfzSYBU6WHSErsy7jLPbD1iIgAboASPMcKo7woVni5/5IKWeT0RxC8rY802MFktur3OKEw2JY1Tv2w==
   dependencies:
-    "@ava/babel-plugin-throws-helper" "^3.0.0"
-    babel-plugin-espower "^3.0.1"
+    "@babel/plugin-proposal-async-generator-functions" "^7.2.0"
+    "@babel/plugin-proposal-dynamic-import" "^7.5.0"
+    "@babel/plugin-proposal-optional-catch-binding" "^7.2.0"
+    "@babel/plugin-transform-dotall-regex" "^7.4.4"
+    "@babel/plugin-transform-modules-commonjs" "^7.5.0"
 
-"@ava/write-file-atomic@^2.2.0":
-  version "2.2.0"
-  resolved 
"https://registry.yarnpkg.com/@ava/write-file-atomic/-/write-file-atomic-2.2.0.tgz#d625046f3495f1f5e372135f473909684b429247";
-  integrity 
sha512-BTNB3nGbEfJT+69wuqXFr/bQH7Vr7ihx2xGOMNqPgDGhwspoZhiWumDDZNjBy7AScmqS5CELIOGtPVXESyrnDA==
+"@ava/babel-preset-transform-test-files@^6.0.0":
+  version "6.0.0"
+  resolved 
"https://registry.yarnpkg.com/@ava/babel-preset-transform-test-files/-/babel-preset-transform-test-files-6.0.0.tgz#639e8929d2cdc8863c1f16020ce644c525723cd4";
+  integrity 
sha512-8eKhFzZp7Qcq1VLfoC75ggGT8nQs9q8fIxltU47yCB7Wi7Y8Qf6oqY1Bm0z04fIec24vEgr0ENhDHEOUGVDqnA==
   dependencies:
-    graceful-fs "^4.1.11"
-    imurmurhash "^0.1.4"
-    slide "^1.1.5"
+    "@ava/babel-plugin-throws-helper" "^4.0.0"
+    babel-plugin-espower "^3.0.1"
 
 "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5":
   version "7.5.5"
@@ -44,7 +33,7 @@
   dependencies:
     "@babel/highlight" "^7.0.0"
 
-"@babel/core@^7.4.0":
+"@babel/core@^7.5.5":
   version "7.5.5"
   resolved 
"https://registry.yarnpkg.com/@babel/core/-/core-7.5.5.tgz#17b2686ef0d6bc58f963dddd68ab669755582c30";
   integrity 
sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg==
@@ -82,22 +71,6 @@
   dependencies:
     "@babel/types" "^7.0.0"
 
-"@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0":
-  version "7.1.0"
-  resolved 
"https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz#6b69628dfe4087798e0c4ed98e3d4a6b2fbd2f5f";
-  integrity 
sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==
-  dependencies:
-    "@babel/helper-explode-assignable-expression" "^7.1.0"
-    "@babel/types" "^7.0.0"
-
-"@babel/helper-explode-assignable-expression@^7.1.0":
-  version "7.1.0"
-  resolved 
"https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz#537fa13f6f1674df745b0c00ec8fe4e99681c8f6";
-  integrity 
sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==
-  dependencies:
-    "@babel/traverse" "^7.1.0"
-    "@babel/types" "^7.0.0"
-
 "@babel/helper-function-name@^7.1.0":
   version "7.1.0"
   resolved 
"https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53";
@@ -204,7 +177,7 @@
   resolved 
"https://registry.yarnpkg.com/@babel/parser/-/parser-7.5.5.tgz#02f077ac8817d3df4a832ef59de67565e71cca4b";
   integrity 
sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==
 
-"@babel/plugin-proposal-async-generator-functions@^7.0.0":
+"@babel/plugin-proposal-async-generator-functions@^7.2.0":
   version "7.2.0"
   resolved 
"https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e";
   integrity 
sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==
@@ -213,15 +186,15 @@
     "@babel/helper-remap-async-to-generator" "^7.1.0"
     "@babel/plugin-syntax-async-generators" "^7.2.0"
 
-"@babel/plugin-proposal-object-rest-spread@^7.0.0":
-  version "7.5.5"
-  resolved 
"https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz#61939744f71ba76a3ae46b5eea18a54c16d22e58";
-  integrity 
sha512-F2DxJJSQ7f64FyTVl5cw/9MWn6naXGdk3Q3UhDbFEEHv+EilCPoeRD3Zh/Utx1CJz4uyKlQ4uH+bJPbEhMV7Zw==
+"@babel/plugin-proposal-dynamic-import@^7.5.0":
+  version "7.5.0"
+  resolved 
"https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz#e532202db4838723691b10a67b8ce509e397c506";
+  integrity 
sha512-x/iMjggsKTFHYC6g11PL7Qy58IK8H5zqfm9e6hu4z1iH2IRyAp9u9dL80zA6R76yFovETFLKz2VJIC2iIPBuFw==
   dependencies:
     "@babel/helper-plugin-utils" "^7.0.0"
-    "@babel/plugin-syntax-object-rest-spread" "^7.2.0"
+    "@babel/plugin-syntax-dynamic-import" "^7.2.0"
 
-"@babel/plugin-proposal-optional-catch-binding@^7.0.0":
+"@babel/plugin-proposal-optional-catch-binding@^7.2.0":
   version "7.2.0"
   resolved 
"https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5";
   integrity 
sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==
@@ -236,10 +209,10 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.0.0"
 
-"@babel/plugin-syntax-object-rest-spread@^7.2.0":
+"@babel/plugin-syntax-dynamic-import@^7.2.0":
   version "7.2.0"
-  resolved 
"https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e";
-  integrity 
sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==
+  resolved 
"https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz#69c159ffaf4998122161ad8ebc5e6d1f55df8612";
+  integrity 
sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==
   dependencies:
     "@babel/helper-plugin-utils" "^7.0.0"
 
@@ -250,16 +223,7 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.0.0"
 
-"@babel/plugin-transform-async-to-generator@^7.0.0":
-  version "7.5.0"
-  resolved 
"https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz#89a3848a0166623b5bc481164b5936ab947e887e";
-  integrity 
sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg==
-  dependencies:
-    "@babel/helper-module-imports" "^7.0.0"
-    "@babel/helper-plugin-utils" "^7.0.0"
-    "@babel/helper-remap-async-to-generator" "^7.1.0"
-
-"@babel/plugin-transform-dotall-regex@^7.0.0":
+"@babel/plugin-transform-dotall-regex@^7.4.4":
   version "7.4.4"
   resolved 
"https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz#361a148bc951444312c69446d76ed1ea8e4450c3";
   integrity 
sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg==
@@ -268,15 +232,7 @@
     "@babel/helper-regex" "^7.4.4"
     regexpu-core "^4.5.4"
 
-"@babel/plugin-transform-exponentiation-operator@^7.0.0":
-  version "7.2.0"
-  resolved 
"https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz#a63868289e5b4007f7054d46491af51435766008";
-  integrity 
sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==
-  dependencies:
-    "@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0"
-    "@babel/helper-plugin-utils" "^7.0.0"
-
-"@babel/plugin-transform-modules-commonjs@^7.0.0":
+"@babel/plugin-transform-modules-commonjs@^7.5.0":
   version "7.5.0"
   resolved 
"https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.5.0.tgz#425127e6045231360858eeaa47a71d75eded7a74";
   integrity 
sha512-xmHq0B+ytyrWJvQTc5OWAC4ii6Dhr0s22STOoydokG51JjWhyYo5mRPXoi+ZmtHQhZZwuXNN+GG5jy5UZZJxIQ==
@@ -326,6 +282,39 @@
   dependencies:
     arrify "^1.0.1"
 
+"@nodelib/fs.scandir@2.1.2":
+  version "2.1.2"
+  resolved 
"https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.2.tgz#1f981cd5b83e85cfdeb386fc693d4baab392fa54";
+  integrity 
sha512-wrIBsjA5pl13f0RN4Zx4FNWmU71lv03meGKnqRUoCyan17s4V3WL92f3w3AIuWbNnpcrQyFBU5qMavJoB8d27w==
+  dependencies:
+    "@nodelib/fs.stat" "2.0.2"
+    run-parallel "^1.1.9"
+
+"@nodelib/fs.stat@2.0.2", "@nodelib/fs.stat@^2.0.1":
+  version "2.0.2"
+  resolved 
"https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.2.tgz#2762aea8fe78ea256860182dcb52d61ee4b8fda6";
+  integrity 
sha512-z8+wGWV2dgUhLqrtRYa03yDx4HWMvXKi1z8g3m2JyxAx8F7xk74asqPk5LAETjqDSGLFML/6CDl0+yFunSYicw==
+
+"@nodelib/fs.walk@^1.2.1":
+  version "1.2.3"
+  resolved 
"https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.3.tgz#a555dc256acaf00c62b0db29529028dd4d4cb141";
+  integrity 
sha512-l6t8xEhfK9Sa4YO5mIRdau7XSOADfmh3jCr0evNHdY+HNkW6xuQhgMH7D73VV6WpZOagrW0UludvMTiifiwTfA==
+  dependencies:
+    "@nodelib/fs.scandir" "2.1.2"
+    fastq "^1.6.0"
+
+"@sindresorhus/is@^0.14.0":
+  version "0.14.0"
+  resolved 
"https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea";
+  integrity 
sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==
+
+"@szmarczak/http-timer@^1.1.2":
+  version "1.1.2"
+  resolved 
"https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421";
+  integrity 
sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==
+  dependencies:
+    defer-to-connect "^1.0.1"
+
 "@types/chrome@^0.0.88":
   version "0.0.88"
   resolved 
"https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.88.tgz#0041a101d69f78008910927c5b3299a00d8660db";
@@ -598,12 +587,12 @@ ajv@^6.1.0, ajv@^6.10.2:
     json-schema-traverse "^0.4.1"
     uri-js "^4.2.2"
 
-ansi-align@^2.0.0:
-  version "2.0.0"
-  resolved 
"https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f";
-  integrity sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=
+ansi-align@^3.0.0:
+  version "3.0.0"
+  resolved 
"https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb";
+  integrity 
sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==
   dependencies:
-    string-width "^2.0.0"
+    string-width "^3.0.0"
 
 ansi-colors@^1.0.1:
   version "1.1.0"
@@ -612,10 +601,12 @@ ansi-colors@^1.0.1:
   dependencies:
     ansi-wrap "^0.1.0"
 
-ansi-escapes@^3.2.0:
-  version "3.2.0"
-  resolved 
"https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b";
-  integrity 
sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==
+ansi-escapes@^4.2.1:
+  version "4.2.1"
+  resolved 
"https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.2.1.tgz#4dccdb846c3eee10f6d64dea66273eab90c37228";
+  integrity 
sha512-Cg3ymMAdN10wOk/VYfLV7KCQyv7EDirJ64500sU7n9UlmioEtDuU5Gd+hj73hXSU/ex7tHJSssmyftDdkMLO8Q==
+  dependencies:
+    type-fest "^0.5.2"
 
 ansi-gray@^0.1.1:
   version "0.1.1"
@@ -646,6 +637,13 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1:
   dependencies:
     color-convert "^1.9.0"
 
+ansi-styles@^4.0.0:
+  version "4.1.0"
+  resolved 
"https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.1.0.tgz#d3ba8047b818293eaaa7978321dd61bff9842cfc";
+  integrity 
sha512-Qts4KCLKG+waHc9C4m07weIY8qyeixoS0h6RnbsNVD6Fw+pEZGW3vTyObL3WXpE09Mq4Oi7/lBEyLmOiLtlYWQ==
+  dependencies:
+    color-convert "^2.0.1"
+
 ansi-wrap@0.1.0, ansi-wrap@^0.1.0:
   version "0.1.0"
   resolved 
"https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf";
@@ -664,6 +662,14 @@ anymatch@^2.0.0:
     micromatch "^3.1.4"
     normalize-path "^2.1.1"
 
+anymatch@^3.0.1:
+  version "3.0.3"
+  resolved 
"https://registry.yarnpkg.com/anymatch/-/anymatch-3.0.3.tgz#2fb624fe0e84bccab00afee3d0006ed310f22f09";
+  integrity 
sha512-c6IvoeBECQlMVuYUjSwimnhmztImpErfxJzWZhIQinIvQWoGOnB0dLIgifbPHQt5heS6mNlaZG16f06H3C8t1g==
+  dependencies:
+    normalize-path "^3.0.0"
+    picomatch "^2.0.4"
+
 append-buffer@^1.0.2:
   version "1.0.2"
   resolved 
"https://registry.yarnpkg.com/append-buffer/-/append-buffer-1.0.2.tgz#d8220cf466081525efea50614f3de6514dfa58f1";
@@ -761,11 +767,6 @@ arr-union@^3.1.0:
   resolved 
"https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4";
   integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=
 
-array-differ@^2.0.3:
-  version "2.1.0"
-  resolved 
"https://registry.yarnpkg.com/array-differ/-/array-differ-2.1.0.tgz#4b9c1c3f14b906757082925769e8ab904f4801b1";
-  integrity 
sha512-KbUpJgx909ZscOc/7CLATBFam7P1Z1QRQInvgT0UztM9Q72aGKCunKASAl7WNW0tnPmPyEMeMhdsfWhfmW037w==
-
 array-each@^1.0.0, array-each@^1.0.1:
   version "1.0.1"
   resolved 
"https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f";
@@ -810,19 +811,24 @@ array-sort@^1.0.0:
     get-value "^2.0.6"
     kind-of "^5.0.2"
 
-array-union@^1.0.1, array-union@^1.0.2:
+array-union@^1.0.1:
   version "1.0.2"
   resolved 
"https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39";
   integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=
   dependencies:
     array-uniq "^1.0.1"
 
+array-union@^2.1.0:
+  version "2.1.0"
+  resolved 
"https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d";
+  integrity 
sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
+
 array-uniq@^1.0.1:
   version "1.0.3"
   resolved 
"https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6";
   integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=
 
-array-uniq@^2.0.0:
+array-uniq@^2.1.0:
   version "2.1.0"
   resolved 
"https://registry.yarnpkg.com/array-uniq/-/array-uniq-2.1.0.tgz#46603d5e28e79bfd02b046fcc1d77c6820bd8e98";
   integrity 
sha512-bdHxtev7FN6+MXI1YFW0Q8mQ8dTJc2S8AMfju+ZR77pbg2yAdVyDlwkaUI7Har0LyOMRFPHrJ9lYdyjZZswdlQ==
@@ -832,11 +838,16 @@ array-unique@^0.3.2:
   resolved 
"https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428";
   integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
 
-arrify@^1.0.0, arrify@^1.0.1:
+arrify@^1.0.1:
   version "1.0.1"
   resolved 
"https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d";
   integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=
 
+arrify@^2.0.1:
+  version "2.0.1"
+  resolved 
"https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa";
+  integrity 
sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==
+
 asap@~2.0.6:
   version "2.0.6"
   resolved 
"https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46";
@@ -864,6 +875,11 @@ assign-symbols@^1.0.0:
   resolved 
"https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367";
   integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
 
+astral-regex@^1.0.0:
+  version "1.0.0"
+  resolved 
"https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9";
+  integrity 
sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==
+
 async-done@^1.2.0, async-done@^1.2.2:
   version "1.3.2"
   resolved 
"https://registry.yarnpkg.com/async-done/-/async-done-1.3.2.tgz#5e15aa729962a4b07414f528a88cdf18e0b290a2";
@@ -903,92 +919,84 @@ atob@^2.1.1:
   resolved 
"https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9";
   integrity 
sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
 
-ava@^1.4.1:
-  version "1.4.1"
-  resolved 
"https://registry.yarnpkg.com/ava/-/ava-1.4.1.tgz#4a59289e0c9728e492ec3a5be21d1072636be172";
-  integrity 
sha512-wKpgOPTL7hJSBWpfbU4SA8rlsTZrph9g9g7qYDV7M6uK1rKeW8oCUJWRwCd8B24S4N0Y5myf6cTEnA66WIk0sA==
+ava@^2.3.0:
+  version "2.3.0"
+  resolved 
"https://registry.yarnpkg.com/ava/-/ava-2.3.0.tgz#cac4d7f0a30077a852c6bf5bc7c0bc78c3021e63";
+  integrity 
sha512-4VaaSnl13vpTZmqW3aMqioSolT0/ozRkjQxTLi3p8wtyRONuX/uLKL3uF0j50w2BNRoLsJqztnkX2h8xeVp2lg==
   dependencies:
-    "@ava/babel-preset-stage-4" "^2.0.0"
-    "@ava/babel-preset-transform-test-files" "^5.0.0"
-    "@ava/write-file-atomic" "^2.2.0"
-    "@babel/core" "^7.4.0"
-    "@babel/generator" "^7.4.0"
-    "@babel/plugin-syntax-async-generators" "^7.2.0"
-    "@babel/plugin-syntax-object-rest-spread" "^7.2.0"
-    "@babel/plugin-syntax-optional-catch-binding" "^7.2.0"
+    "@ava/babel-preset-stage-4" "^4.0.0"
+    "@ava/babel-preset-transform-test-files" "^6.0.0"
+    "@babel/core" "^7.5.5"
+    "@babel/generator" "^7.5.5"
     "@concordance/react" "^2.0.0"
-    ansi-escapes "^3.2.0"
-    ansi-styles "^3.2.1"
+    ansi-escapes "^4.2.1"
+    ansi-styles "^4.0.0"
     arr-flatten "^1.1.0"
-    array-union "^1.0.1"
-    array-uniq "^2.0.0"
-    arrify "^1.0.0"
-    bluebird "^3.5.3"
+    array-union "^2.1.0"
+    array-uniq "^2.1.0"
+    arrify "^2.0.1"
+    bluebird "^3.5.5"
     chalk "^2.4.2"
-    chokidar "^2.1.5"
+    chokidar "^3.0.2"
     chunkd "^1.0.0"
     ci-parallel-vars "^1.0.0"
-    clean-stack "^2.0.0"
+    clean-stack "^2.2.0"
     clean-yaml-object "^0.1.0"
-    cli-cursor "^2.1.0"
-    cli-truncate "^1.1.0"
+    cli-cursor "^3.1.0"
+    cli-truncate "^2.0.0"
     code-excerpt "^2.1.1"
     common-path-prefix "^1.0.0"
     concordance "^4.0.0"
     convert-source-map "^1.6.0"
     currently-unhandled "^0.4.1"
     debug "^4.1.1"
-    del "^4.0.0"
-    dot-prop "^4.2.0"
+    del "^4.1.1"
+    dot-prop "^5.1.0"
     emittery "^0.4.1"
     empower-core "^1.2.0"
     equal-length "^1.0.0"
-    escape-string-regexp "^1.0.5"
-    esm "^3.2.20"
-    figures "^2.0.0"
-    find-up "^3.0.0"
-    get-port "^4.2.0"
-    globby "^7.1.1"
+    escape-string-regexp "^2.0.0"
+    esm "^3.2.25"
+    figures "^3.0.0"
+    find-up "^4.1.0"
+    get-port "^5.0.0"
+    globby "^10.0.1"
     ignore-by-default "^1.0.0"
-    import-local "^2.0.0"
-    indent-string "^3.2.0"
+    import-local "^3.0.2"
+    indent-string "^4.0.0"
     is-ci "^2.0.0"
-    is-error "^2.2.1"
-    is-observable "^1.1.0"
-    is-plain-object "^2.0.4"
+    is-error "^2.2.2"
+    is-observable "^2.0.0"
+    is-plain-object "^3.0.0"
     is-promise "^2.1.0"
-    lodash.clone "^4.5.0"
-    lodash.clonedeep "^4.5.0"
-    lodash.clonedeepwith "^4.5.0"
-    lodash.debounce "^4.0.3"
-    lodash.difference "^4.3.0"
-    lodash.flatten "^4.2.0"
-    loud-rejection "^1.2.0"
-    make-dir "^2.1.0"
-    matcher "^1.1.1"
-    md5-hex "^2.0.0"
+    lodash "^4.17.15"
+    loud-rejection "^2.1.0"
+    make-dir "^3.0.0"
+    matcher "^2.0.0"
+    md5-hex "^3.0.1"
     meow "^5.0.0"
-    ms "^2.1.1"
-    multimatch "^3.0.0"
-    observable-to-promise "^0.5.0"
-    ora "^3.2.0"
-    package-hash "^3.0.0"
-    pkg-conf "^3.0.0"
-    plur "^3.0.1"
-    pretty-ms "^4.0.0"
+    micromatch "^4.0.2"
+    ms "^2.1.2"
+    observable-to-promise "^1.0.0"
+    ora "^3.4.0"
+    package-hash "^4.0.0"
+    pkg-conf "^3.1.0"
+    plur "^3.1.1"
+    pretty-ms "^5.0.0"
     require-precompiled "^0.1.0"
-    resolve-cwd "^2.0.0"
-    slash "^2.0.0"
-    source-map-support "^0.5.11"
+    resolve-cwd "^3.0.0"
+    slash "^3.0.0"
+    source-map-support "^0.5.13"
     stack-utils "^1.0.2"
     strip-ansi "^5.2.0"
-    strip-bom-buf "^1.0.0"
+    strip-bom-buf "^2.0.0"
     supertap "^1.0.0"
-    supports-color "^6.1.0"
+    supports-color "^7.0.0"
     trim-off-newlines "^1.0.1"
     trim-right "^1.0.1"
     unique-temp-dir "^1.0.0"
-    update-notifier "^2.5.0"
+    update-notifier "^3.0.1"
+    write-file-atomic "^3.0.0"
 
 awesome-typescript-loader@^5.2.1:
   version "5.2.1"
@@ -1097,6 +1105,11 @@ binary-extensions@^1.0.0:
   resolved 
"https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65";
   integrity 
sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==
 
+binary-extensions@^2.0.0:
+  version "2.0.0"
+  resolved 
"https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c";
+  integrity 
sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==
+
 bl@^3.0.0:
   version "3.0.0"
   resolved 
"https://registry.yarnpkg.com/bl/-/bl-3.0.0.tgz#3611ec00579fd18561754360b21e9f784500ff88";
@@ -1104,11 +1117,16 @@ bl@^3.0.0:
   dependencies:
     readable-stream "^3.0.1"
 
-bluebird@^3.5.3, bluebird@^3.5.5:
+bluebird@^3.5.5:
   version "3.5.5"
   resolved 
"https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f";
   integrity 
sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==
 
+blueimp-md5@^2.10.0:
+  version "2.12.0"
+  resolved 
"https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.12.0.tgz#be7367938a889dec3ffbb71138617c117e9c130a";
+  integrity 
sha512-zo+HIdIhzojv6F1siQPqPFROyVy7C50KzHv/k/Iz+BtvtVzSHXiMXOpq2wCfNkeBqdCv+V8XOV96tsEt2W/3rQ==
+
 bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
   version "4.11.8"
   resolved 
"https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f";
@@ -1130,17 +1148,18 @@ body-parser@1.19.0:
     raw-body "2.4.0"
     type-is "~1.6.17"
 
-boxen@^1.2.1:
-  version "1.3.0"
-  resolved 
"https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b";
-  integrity 
sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==
+boxen@^3.0.0:
+  version "3.2.0"
+  resolved 
"https://registry.yarnpkg.com/boxen/-/boxen-3.2.0.tgz#fbdff0de93636ab4450886b6ff45b92d098f45eb";
+  integrity 
sha512-cU4J/+NodM3IHdSL2yN8bqYqnmlBTidDR4RC7nJs61ZmtGz8VZzM3HLQX0zY5mrSmPtR3xWwsq2jOUQqFZN8+A==
   dependencies:
-    ansi-align "^2.0.0"
-    camelcase "^4.0.0"
-    chalk "^2.0.1"
-    cli-boxes "^1.0.0"
-    string-width "^2.0.0"
+    ansi-align "^3.0.0"
+    camelcase "^5.3.1"
+    chalk "^2.4.2"
+    cli-boxes "^2.2.0"
+    string-width "^3.0.0"
     term-size "^1.2.0"
+    type-fest "^0.3.0"
     widest-line "^2.0.0"
 
 brace-expansion@^1.1.7:
@@ -1167,6 +1186,13 @@ braces@^2.3.1, braces@^2.3.2:
     split-string "^3.0.2"
     to-regex "^3.0.1"
 
+braces@^3.0.1, braces@^3.0.2:
+  version "3.0.2"
+  resolved 
"https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107";
+  integrity 
sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
+  dependencies:
+    fill-range "^7.0.1"
+
 brorand@^1.0.1:
   version "1.1.0"
   resolved 
"https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f";
@@ -1319,6 +1345,19 @@ cache-base@^1.0.1:
     union-value "^1.0.0"
     unset-value "^1.0.0"
 
+cacheable-request@^6.0.0:
+  version "6.1.0"
+  resolved 
"https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912";
+  integrity 
sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==
+  dependencies:
+    clone-response "^1.0.2"
+    get-stream "^5.1.0"
+    http-cache-semantics "^4.0.0"
+    keyv "^3.0.0"
+    lowercase-keys "^2.0.0"
+    normalize-url "^4.1.0"
+    responselike "^1.0.2"
+
 caching-transform@^3.0.2:
   version "3.0.2"
   resolved 
"https://registry.yarnpkg.com/caching-transform/-/caching-transform-3.0.2.tgz#601d46b91eca87687a281e71cef99791b0efca70";
@@ -1358,21 +1397,16 @@ camelcase@^3.0.0:
   resolved 
"https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a";
   integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo=
 
-camelcase@^4.0.0, camelcase@^4.1.0:
+camelcase@^4.1.0:
   version "4.1.0"
   resolved 
"https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd";
   integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=
 
-camelcase@^5.0.0:
+camelcase@^5.0.0, camelcase@^5.3.1:
   version "5.3.1"
   resolved 
"https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320";
   integrity 
sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
 
-capture-stack-trace@^1.0.0:
-  version "1.0.1"
-  resolved 
"https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz#a6c0bbe1f38f3aa0b92238ecb6ff42c344d4135d";
-  integrity 
sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==
-
 chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, 
chalk@^2.4.1, chalk@^2.4.2:
   version "2.4.2"
   resolved 
"https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424";
@@ -1387,7 +1421,7 @@ check-types@^8.0.3:
   resolved 
"https://registry.yarnpkg.com/check-types/-/check-types-8.0.3.tgz#3356cca19c889544f2d7a95ed49ce508a0ecf552";
   integrity 
sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ==
 
-chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.1.5:
+chokidar@^2.0.0, chokidar@^2.0.2:
   version "2.1.6"
   resolved 
"https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.6.tgz#b6cad653a929e244ce8a834244164d241fa954c5";
   integrity 
sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==
@@ -1406,6 +1440,21 @@ chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.1.5:
   optionalDependencies:
     fsevents "^1.2.7"
 
+chokidar@^3.0.2:
+  version "3.0.2"
+  resolved 
"https://registry.yarnpkg.com/chokidar/-/chokidar-3.0.2.tgz#0d1cd6d04eb2df0327446188cd13736a3367d681";
+  integrity 
sha512-c4PR2egjNjI1um6bamCQ6bUNPDiyofNQruHvKgHQ4gDUP/ITSVSzNsiI5OWtHOsX323i5ha/kk4YmOZ1Ktg7KA==
+  dependencies:
+    anymatch "^3.0.1"
+    braces "^3.0.2"
+    glob-parent "^5.0.0"
+    is-binary-path "^2.1.0"
+    is-glob "^4.0.1"
+    normalize-path "^3.0.0"
+    readdirp "^3.1.1"
+  optionalDependencies:
+    fsevents "^2.0.6"
+
 chownr@^1.1.1:
   version "1.1.2"
   resolved 
"https://registry.yarnpkg.com/chownr/-/chownr-1.1.2.tgz#a18f1e0b269c8a6a5d3c86eb298beb14c3dd7bf6";
@@ -1423,11 +1472,6 @@ chunkd@^1.0.0:
   resolved 
"https://registry.yarnpkg.com/chunkd/-/chunkd-1.0.0.tgz#4ead4a3704bcce510c4bb4d4a8be30c557836dd1";
   integrity 
sha512-xx3Pb5VF9QaqCotolyZ1ywFBgyuJmu6+9dLiqBxgelEse9Xsr3yUlpoX3O4Oh11M00GT2kYMsRByTKIMJW2Lkg==
 
-ci-info@^1.5.0:
-  version "1.6.0"
-  resolved 
"https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497";
-  integrity 
sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==
-
 ci-info@^2.0.0:
   version "2.0.0"
   resolved 
"https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46";
@@ -1456,7 +1500,7 @@ class-utils@^0.3.5:
     isobject "^3.0.0"
     static-extend "^0.1.1"
 
-clean-stack@^2.0.0:
+clean-stack@^2.2.0:
   version "2.2.0"
   resolved 
"https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b";
   integrity 
sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
@@ -1466,10 +1510,10 @@ clean-yaml-object@^0.1.0:
   resolved 
"https://registry.yarnpkg.com/clean-yaml-object/-/clean-yaml-object-0.1.0.tgz#63fb110dc2ce1a84dc21f6d9334876d010ae8b68";
   integrity sha1-Y/sRDcLOGoTcIfbZM0h20BCui2g=
 
-cli-boxes@^1.0.0:
-  version "1.0.0"
-  resolved 
"https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143";
-  integrity sha1-T6kXw+WclKAEzWH47lCdplFocUM=
+cli-boxes@^2.2.0:
+  version "2.2.0"
+  resolved 
"https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d";
+  integrity 
sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==
 
 cli-cursor@^2.1.0:
   version "2.1.0"
@@ -1478,18 +1522,25 @@ cli-cursor@^2.1.0:
   dependencies:
     restore-cursor "^2.0.0"
 
+cli-cursor@^3.1.0:
+  version "3.1.0"
+  resolved 
"https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307";
+  integrity 
sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==
+  dependencies:
+    restore-cursor "^3.1.0"
+
 cli-spinners@^2.0.0:
   version "2.2.0"
   resolved 
"https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.2.0.tgz#e8b988d9206c692302d8ee834e7a85c0144d8f77";
   integrity 
sha512-tgU3fKwzYjiLEQgPMD9Jt+JjHVL9kW93FiIMX/l7rivvOD4/LL0Mf7gda3+4U2KJBloybwgj5KEoQgGRioMiKQ==
 
-cli-truncate@^1.1.0:
-  version "1.1.0"
-  resolved 
"https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-1.1.0.tgz#2b2dfd83c53cfd3572b87fc4d430a808afb04086";
-  integrity 
sha512-bAtZo0u82gCfaAGfSNxUdTI9mNyza7D8w4CVCcaOsy7sgwDzvx6ekr6cuWJqY3UGzgnQ1+4wgENup5eIhgxEYA==
+cli-truncate@^2.0.0:
+  version "2.0.0"
+  resolved 
"https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.0.0.tgz#68ff6aaa53b203b52ad89b8b1a80f1f61ad1e1d5";
+  integrity 
sha512-C4hp+8GCIFVsUUiXcw+ce+7wexVWImw8rQrgMBFsqerx9LvvcGlwm6sMjQYAEmV/Xb87xc1b5Ttx505MSpZVqg==
   dependencies:
-    slice-ansi "^1.0.0"
-    string-width "^2.0.0"
+    slice-ansi "^2.1.0"
+    string-width "^4.1.0"
 
 cliui@^3.2.0:
   version "3.2.0"
@@ -1514,6 +1565,13 @@ clone-buffer@^1.0.0:
   resolved 
"https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58";
   integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg=
 
+clone-response@^1.0.2:
+  version "1.0.2"
+  resolved 
"https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b";
+  integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=
+  dependencies:
+    mimic-response "^1.0.0"
+
 clone-stats@^1.0.0:
   version "1.0.0"
   resolved 
"https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680";
@@ -1574,11 +1632,23 @@ color-convert@^1.9.0:
   dependencies:
     color-name "1.1.3"
 
+color-convert@^2.0.1:
+  version "2.0.1"
+  resolved 
"https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3";
+  integrity 
sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
+  dependencies:
+    color-name "~1.1.4"
+
 color-name@1.1.3:
   version "1.1.3"
   resolved 
"https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25";
   integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
 
+color-name@~1.1.4:
+  version "1.1.4"
+  resolved 
"https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2";
+  integrity 
sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+
 color-support@^1.1.3:
   version "1.1.3"
   resolved 
"https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2";
@@ -1651,10 +1721,10 @@ concordance@^4.0.0:
     semver "^5.5.1"
     well-known-symbols "^2.0.0"
 
-configstore@^3.0.0:
-  version "3.1.2"
-  resolved 
"https://registry.yarnpkg.com/configstore/-/configstore-3.1.2.tgz#c6f25defaeef26df12dd33414b001fe81a543f8f";
-  integrity 
sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==
+configstore@^4.0.0:
+  version "4.0.0"
+  resolved 
"https://registry.yarnpkg.com/configstore/-/configstore-4.0.0.tgz#5933311e95d3687efb592c528b922d9262d227e7";
+  integrity 
sha512-CmquAXFBocrzaSM8mtGPMM/HiWmyIpr4CcJl/rgY2uCObZ/S7cKU0silxslqJejl+t/T9HS8E0PUNQD81JGUEQ==
   dependencies:
     dot-prop "^4.1.0"
     graceful-fs "^4.1.2"
@@ -1783,13 +1853,6 @@ create-ecdh@^4.0.0:
     bn.js "^4.1.0"
     elliptic "^6.0.0"
 
-create-error-class@^3.0.0:
-  version "3.0.2"
-  resolved 
"https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6";
-  integrity sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=
-  dependencies:
-    capture-stack-trace "^1.0.0"
-
 create-hash@^1.1.0, create-hash@^1.1.2:
   version "1.2.0"
   resolved 
"https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196";
@@ -1946,6 +2009,13 @@ decode-uri-component@^0.2.0:
   resolved 
"https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545";
   integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
 
+decompress-response@^3.3.0:
+  version "3.3.0"
+  resolved 
"https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3";
+  integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=
+  dependencies:
+    mimic-response "^1.0.0"
+
 deep-equal@^1.0.0:
   version "1.0.1"
   resolved 
"https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5";
@@ -1982,6 +2052,11 @@ defaults@^1.0.3:
   dependencies:
     clone "^1.0.2"
 
+defer-to-connect@^1.0.1:
+  version "1.0.2"
+  resolved 
"https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.0.2.tgz#4bae758a314b034ae33902b5aac25a8dd6a8633e";
+  integrity 
sha512-k09hcQcTDY+cwgiwa6PYKLm3jlagNzQ+RSvhjzESOGOx+MNOuXkxTfEvPrO1IOQ81tArCFYQgi631clB70RpQw==
+
 define-properties@^1.1.2:
   version "1.1.3"
   resolved 
"https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1";
@@ -2011,7 +2086,7 @@ define-property@^2.0.2:
     is-descriptor "^1.0.2"
     isobject "^3.0.1"
 
-del@^4.0.0:
+del@^4.1.1:
   version "4.1.1"
   resolved 
"https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4";
   integrity 
sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==
@@ -2071,25 +2146,32 @@ diffie-hellman@^5.0.0:
     miller-rabin "^4.0.0"
     randombytes "^2.0.0"
 
-dir-glob@^2.0.0:
-  version "2.2.2"
-  resolved 
"https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4";
-  integrity 
sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==
+dir-glob@^3.0.1:
+  version "3.0.1"
+  resolved 
"https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f";
+  integrity 
sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
   dependencies:
-    path-type "^3.0.0"
+    path-type "^4.0.0"
 
 domain-browser@^1.1.1:
   version "1.2.0"
   resolved 
"https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda";
   integrity 
sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==
 
-dot-prop@^4.1.0, dot-prop@^4.2.0:
+dot-prop@^4.1.0:
   version "4.2.0"
   resolved 
"https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57";
   integrity 
sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==
   dependencies:
     is-obj "^1.0.0"
 
+dot-prop@^5.1.0:
+  version "5.1.0"
+  resolved 
"https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.1.0.tgz#bdd8c986a77b83e3fca524e53786df916cabbd8a";
+  integrity 
sha512-n1oC6NBF+KM9oVXtjmen4Yo7HyAVWV2UUl50dCYJdw2924K6dX9bf9TTTWaKtYlRn0FEtxG27KS80ayVLixxJA==
+  dependencies:
+    is-obj "^2.0.0"
+
 duplexer3@^0.1.4:
   version "0.1.4"
   resolved 
"https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2";
@@ -2151,6 +2233,11 @@ emoji-regex@^7.0.1:
   resolved 
"https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156";
   integrity 
sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
 
+emoji-regex@^8.0.0:
+  version "8.0.0"
+  resolved 
"https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37";
+  integrity 
sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
+
 emojis-list@^2.0.0:
   version "2.1.0"
   resolved 
"https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389";
@@ -2257,11 +2344,16 @@ escape-html@~1.0.3:
   resolved 
"https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988";
   integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
 
-escape-string-regexp@^1.0.4, escape-string-regexp@^1.0.5:
+escape-string-regexp@^1.0.5:
   version "1.0.5"
   resolved 
"https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4";
   integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
 
+escape-string-regexp@^2.0.0:
+  version "2.0.0"
+  resolved 
"https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344";
+  integrity 
sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
+
 eslint-scope@^4.0.3:
   version "4.0.3"
   resolved 
"https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848";
@@ -2270,7 +2362,7 @@ eslint-scope@^4.0.3:
     esrecurse "^4.1.0"
     estraverse "^4.1.1"
 
-esm@^3.2.20:
+esm@^3.2.25:
   version "3.2.25"
   resolved 
"https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10";
   integrity 
sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==
@@ -2468,20 +2560,39 @@ fast-diff@^1.1.2:
   resolved 
"https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03";
   integrity 
sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==
 
+fast-glob@^3.0.3:
+  version "3.0.4"
+  resolved 
"https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.0.4.tgz#d484a41005cb6faeb399b951fd1bd70ddaebb602";
+  integrity 
sha512-wkIbV6qg37xTJwqSsdnIphL1e+LaGz4AIQqr00mIubMaEhv1/HEmJ0uuCGZRNRUkZZmOB5mJKO0ZUTVq+SxMQg==
+  dependencies:
+    "@nodelib/fs.stat" "^2.0.1"
+    "@nodelib/fs.walk" "^1.2.1"
+    glob-parent "^5.0.0"
+    is-glob "^4.0.1"
+    merge2 "^1.2.3"
+    micromatch "^4.0.2"
+
 fast-json-stable-stringify@^2.0.0:
   version "2.0.0"
   resolved 
"https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2";
   integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I=
 
+fastq@^1.6.0:
+  version "1.6.0"
+  resolved 
"https://registry.yarnpkg.com/fastq/-/fastq-1.6.0.tgz#4ec8a38f4ac25f21492673adb7eae9cfef47d1c2";
+  integrity 
sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA==
+  dependencies:
+    reusify "^1.0.0"
+
 figgy-pudding@^3.5.1:
   version "3.5.1"
   resolved 
"https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790";
   integrity 
sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==
 
-figures@^2.0.0:
-  version "2.0.0"
-  resolved 
"https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962";
-  integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=
+figures@^3.0.0:
+  version "3.0.0"
+  resolved 
"https://registry.yarnpkg.com/figures/-/figures-3.0.0.tgz#756275c964646163cc6f9197c7a0295dbfd04de9";
+  integrity 
sha512-HKri+WoWoUgr83pehn/SIgLOMZ9nAWC6dcGj26RY2R4F50u4+RTUz0RCrUlOV3nKRAICW1UGzyb+kcX2qK1S/g==
   dependencies:
     escape-string-regexp "^1.0.5"
 
@@ -2500,6 +2611,13 @@ fill-range@^4.0.0:
     repeat-string "^1.6.1"
     to-regex-range "^2.1.0"
 
+fill-range@^7.0.1:
+  version "7.0.1"
+  resolved 
"https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40";
+  integrity 
sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
+  dependencies:
+    to-regex-range "^5.0.1"
+
 finalhandler@~1.1.2:
   version "1.1.2"
   resolved 
"https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d";
@@ -2544,6 +2662,14 @@ find-up@^3.0.0:
   dependencies:
     locate-path "^3.0.0"
 
+find-up@^4.0.0, find-up@^4.1.0:
+  version "4.1.0"
+  resolved 
"https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19";
+  integrity 
sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
+  dependencies:
+    locate-path "^5.0.0"
+    path-exists "^4.0.0"
+
 findup-sync@3.0.0, findup-sync@^3.0.0:
   version "3.0.0"
   resolved 
"https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1";
@@ -2692,6 +2818,11 @@ fsevents@^1.2.7:
     nan "^2.12.1"
     node-pre-gyp "^0.12.0"
 
+fsevents@^2.0.6:
+  version "2.0.7"
+  resolved 
"https://registry.yarnpkg.com/fsevents/-/fsevents-2.0.7.tgz#382c9b443c6cbac4c57187cdda23aa3bf1ccfc2a";
+  integrity 
sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ==
+
 function-bind@^1.1.1:
   version "1.1.1"
   resolved 
"https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d";
@@ -2721,17 +2852,19 @@ get-caller-file@^2.0.1:
   resolved 
"https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e";
   integrity 
sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
 
-get-port@^4.2.0:
-  version "4.2.0"
-  resolved 
"https://registry.yarnpkg.com/get-port/-/get-port-4.2.0.tgz#e37368b1e863b7629c43c5a323625f95cf24b119";
-  integrity 
sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw==
+get-port@^5.0.0:
+  version "5.0.0"
+  resolved 
"https://registry.yarnpkg.com/get-port/-/get-port-5.0.0.tgz#aa22b6b86fd926dd7884de3e23332c9f70c031a6";
+  integrity 
sha512-imzMU0FjsZqNa6BqOjbbW6w5BivHIuQKopjpPqcnx0AVHJQKCxK1O+Ab3OrVXhrekqfVMjwA9ZYu062R+KcIsQ==
+  dependencies:
+    type-fest "^0.3.0"
 
 get-stream@^3.0.0:
   version "3.0.0"
   resolved 
"https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14";
   integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=
 
-get-stream@^4.0.0:
+get-stream@^4.0.0, get-stream@^4.1.0:
   version "4.1.0"
   resolved 
"https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5";
   integrity 
sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
@@ -2781,6 +2914,13 @@ glob-parent@^3.1.0:
     is-glob "^3.1.0"
     path-dirname "^1.0.0"
 
+glob-parent@^5.0.0:
+  version "5.0.0"
+  resolved 
"https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.0.0.tgz#1dc99f0f39b006d3e92c2c284068382f0c20e954";
+  integrity 
sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==
+  dependencies:
+    is-glob "^4.0.1"
+
 glob-stream@^6.1.0:
   version "6.1.0"
   resolved 
"https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz#7045c99413b3eb94888d83ab46d0b404cc7bdde4";
@@ -2809,7 +2949,7 @@ glob-watcher@^5.0.3:
     just-debounce "^1.0.0"
     object.defaults "^1.1.0"
 
-glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
+glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4:
   version "7.1.4"
   resolved 
"https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255";
   integrity 
sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==
@@ -2869,6 +3009,20 @@ globals@^11.1.0:
   resolved 
"https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e";
   integrity 
sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
 
+globby@^10.0.1:
+  version "10.0.1"
+  resolved 
"https://registry.yarnpkg.com/globby/-/globby-10.0.1.tgz#4782c34cb75dd683351335c5829cc3420e606b22";
+  integrity 
sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==
+  dependencies:
+    "@types/glob" "^7.1.1"
+    array-union "^2.1.0"
+    dir-glob "^3.0.1"
+    fast-glob "^3.0.3"
+    glob "^7.1.3"
+    ignore "^5.1.1"
+    merge2 "^1.2.3"
+    slash "^3.0.0"
+
 globby@^6.1.0:
   version "6.1.0"
   resolved 
"https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c";
@@ -2880,18 +3034,6 @@ globby@^6.1.0:
     pify "^2.0.0"
     pinkie-promise "^2.0.0"
 
-globby@^7.1.1:
-  version "7.1.1"
-  resolved 
"https://registry.yarnpkg.com/globby/-/globby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680";
-  integrity sha1-+yzP+UAfhgCUXfral0QMypcrhoA=
-  dependencies:
-    array-union "^1.0.1"
-    dir-glob "^2.0.0"
-    glob "^7.1.2"
-    ignore "^3.3.5"
-    pify "^3.0.0"
-    slash "^1.0.0"
-
 glogg@^1.0.0:
   version "1.0.2"
   resolved 
"https://registry.yarnpkg.com/glogg/-/glogg-1.0.2.tgz#2d7dd702beda22eb3bffadf880696da6d846313f";
@@ -2899,22 +3041,22 @@ glogg@^1.0.0:
   dependencies:
     sparkles "^1.0.0"
 
-got@^6.7.1:
-  version "6.7.1"
-  resolved 
"https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0";
-  integrity sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=
+got@^9.6.0:
+  version "9.6.0"
+  resolved 
"https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85";
+  integrity 
sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==
   dependencies:
-    create-error-class "^3.0.0"
+    "@sindresorhus/is" "^0.14.0"
+    "@szmarczak/http-timer" "^1.1.2"
+    cacheable-request "^6.0.0"
+    decompress-response "^3.3.0"
     duplexer3 "^0.1.4"
-    get-stream "^3.0.0"
-    is-redirect "^1.0.0"
-    is-retry-allowed "^1.0.0"
-    is-stream "^1.0.0"
-    lowercase-keys "^1.0.0"
-    safe-buffer "^5.0.1"
-    timed-out "^4.0.0"
-    unzip-response "^2.0.1"
-    url-parse-lax "^1.0.0"
+    get-stream "^4.1.0"
+    lowercase-keys "^1.0.1"
+    mimic-response "^1.0.1"
+    p-cancelable "^1.0.0"
+    to-readable-stream "^1.0.0"
+    url-parse-lax "^3.0.0"
 
 graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.15, 
graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0:
   version "4.2.2"
@@ -3036,6 +3178,11 @@ has-flag@^3.0.0:
   resolved 
"https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd";
   integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
 
+has-flag@^4.0.0:
+  version "4.0.0"
+  resolved 
"https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b";
+  integrity 
sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
+
 has-symbols@^1.0.0:
   version "1.0.0"
   resolved 
"https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44";
@@ -3077,6 +3224,11 @@ has-values@^1.0.0:
     is-number "^3.0.0"
     kind-of "^4.0.0"
 
+has-yarn@^2.1.0:
+  version "2.1.0"
+  resolved 
"https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77";
+  integrity 
sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==
+
 hash-base@^3.0.0:
   version "3.0.4"
   resolved 
"https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918";
@@ -3100,6 +3252,14 @@ hasha@^3.0.0:
   dependencies:
     is-stream "^1.0.1"
 
+hasha@^5.0.0:
+  version "5.0.0"
+  resolved 
"https://registry.yarnpkg.com/hasha/-/hasha-5.0.0.tgz#fdc3785caea03df29535fc8adb512c3d3a709004";
+  integrity 
sha512-PqWdhnQhq6tqD32hZv+l1e5mJHNSudjnaAzgAHfkGiU0ABN6lmbZF8abJIulQHbZ7oiHhP8yL6O910ICMc+5pw==
+  dependencies:
+    is-stream "^1.1.0"
+    type-fest "^0.3.0"
+
 highlight.js@^9.15.8:
   version "9.15.10"
   resolved 
"https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.15.10.tgz#7b18ed75c90348c045eef9ed08ca1319a2219ad2";
@@ -3131,6 +3291,11 @@ hosted-git-info@^2.1.4:
   resolved 
"https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.4.tgz#44119abaf4bc64692a16ace34700fed9c03e2546";
   integrity 
sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ==
 
+http-cache-semantics@^4.0.0:
+  version "4.0.3"
+  resolved 
"https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz#495704773277eeef6e43f9ab2c2c7d259dda25c5";
+  integrity 
sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew==
+
 http-errors@1.7.2:
   version "1.7.2"
   resolved 
"https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f";
@@ -3165,10 +3330,10 @@ iconv-lite@0.4.24, iconv-lite@^0.4.4, 
iconv-lite@~0.4.13:
   dependencies:
     safer-buffer ">= 2.1.2 < 3"
 
-idb-bridge@^0.0.7:
-  version "0.0.7"
-  resolved 
"https://registry.yarnpkg.com/idb-bridge/-/idb-bridge-0.0.7.tgz#34705d79ab992c4b5d5fa048c313ac5f803a972f";
-  integrity 
sha512-vGTYbX6ni8h/6B2POS6f1Nuzp47+Tna5MggQKDmQp1MLCPFbI8RXBzs1rvKWuMx+WKX3LtMWbxSm8hQBnI9DLA==
+idb-bridge@^0.0.9:
+  version "0.0.9"
+  resolved 
"https://registry.yarnpkg.com/idb-bridge/-/idb-bridge-0.0.9.tgz#28c9a9e50b275dc80316b29bdaec536ee96bc65b";
+  integrity 
sha512-MOoiDJvbhskEzyDtbOz9ecfGZ2Jx0CZ6L81h71fPjdERCkUUqvkt6p7RkChPr8GmteIfja2k9mIRNFkS7enmrQ==
 
 ieee754@^1.1.4:
   version "1.1.13"
@@ -3192,17 +3357,17 @@ ignore-walk@^3.0.1:
   dependencies:
     minimatch "^3.0.4"
 
-ignore@^3.3.5:
-  version "3.3.10"
-  resolved 
"https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043";
-  integrity 
sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==
+ignore@^5.1.1:
+  version "5.1.4"
+  resolved 
"https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf";
+  integrity 
sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==
 
 import-lazy@^2.1.0:
   version "2.1.0"
   resolved 
"https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43";
   integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=
 
-import-local@2.0.0, import-local@^2.0.0:
+import-local@2.0.0:
   version "2.0.0"
   resolved 
"https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d";
   integrity 
sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==
@@ -3210,6 +3375,14 @@ import-local@2.0.0, import-local@^2.0.0:
     pkg-dir "^3.0.0"
     resolve-cwd "^2.0.0"
 
+import-local@^3.0.2:
+  version "3.0.2"
+  resolved 
"https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6";
+  integrity 
sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==
+  dependencies:
+    pkg-dir "^4.2.0"
+    resolve-cwd "^3.0.0"
+
 imurmurhash@^0.1.4:
   version "0.1.4"
   resolved 
"https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea";
@@ -3220,6 +3393,11 @@ indent-string@^3.0.0, indent-string@^3.2.0:
   resolved 
"https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289";
   integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=
 
+indent-string@^4.0.0:
+  version "4.0.0"
+  resolved 
"https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251";
+  integrity 
sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
+
 infer-owner@^1.0.3:
   version "1.0.4"
   resolved 
"https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467";
@@ -3312,6 +3490,13 @@ is-binary-path@^1.0.0:
   dependencies:
     binary-extensions "^1.0.0"
 
+is-binary-path@^2.1.0:
+  version "2.1.0"
+  resolved 
"https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09";
+  integrity 
sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
+  dependencies:
+    binary-extensions "^2.0.0"
+
 is-buffer@^1.1.5:
   version "1.1.6"
   resolved 
"https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be";
@@ -3322,13 +3507,6 @@ is-buffer@^2.0.2:
   resolved 
"https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725";
   integrity 
sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==
 
-is-ci@^1.0.10:
-  version "1.2.1"
-  resolved 
"https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c";
-  integrity 
sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==
-  dependencies:
-    ci-info "^1.5.0"
-
 is-ci@^2.0.0:
   version "2.0.0"
   resolved 
"https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c";
@@ -3368,7 +3546,7 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2:
     is-data-descriptor "^1.0.0"
     kind-of "^6.0.2"
 
-is-error@^2.2.1:
+is-error@^2.2.2:
   version "2.2.2"
   resolved 
"https://registry.yarnpkg.com/is-error/-/is-error-2.2.2.tgz#c10ade187b3c93510c5470a5567833ee25649843";
   integrity 
sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg==
@@ -3402,6 +3580,11 @@ is-fullwidth-code-point@^2.0.0:
   resolved 
"https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f";
   integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
 
+is-fullwidth-code-point@^3.0.0:
+  version "3.0.0"
+  resolved 
"https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d";
+  integrity 
sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
+
 is-glob@^3.1.0:
   version "3.1.0"
   resolved 
"https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a";
@@ -3409,7 +3592,7 @@ is-glob@^3.1.0:
   dependencies:
     is-extglob "^2.1.0"
 
-is-glob@^4.0.0:
+is-glob@^4.0.0, is-glob@^4.0.1:
   version "4.0.1"
   resolved 
"https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc";
   integrity 
sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
@@ -3429,10 +3612,10 @@ is-negated-glob@^1.0.0:
   resolved 
"https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2";
   integrity sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=
 
-is-npm@^1.0.0:
-  version "1.0.0"
-  resolved 
"https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4";
-  integrity sha1-8vtjpl5JBbQGyGBydloaTceTufQ=
+is-npm@^3.0.0:
+  version "3.0.0"
+  resolved 
"https://registry.yarnpkg.com/is-npm/-/is-npm-3.0.0.tgz#ec9147bfb629c43f494cf67936a961edec7e8053";
+  integrity 
sha512-wsigDr1Kkschp2opC4G3yA6r9EgVA6NjRpWzIi9axXqeIaAATPRJc4uLujXe3Nd9uO8KoDyA4MD6aZSeXTADhA==
 
 is-number@^3.0.0:
   version "3.0.0"
@@ -3446,24 +3629,25 @@ is-number@^4.0.0:
   resolved 
"https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff";
   integrity 
sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==
 
+is-number@^7.0.0:
+  version "7.0.0"
+  resolved 
"https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b";
+  integrity 
sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
 is-obj@^1.0.0:
   version "1.0.1"
   resolved 
"https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f";
   integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8=
 
-is-observable@^0.2.0:
-  version "0.2.0"
-  resolved 
"https://registry.yarnpkg.com/is-observable/-/is-observable-0.2.0.tgz#b361311d83c6e5d726cabf5e250b0237106f5ae2";
-  integrity sha1-s2ExHYPG5dcmyr9eJQsCNxBvWuI=
-  dependencies:
-    symbol-observable "^0.2.2"
+is-obj@^2.0.0:
+  version "2.0.0"
+  resolved 
"https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982";
+  integrity 
sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==
 
-is-observable@^1.1.0:
-  version "1.1.0"
-  resolved 
"https://registry.yarnpkg.com/is-observable/-/is-observable-1.1.0.tgz#b3e986c8f44de950867cab5403f5a3465005975e";
-  integrity 
sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==
-  dependencies:
-    symbol-observable "^1.1.0"
+is-observable@^2.0.0:
+  version "2.0.0"
+  resolved 
"https://registry.yarnpkg.com/is-observable/-/is-observable-2.0.0.tgz#327af1e8cdea9cd717f95911b87c5d34301721a6";
+  integrity 
sha512-fhBZv3eFKUbyHXZ1oHujdo2tZ+CNbdpdzzlENgCGZUC8keoGxUew2jYFLYcUB4qo7LDD03o4KK11m/QYD7kEjg==
 
 is-path-cwd@^2.0.0:
   version "2.2.0"
@@ -3503,16 +3687,18 @@ is-plain-object@^2.0.1, is-plain-object@^2.0.3, 
is-plain-object@^2.0.4:
   dependencies:
     isobject "^3.0.1"
 
+is-plain-object@^3.0.0:
+  version "3.0.0"
+  resolved 
"https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.0.tgz#47bfc5da1b5d50d64110806c199359482e75a928";
+  integrity 
sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg==
+  dependencies:
+    isobject "^4.0.0"
+
 is-promise@^2.1.0:
   version "2.1.0"
   resolved 
"https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa";
   integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=
 
-is-redirect@^1.0.0:
-  version "1.0.0"
-  resolved 
"https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24";
-  integrity sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=
-
 is-relative@^1.0.0:
   version "1.0.0"
   resolved 
"https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d";
@@ -3520,16 +3706,16 @@ is-relative@^1.0.0:
   dependencies:
     is-unc-path "^1.0.0"
 
-is-retry-allowed@^1.0.0:
-  version "1.1.0"
-  resolved 
"https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34";
-  integrity sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=
-
-is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0:
+is-stream@^1.0.1, is-stream@^1.1.0:
   version "1.1.0"
   resolved 
"https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44";
   integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
 
+is-typedarray@^1.0.0:
+  version "1.0.0"
+  resolved 
"https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a";
+  integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
+
 is-unc-path@^1.0.0:
   version "1.0.0"
   resolved 
"https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d";
@@ -3562,6 +3748,11 @@ is-wsl@^1.1.0:
   resolved 
"https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d";
   integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=
 
+is-yarn-global@^0.3.0:
+  version "0.3.0"
+  resolved 
"https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232";
+  integrity 
sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==
+
 isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
   version "1.0.0"
   resolved 
"https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11";
@@ -3584,6 +3775,11 @@ isobject@^3.0.0, isobject@^3.0.1:
   resolved 
"https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df";
   integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
 
+isobject@^4.0.0:
+  version "4.0.0"
+  resolved 
"https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0";
+  integrity 
sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==
+
 istanbul-lib-coverage@^2.0.5:
   version "2.0.5"
   resolved 
"https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49";
@@ -3674,6 +3870,11 @@ jsesc@~0.5.0:
   resolved 
"https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d";
   integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=
 
+json-buffer@3.0.0:
+  version "3.0.0"
+  resolved 
"https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898";
+  integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=
+
 json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2:
   version "1.0.2"
   resolved 
"https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9";
@@ -3715,6 +3916,13 @@ just-debounce@^1.0.0:
   resolved 
"https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.0.0.tgz#87fccfaeffc0b68cd19d55f6722943f929ea35ea";
   integrity sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=
 
+keyv@^3.0.0:
+  version "3.1.0"
+  resolved 
"https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9";
+  integrity 
sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==
+  dependencies:
+    json-buffer "3.0.0"
+
 kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
   version "3.2.2"
   resolved 
"https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64";
@@ -3747,12 +3955,12 @@ last-run@^1.1.0:
     default-resolution "^2.0.0"
     es6-weak-map "^2.0.1"
 
-latest-version@^3.0.0:
-  version "3.1.0"
-  resolved 
"https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15";
-  integrity sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=
+latest-version@^5.0.0:
+  version "5.1.0"
+  resolved 
"https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face";
+  integrity 
sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==
   dependencies:
-    package-json "^4.0.0"
+    package-json "^6.3.0"
 
 lazystream@^1.0.0:
   version "1.0.0"
@@ -3858,37 +4066,29 @@ locate-path@^3.0.0:
     p-locate "^3.0.0"
     path-exists "^3.0.0"
 
-lodash.clone@^4.5.0:
-  version "4.5.0"
-  resolved 
"https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6";
-  integrity sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=
+locate-path@^5.0.0:
+  version "5.0.0"
+  resolved 
"https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0";
+  integrity 
sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
+  dependencies:
+    p-locate "^4.1.0"
 
 lodash.clonedeep@^4.5.0:
   version "4.5.0"
   resolved 
"https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef";
   integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=
 
-lodash.clonedeepwith@^4.5.0:
-  version "4.5.0"
-  resolved 
"https://registry.yarnpkg.com/lodash.clonedeepwith/-/lodash.clonedeepwith-4.5.0.tgz#6ee30573a03a1a60d670a62ef33c10cf1afdbdd4";
-  integrity sha1-buMFc6A6GmDWcKYu8zwQzxr9vdQ=
-
-lodash.debounce@^4.0.3:
-  version "4.0.8"
-  resolved 
"https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af";
-  integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
-
 lodash.defaults@^4.2.0:
   version "4.2.0"
   resolved 
"https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c";
   integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=
 
-lodash.difference@^4.3.0, lodash.difference@^4.5.0:
+lodash.difference@^4.5.0:
   version "4.5.0"
   resolved 
"https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c";
   integrity sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=
 
-lodash.flatten@^4.2.0, lodash.flatten@^4.4.0:
+lodash.flatten@^4.4.0:
   version "4.4.0"
   resolved 
"https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f";
   integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=
@@ -3945,7 +4145,7 @@ loose-envify@^1.1.0, loose-envify@^1.4.0:
   dependencies:
     js-tokens "^3.0.0 || ^4.0.0"
 
-loud-rejection@^1.0.0, loud-rejection@^1.2.0:
+loud-rejection@^1.0.0:
   version "1.6.0"
   resolved 
"https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f";
   integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=
@@ -3953,11 +4153,24 @@ loud-rejection@^1.0.0, loud-rejection@^1.2.0:
     currently-unhandled "^0.4.1"
     signal-exit "^3.0.0"
 
-lowercase-keys@^1.0.0:
+loud-rejection@^2.1.0:
+  version "2.1.0"
+  resolved 
"https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-2.1.0.tgz#4020547ddbc39ed711c8434326df9fc7d2395355";
+  integrity 
sha512-g/6MQxUXYHeVqZ4PGpPL1fS1fOvlXoi7bay0pizmjAd/3JhyXwxzwrnr74yzdmhuerlslbRJ3x7IOXzFz0cE5w==
+  dependencies:
+    currently-unhandled "^0.4.1"
+    signal-exit "^3.0.2"
+
+lowercase-keys@^1.0.0, lowercase-keys@^1.0.1:
   version "1.0.1"
   resolved 
"https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f";
   integrity 
sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==
 
+lowercase-keys@^2.0.0:
+  version "2.0.0"
+  resolved 
"https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479";
+  integrity 
sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==
+
 lru-cache@^4.0.1:
   version "4.1.5"
   resolved 
"https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd";
@@ -3993,6 +4206,13 @@ make-dir@^2.0.0, make-dir@^2.1.0:
     pify "^4.0.1"
     semver "^5.6.0"
 
+make-dir@^3.0.0:
+  version "3.0.0"
+  resolved 
"https://registry.yarnpkg.com/make-dir/-/make-dir-3.0.0.tgz#1b5f39f6b9270ed33f9f054c5c0f84304989f801";
+  integrity 
sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==
+  dependencies:
+    semver "^6.0.0"
+
 make-iterator@^1.0.0:
   version "1.0.1"
   resolved 
"https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6";
@@ -4054,12 +4274,12 @@ matchdep@^2.0.0:
     resolve "^1.4.0"
     stack-trace "0.0.10"
 
-matcher@^1.1.1:
-  version "1.1.1"
-  resolved 
"https://registry.yarnpkg.com/matcher/-/matcher-1.1.1.tgz#51d8301e138f840982b338b116bb0c09af62c1c2";
-  integrity 
sha512-+BmqxWIubKTRKNWx/ahnCkk3mG8m7OturVlqq6HiojGJTd5hVYbgZm6WzcYPCoB+KBT4Vd6R7WSRG2OADNaCjg==
+matcher@^2.0.0:
+  version "2.0.0"
+  resolved 
"https://registry.yarnpkg.com/matcher/-/matcher-2.0.0.tgz#85fe38d97670dbd2a46590cf099401e2ffb4755c";
+  integrity 
sha512-nlmfSlgHBFx36j/Pl/KQPbIaqE8Zf0TqmSMjsuddHDg6PMSVgmyW9HpkLs0o0M1n2GIZ/S2BZBLIww/xjhiGng==
   dependencies:
-    escape-string-regexp "^1.0.4"
+    escape-string-regexp "^2.0.0"
 
 md5-hex@^2.0.0:
   version "2.0.0"
@@ -4068,6 +4288,13 @@ md5-hex@^2.0.0:
   dependencies:
     md5-o-matic "^0.1.1"
 
+md5-hex@^3.0.1:
+  version "3.0.1"
+  resolved 
"https://registry.yarnpkg.com/md5-hex/-/md5-hex-3.0.1.tgz#be3741b510591434b2784d79e556eefc2c9a8e5c";
+  integrity 
sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==
+  dependencies:
+    blueimp-md5 "^2.10.0"
+
 md5-o-matic@^0.1.1:
   version "0.1.1"
   resolved 
"https://registry.yarnpkg.com/md5-o-matic/-/md5-o-matic-0.1.1.tgz#822bccd65e117c514fab176b25945d54100a03c3";
@@ -4131,6 +4358,11 @@ merge-source-map@^1.1.0:
   dependencies:
     source-map "^0.6.1"
 
+merge2@^1.2.3:
+  version "1.2.4"
+  resolved 
"https://registry.yarnpkg.com/merge2/-/merge2-1.2.4.tgz#c9269589e6885a60cf80605d9522d4b67ca646e3";
+  integrity 
sha512-FYE8xI+6pjFOhokZu0We3S5NKCirLbCzSh2Usf3qEyr4X8U+0jNg9P8RZ4qz+V2UoECLVwSyzU3LxXBaLGtD3A==
+
 methods@~1.1.2:
   version "1.1.2"
   resolved 
"https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee";
@@ -4155,6 +4387,14 @@ micromatch@^3.0.4, micromatch@^3.1.10, 
micromatch@^3.1.4, micromatch@^3.1.9:
     snapdragon "^0.8.1"
     to-regex "^3.0.2"
 
+micromatch@^4.0.2:
+  version "4.0.2"
+  resolved 
"https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259";
+  integrity 
sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==
+  dependencies:
+    braces "^3.0.1"
+    picomatch "^2.0.5"
+
 miller-rabin@^4.0.0:
   version "4.0.1"
   resolved 
"https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d";
@@ -4185,11 +4425,16 @@ mimic-fn@^1.0.0:
   resolved 
"https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022";
   integrity 
sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==
 
-mimic-fn@^2.0.0:
+mimic-fn@^2.0.0, mimic-fn@^2.1.0:
   version "2.1.0"
   resolved 
"https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b";
   integrity 
sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
 
+mimic-response@^1.0.0, mimic-response@^1.0.1:
+  version "1.0.1"
+  resolved 
"https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b";
+  integrity 
sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==
+
 minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
   version "1.0.1"
   resolved 
"https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7";
@@ -4303,21 +4548,11 @@ ms@2.1.1:
   resolved 
"https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a";
   integrity 
sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
 
-ms@^2.1.1:
+ms@^2.1.1, ms@^2.1.2:
   version "2.1.2"
   resolved 
"https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009";
   integrity 
sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
 
-multimatch@^3.0.0:
-  version "3.0.0"
-  resolved 
"https://registry.yarnpkg.com/multimatch/-/multimatch-3.0.0.tgz#0e2534cc6bc238d9ab67e1b9cd5fcd85a6dbf70b";
-  integrity 
sha512-22foS/gqQfANZ3o+W7ST2x25ueHDVNWl/b9OlGcLpy/iKxjCpvcNCM51YCenUi7Mt/jAjjqv8JwZRs8YP5sRjA==
-  dependencies:
-    array-differ "^2.0.3"
-    array-union "^1.0.2"
-    arrify "^1.0.1"
-    minimatch "^3.0.4"
-
 mute-stdout@^1.0.0:
   version "1.0.1"
   resolved 
"https://registry.yarnpkg.com/mute-stdout/-/mute-stdout-1.0.1.tgz#acb0300eb4de23a7ddeec014e3e96044b3472331";
@@ -4454,6 +4689,11 @@ normalize-path@^3.0.0:
   resolved 
"https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65";
   integrity 
sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
 
+normalize-url@^4.1.0:
+  version "4.3.0"
+  resolved 
"https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.3.0.tgz#9c49e10fc1876aeb76dba88bf1b2b5d9fa57b2ee";
+  integrity 
sha512-0NLtR71o4k6GLP+mr6Ty34c5GA6CMoEsncKJxvQd8NzPxaHRJNnb5gZE8R1XF4CPIS7QPHLJ74IFszwtNVAHVQ==
+
 now-and-later@^2.0.0:
   version "2.0.1"
   resolved 
"https://registry.yarnpkg.com/now-and-later/-/now-and-later-2.0.1.tgz#8e579c8685764a7cc02cb680380e94f43ccb1f7c";
@@ -4596,12 +4836,12 @@ object.reduce@^1.0.0:
     for-own "^1.0.0"
     make-iterator "^1.0.0"
 
-observable-to-promise@^0.5.0:
-  version "0.5.0"
-  resolved 
"https://registry.yarnpkg.com/observable-to-promise/-/observable-to-promise-0.5.0.tgz#c828f0f0dc47e9f86af8a4977c5d55076ce7a91f";
-  integrity sha1-yCjw8NxH6fhq+KSXfF1VB2znqR8=
+observable-to-promise@^1.0.0:
+  version "1.0.0"
+  resolved 
"https://registry.yarnpkg.com/observable-to-promise/-/observable-to-promise-1.0.0.tgz#37e136f16a15385ac063411ada0e1202bfff58f4";
+  integrity 
sha512-cqnGUrNsE6vdVDTPAX9/WeVzwy/z37vdxupdQXU8vgTXRFH72KCZiZga8aca2ulRPIeem8W3vW9rQHBwfIl2WA==
   dependencies:
-    is-observable "^0.2.0"
+    is-observable "^2.0.0"
     symbol-observable "^1.0.4"
 
 on-finished@~2.3.0:
@@ -4625,6 +4865,13 @@ onetime@^2.0.0:
   dependencies:
     mimic-fn "^1.0.0"
 
+onetime@^5.1.0:
+  version "5.1.0"
+  resolved 
"https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5";
+  integrity 
sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==
+  dependencies:
+    mimic-fn "^2.1.0"
+
 opener@^1.5.1:
   version "1.5.1"
   resolved 
"https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed";
@@ -4638,7 +4885,7 @@ optimist@^0.6.1:
     minimist "~0.0.1"
     wordwrap "~0.0.2"
 
-ora@^3.2.0:
+ora@^3.4.0:
   version "3.4.0"
   resolved 
"https://registry.yarnpkg.com/ora/-/ora-3.4.0.tgz#bf0752491059a3ef3ed4c85097531de9fdbcd318";
   integrity 
sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==
@@ -4696,6 +4943,11 @@ osenv@^0.1.4:
     os-homedir "^1.0.0"
     os-tmpdir "^1.0.0"
 
+p-cancelable@^1.0.0:
+  version "1.1.0"
+  resolved 
"https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc";
+  integrity 
sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==
+
 p-defer@^1.0.0:
   version "1.0.0"
   resolved 
"https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c";
@@ -4718,7 +4970,7 @@ p-limit@^1.1.0:
   dependencies:
     p-try "^1.0.0"
 
-p-limit@^2.0.0:
+p-limit@^2.0.0, p-limit@^2.2.0:
   version "2.2.1"
   resolved 
"https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537";
   integrity 
sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==
@@ -4739,6 +4991,13 @@ p-locate@^3.0.0:
   dependencies:
     p-limit "^2.0.0"
 
+p-locate@^4.1.0:
+  version "4.1.0"
+  resolved 
"https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07";
+  integrity 
sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
+  dependencies:
+    p-limit "^2.2.0"
+
 p-map@^2.0.0:
   version "2.1.0"
   resolved 
"https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175";
@@ -4764,15 +5023,25 @@ package-hash@^3.0.0:
     lodash.flattendeep "^4.4.0"
     release-zalgo "^1.0.0"
 
-package-json@^4.0.0:
-  version "4.0.1"
-  resolved 
"https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed";
-  integrity sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=
+package-hash@^4.0.0:
+  version "4.0.0"
+  resolved 
"https://registry.yarnpkg.com/package-hash/-/package-hash-4.0.0.tgz#3537f654665ec3cc38827387fc904c163c54f506";
+  integrity 
sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==
+  dependencies:
+    graceful-fs "^4.1.15"
+    hasha "^5.0.0"
+    lodash.flattendeep "^4.4.0"
+    release-zalgo "^1.0.0"
+
+package-json@^6.3.0:
+  version "6.5.0"
+  resolved 
"https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0";
+  integrity 
sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==
   dependencies:
-    got "^6.7.1"
-    registry-auth-token "^3.0.1"
-    registry-url "^3.0.3"
-    semver "^5.1.0"
+    got "^9.6.0"
+    registry-auth-token "^4.0.0"
+    registry-url "^5.0.0"
+    semver "^6.2.0"
 
 pako@~1.0.5:
   version "1.0.10"
@@ -4824,7 +5093,7 @@ parse-json@^4.0.0:
     error-ex "^1.3.1"
     json-parse-better-errors "^1.0.1"
 
-parse-ms@^2.0.0:
+parse-ms@^2.1.0:
   version "2.1.0"
   resolved 
"https://registry.yarnpkg.com/parse-ms/-/parse-ms-2.1.0.tgz#348565a753d4391fa524029956b172cb7753097d";
   integrity 
sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==
@@ -4871,6 +5140,11 @@ path-exists@^3.0.0:
   resolved 
"https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515";
   integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=
 
+path-exists@^4.0.0:
+  version "4.0.0"
+  resolved 
"https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3";
+  integrity 
sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
+
 path-is-absolute@^1.0.0:
   version "1.0.1"
   resolved 
"https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f";
@@ -4924,6 +5198,11 @@ path-type@^3.0.0:
   dependencies:
     pify "^3.0.0"
 
+path-type@^4.0.0:
+  version "4.0.0"
+  resolved 
"https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b";
+  integrity 
sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
+
 pbkdf2@^3.0.3:
   version "3.0.17"
   resolved 
"https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6";
@@ -4935,6 +5214,11 @@ pbkdf2@^3.0.3:
     safe-buffer "^5.0.1"
     sha.js "^2.4.8"
 
+picomatch@^2.0.4, picomatch@^2.0.5:
+  version "2.0.7"
+  resolved 
"https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6";
+  integrity 
sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==
+
 pify@^2.0.0:
   version "2.3.0"
   resolved 
"https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c";
@@ -4962,7 +5246,7 @@ pinkie@^2.0.0:
   resolved 
"https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870";
   integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
 
-pkg-conf@^3.0.0:
+pkg-conf@^3.1.0:
   version "3.1.0"
   resolved 
"https://registry.yarnpkg.com/pkg-conf/-/pkg-conf-3.1.0.tgz#d9f9c75ea1bae0e77938cde045b276dac7cc69ae";
   integrity 
sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==
@@ -4977,6 +5261,13 @@ pkg-dir@^3.0.0:
   dependencies:
     find-up "^3.0.0"
 
+pkg-dir@^4.2.0:
+  version "4.2.0"
+  resolved 
"https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3";
+  integrity 
sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==
+  dependencies:
+    find-up "^4.0.0"
+
 plugin-error@^1.0.0, plugin-error@^1.0.1:
   version "1.0.1"
   resolved 
"https://registry.yarnpkg.com/plugin-error/-/plugin-error-1.0.1.tgz#77016bd8919d0ac377fdcdd0322328953ca5781c";
@@ -4987,7 +5278,7 @@ plugin-error@^1.0.0, plugin-error@^1.0.1:
     arr-union "^3.1.0"
     extend-shallow "^3.0.2"
 
-plur@^3.0.1:
+plur@^3.1.1:
   version "3.1.1"
   resolved 
"https://registry.yarnpkg.com/plur/-/plur-3.1.1.tgz#60267967866a8d811504fe58f2faaba237546a5b";
   integrity 
sha512-t1Ax8KUvV3FFII8ltczPn2tJdjqbd1sIzu6t4JL7nQ3EyeL/lTrj5PWKb06ic5/6XYDr65rQ4uzQEGN70/6X5w==
@@ -5015,22 +5306,22 @@ posix-character-classes@^0.1.0:
   resolved 
"https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab";
   integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
 
-prepend-http@^1.0.1:
-  version "1.0.4"
-  resolved 
"https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc";
-  integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=
+prepend-http@^2.0.0:
+  version "2.0.0"
+  resolved 
"https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897";
+  integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=
 
 pretty-hrtime@^1.0.0:
   version "1.0.3"
   resolved 
"https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1";
   integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=
 
-pretty-ms@^4.0.0:
-  version "4.0.0"
-  resolved 
"https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-4.0.0.tgz#31baf41b94fd02227098aaa03bd62608eb0d6e92";
-  integrity 
sha512-qG66ahoLCwpLXD09ZPHSCbUWYTqdosB7SMP4OffgTgL2PBKXMuUsrk5Bwg8q4qPkjTXsKBMr+YK3Ltd/6F9s/Q==
+pretty-ms@^5.0.0:
+  version "5.0.0"
+  resolved 
"https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-5.0.0.tgz#6133a8f55804b208e4728f6aa7bf01085e951e24";
+  integrity 
sha512-94VRYjL9k33RzfKiGokPBPpsmloBYSf5Ri+Pq19zlsEcUKFob+admeXr5eFDRuPjFmEOcjJvPGdillYOJyvZ7Q==
   dependencies:
-    parse-ms "^2.0.0"
+    parse-ms "^2.1.0"
 
 process-nextick-args@^2.0.0, process-nextick-args@~2.0.0:
   version "2.0.1"
@@ -5193,7 +5484,7 @@ raw-body@2.4.0:
     iconv-lite "0.4.24"
     unpipe "1.0.0"
 
-rc@^1.0.1, rc@^1.1.6, rc@^1.2.7:
+rc@^1.2.7, rc@^1.2.8:
   version "1.2.8"
   resolved 
"https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed";
   integrity 
sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
@@ -5300,6 +5591,13 @@ readdirp@^2.2.1:
     micromatch "^3.1.10"
     readable-stream "^2.0.2"
 
+readdirp@^3.1.1:
+  version "3.1.2"
+  resolved 
"https://registry.yarnpkg.com/readdirp/-/readdirp-3.1.2.tgz#fa85d2d14d4289920e4671dead96431add2ee78a";
+  integrity 
sha512-8rhl0xs2cxfVsqzreYCvs8EwBfn/DhVdqtoLmw19uI3SC5avYX9teCurlErfpPXGmYtMHReGaP2RsLnFvz/lnw==
+  dependencies:
+    picomatch "^2.0.4"
+
 rechoir@^0.6.2:
   version "0.6.2"
   resolved 
"https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384";
@@ -5347,20 +5645,20 @@ regexpu-core@^4.5.4:
     unicode-match-property-ecmascript "^1.0.4"
     unicode-match-property-value-ecmascript "^1.1.0"
 
-registry-auth-token@^3.0.1:
-  version "3.4.0"
-  resolved 
"https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.4.0.tgz#d7446815433f5d5ed6431cd5dca21048f66b397e";
-  integrity 
sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==
+registry-auth-token@^4.0.0:
+  version "4.0.0"
+  resolved 
"https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.0.0.tgz#30e55961eec77379da551ea5c4cf43cbf03522be";
+  integrity 
sha512-lpQkHxd9UL6tb3k/aHAVfnVtn+Bcs9ob5InuFLLEDqSqeq+AljB8GZW9xY0x7F+xYwEcjKe07nyoxzEYz6yvkw==
   dependencies:
-    rc "^1.1.6"
+    rc "^1.2.8"
     safe-buffer "^5.0.1"
 
-registry-url@^3.0.3:
-  version "3.1.0"
-  resolved 
"https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942";
-  integrity sha1-PU74cPc93h138M+aOBQyRE4XSUI=
+registry-url@^5.0.0:
+  version "5.1.0"
+  resolved 
"https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009";
+  integrity 
sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==
   dependencies:
-    rc "^1.0.1"
+    rc "^1.2.8"
 
 regjsgen@^0.5.0:
   version "0.5.0"
@@ -5454,6 +5752,13 @@ resolve-cwd@^2.0.0:
   dependencies:
     resolve-from "^3.0.0"
 
+resolve-cwd@^3.0.0:
+  version "3.0.0"
+  resolved 
"https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d";
+  integrity 
sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==
+  dependencies:
+    resolve-from "^5.0.0"
+
 resolve-dir@^1.0.0, resolve-dir@^1.0.1:
   version "1.0.1"
   resolved 
"https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43";
@@ -5472,6 +5777,11 @@ resolve-from@^4.0.0:
   resolved 
"https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6";
   integrity 
sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
 
+resolve-from@^5.0.0:
+  version "5.0.0"
+  resolved 
"https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69";
+  integrity 
sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
+
 resolve-options@^1.1.0:
   version "1.1.0"
   resolved 
"https://registry.yarnpkg.com/resolve-options/-/resolve-options-1.1.0.tgz#32bb9e39c06d67338dc9378c0d6d6074566ad131";
@@ -5491,6 +5801,13 @@ resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, 
resolve@^1.3.2, resolve@^1.4.0:
   dependencies:
     path-parse "^1.0.6"
 
+responselike@^1.0.2:
+  version "1.0.2"
+  resolved 
"https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7";
+  integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=
+  dependencies:
+    lowercase-keys "^1.0.0"
+
 restore-cursor@^2.0.0:
   version "2.0.0"
   resolved 
"https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf";
@@ -5499,11 +5816,24 @@ restore-cursor@^2.0.0:
     onetime "^2.0.0"
     signal-exit "^3.0.2"
 
+restore-cursor@^3.1.0:
+  version "3.1.0"
+  resolved 
"https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e";
+  integrity 
sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==
+  dependencies:
+    onetime "^5.1.0"
+    signal-exit "^3.0.2"
+
 ret@~0.1.10:
   version "0.1.15"
   resolved 
"https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc";
   integrity 
sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
 
+reusify@^1.0.0:
+  version "1.0.4"
+  resolved 
"https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76";
+  integrity 
sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+
 rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3:
   version "2.7.1"
   resolved 
"https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec";
@@ -5519,6 +5849,11 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
     hash-base "^3.0.0"
     inherits "^2.0.1"
 
+run-parallel@^1.1.9:
+  version "1.1.9"
+  resolved 
"https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679";
+  integrity 
sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==
+
 run-queue@^1.0.0, run-queue@^1.0.3:
   version "1.0.3"
   resolved 
"https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47";
@@ -5584,12 +5919,12 @@ semver-greatest-satisfied-range@^1.1.0:
   dependencies:
     sver-compat "^1.5.0"
 
-"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, 
semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0:
+"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.3.0, semver@^5.4.1, 
semver@^5.5.0, semver@^5.5.1, semver@^5.6.0:
   version "5.7.1"
   resolved 
"https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7";
   integrity 
sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
 
-semver@^6.0.0:
+semver@^6.0.0, semver@^6.2.0:
   version "6.3.0"
   resolved 
"https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d";
   integrity 
sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
@@ -5692,28 +6027,20 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
   resolved 
"https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d";
   integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
 
-slash@^1.0.0:
-  version "1.0.0"
-  resolved 
"https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55";
-  integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=
-
-slash@^2.0.0:
-  version "2.0.0"
-  resolved 
"https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44";
-  integrity 
sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==
+slash@^3.0.0:
+  version "3.0.0"
+  resolved 
"https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634";
+  integrity 
sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
 
-slice-ansi@^1.0.0:
-  version "1.0.0"
-  resolved 
"https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d";
-  integrity 
sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==
+slice-ansi@^2.1.0:
+  version "2.1.0"
+  resolved 
"https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636";
+  integrity 
sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==
   dependencies:
+    ansi-styles "^3.2.0"
+    astral-regex "^1.0.0"
     is-fullwidth-code-point "^2.0.0"
 
-slide@^1.1.5:
-  version "1.1.6"
-  resolved 
"https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707";
-  integrity sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=
-
 snapdragon-node@^2.0.1:
   version "2.1.1"
   resolved 
"https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b";
@@ -5760,7 +6087,7 @@ source-map-resolve@^0.5.0:
     source-map-url "^0.4.0"
     urix "^0.1.0"
 
-source-map-support@^0.5.11, source-map-support@^0.5.12, 
source-map-support@^0.5.3, source-map-support@~0.5.12:
+source-map-support@^0.5.12, source-map-support@^0.5.13, 
source-map-support@^0.5.3, source-map-support@~0.5.12:
   version "0.5.13"
   resolved 
"https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932";
   integrity 
sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==
@@ -5921,7 +6248,7 @@ string-width@^1.0.1, string-width@^1.0.2:
     is-fullwidth-code-point "^1.0.0"
     strip-ansi "^3.0.0"
 
-"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1:
+"string-width@^1.0.2 || 2", string-width@^2.1.1:
   version "2.1.1"
   resolved 
"https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e";
   integrity 
sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
@@ -5938,6 +6265,15 @@ string-width@^3.0.0, string-width@^3.1.0:
     is-fullwidth-code-point "^2.0.0"
     strip-ansi "^5.1.0"
 
+string-width@^4.1.0:
+  version "4.1.0"
+  resolved 
"https://registry.yarnpkg.com/string-width/-/string-width-4.1.0.tgz#ba846d1daa97c3c596155308063e075ed1c99aff";
+  integrity 
sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ==
+  dependencies:
+    emoji-regex "^8.0.0"
+    is-fullwidth-code-point "^3.0.0"
+    strip-ansi "^5.2.0"
+
 string_decoder@^1.0.0, string_decoder@^1.1.1:
   version "1.3.0"
   resolved 
"https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e";
@@ -5973,10 +6309,10 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
   dependencies:
     ansi-regex "^4.1.0"
 
-strip-bom-buf@^1.0.0:
-  version "1.0.0"
-  resolved 
"https://registry.yarnpkg.com/strip-bom-buf/-/strip-bom-buf-1.0.0.tgz#1cb45aaf57530f4caf86c7f75179d2c9a51dd572";
-  integrity sha1-HLRar1dTD0yvhsf3UXnSyaUd1XI=
+strip-bom-buf@^2.0.0:
+  version "2.0.0"
+  resolved 
"https://registry.yarnpkg.com/strip-bom-buf/-/strip-bom-buf-2.0.0.tgz#ff9c223937f8e7154b77e9de9bde094186885c15";
+  integrity 
sha512-gLFNHucd6gzb8jMsl5QmZ3QgnUJmp7qn4uUSHNwEXumAp7YizoGYw19ZUVfuq4aBOQUtyn2k8X/CwzWB73W2lQ==
   dependencies:
     is-utf8 "^0.2.1"
 
@@ -6037,6 +6373,13 @@ supports-color@^5.3.0:
   dependencies:
     has-flag "^3.0.0"
 
+supports-color@^7.0.0:
+  version "7.0.0"
+  resolved 
"https://registry.yarnpkg.com/supports-color/-/supports-color-7.0.0.tgz#f2392c50ab35bb3cae7beebf24d254a19f880c06";
+  integrity 
sha512-WRt32iTpYEZWYOpcetGm0NPeSvaebccx7hhS/5M6sAiqnhedtFCHFxkjzZlJvFNCPowiKSFGiZk5USQDFy83vQ==
+  dependencies:
+    has-flag "^4.0.0"
+
 sver-compat@^1.5.0:
   version "1.5.0"
   resolved 
"https://registry.yarnpkg.com/sver-compat/-/sver-compat-1.5.0.tgz#3cf87dfeb4d07b4a3f14827bc186b3fd0c645cd8";
@@ -6045,12 +6388,7 @@ sver-compat@^1.5.0:
     es6-iterator "^2.0.1"
     es6-symbol "^3.1.1"
 
-symbol-observable@^0.2.2:
-  version "0.2.4"
-  resolved 
"https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-0.2.4.tgz#95a83db26186d6af7e7a18dbd9760a2f86d08f40";
-  integrity sha1-lag9smGG1q9+ehjb2XYKL4bQj0A=
-
-symbol-observable@^1.0.4, symbol-observable@^1.1.0:
+symbol-observable@^1.0.4:
   version "1.2.0"
   resolved 
"https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804";
   integrity 
sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
@@ -6158,11 +6496,6 @@ time-zone@^1.0.0:
   resolved 
"https://registry.yarnpkg.com/time-zone/-/time-zone-1.0.0.tgz#99c5bf55958966af6d06d83bdf3800dc82faec5d";
   integrity sha1-mcW/VZWJZq9tBtg73zgA3IL67F0=
 
-timed-out@^4.0.0:
-  version "4.0.1"
-  resolved 
"https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f";
-  integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=
-
 timers-browserify@^2.0.4:
   version "2.0.11"
   resolved 
"https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f";
@@ -6195,6 +6528,11 @@ to-object-path@^0.3.0:
   dependencies:
     kind-of "^3.0.2"
 
+to-readable-stream@^1.0.0:
+  version "1.0.0"
+  resolved 
"https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771";
+  integrity 
sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==
+
 to-regex-range@^2.1.0:
   version "2.1.1"
   resolved 
"https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38";
@@ -6203,6 +6541,13 @@ to-regex-range@^2.1.0:
     is-number "^3.0.0"
     repeat-string "^1.6.1"
 
+to-regex-range@^5.0.1:
+  version "5.0.1"
+  resolved 
"https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4";
+  integrity 
sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+  dependencies:
+    is-number "^7.0.0"
+
 to-regex@^3.0.1, to-regex@^3.0.2:
   version "3.0.2"
   resolved 
"https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce";
@@ -6250,10 +6595,10 @@ tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0:
   resolved 
"https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a";
   integrity 
sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
 
-tslint@^5.14.0:
-  version "5.18.0"
-  resolved 
"https://registry.yarnpkg.com/tslint/-/tslint-5.18.0.tgz#f61a6ddcf372344ac5e41708095bbf043a147ac6";
-  integrity 
sha512-Q3kXkuDEijQ37nXZZLKErssQVnwCV/+23gFEMROi8IlbaBG6tXqLPQJ5Wjcyt/yHPKBC+hD5SzuGaMora+ZS6w==
+tslint@^5.19.0:
+  version "5.19.0"
+  resolved 
"https://registry.yarnpkg.com/tslint/-/tslint-5.19.0.tgz#a2cbd4a7699386da823f6b499b8394d6c47bb968";
+  integrity 
sha512-1LwwtBxfRJZnUvoS9c0uj8XQtAnyhWr9KlNvDIdB+oXyT+VpsOAaEhEgKi1HrZ8rq0ki/AAnbGSv4KM6/AfVZw==
   dependencies:
     "@babel/code-frame" "^7.0.0"
     builtin-modules "^1.1.1"
@@ -6286,6 +6631,11 @@ type-fest@^0.3.0:
   resolved 
"https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1";
   integrity 
sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==
 
+type-fest@^0.5.2:
+  version "0.5.2"
+  resolved 
"https://registry.yarnpkg.com/type-fest/-/type-fest-0.5.2.tgz#d6ef42a0356c6cd45f49485c3b6281fc148e48a2";
+  integrity 
sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw==
+
 type-is@~1.6.17, type-is@~1.6.18:
   version "1.6.18"
   resolved 
"https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131";
@@ -6299,6 +6649,13 @@ type@^1.0.1:
   resolved 
"https://registry.yarnpkg.com/type/-/type-1.0.3.tgz#16f5d39f27a2d28d86e48f8981859e9d3296c179";
   integrity 
sha512-51IMtNfVcee8+9GJvj0spSuFcZHe9vSib6Xtgsny1Km9ugyz2mbS08I3rsUIRYgJohFRFU1160sgRodYz378Hg==
 
+typedarray-to-buffer@^3.1.5:
+  version "3.1.5"
+  resolved 
"https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080";
+  integrity 
sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==
+  dependencies:
+    is-typedarray "^1.0.0"
+
 typedarray@^0.0.6:
   version "0.0.6"
   resolved 
"https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777";
@@ -6468,29 +6825,26 @@ unset-value@^1.0.0:
     has-value "^0.3.1"
     isobject "^3.0.0"
 
-unzip-response@^2.0.1:
-  version "2.0.1"
-  resolved 
"https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97";
-  integrity sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=
-
 upath@^1.1.1:
   version "1.1.2"
   resolved 
"https://registry.yarnpkg.com/upath/-/upath-1.1.2.tgz#3db658600edaeeccbe6db5e684d67ee8c2acd068";
   integrity 
sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==
 
-update-notifier@^2.5.0:
-  version "2.5.0"
-  resolved 
"https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.5.0.tgz#d0744593e13f161e406acb1d9408b72cad08aff6";
-  integrity 
sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==
+update-notifier@^3.0.1:
+  version "3.0.1"
+  resolved 
"https://registry.yarnpkg.com/update-notifier/-/update-notifier-3.0.1.tgz#78ecb68b915e2fd1be9f767f6e298ce87b736250";
+  integrity 
sha512-grrmrB6Zb8DUiyDIaeRTBCkgISYUgETNe7NglEbVsrLWXeESnlCSP50WfRSj/GmzMPl6Uchj24S/p80nP/ZQrQ==
   dependencies:
-    boxen "^1.2.1"
+    boxen "^3.0.0"
     chalk "^2.0.1"
-    configstore "^3.0.0"
+    configstore "^4.0.0"
+    has-yarn "^2.1.0"
     import-lazy "^2.1.0"
-    is-ci "^1.0.10"
+    is-ci "^2.0.0"
     is-installed-globally "^0.1.0"
-    is-npm "^1.0.0"
-    latest-version "^3.0.0"
+    is-npm "^3.0.0"
+    is-yarn-global "^0.3.0"
+    latest-version "^5.0.0"
     semver-diff "^2.0.0"
     xdg-basedir "^3.0.0"
 
@@ -6511,12 +6865,12 @@ urix@^0.1.0:
   resolved 
"https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72";
   integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=
 
-url-parse-lax@^1.0.0:
-  version "1.0.0"
-  resolved 
"https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73";
-  integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=
+url-parse-lax@^3.0.0:
+  version "3.0.0"
+  resolved 
"https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c";
+  integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=
   dependencies:
-    prepend-http "^1.0.1"
+    prepend-http "^2.0.0"
 
 url@^0.11.0:
   version "0.11.0"
@@ -6705,12 +7059,12 @@ webpack-log@^1.2.0:
     loglevelnext "^1.0.1"
     uuid "^3.1.0"
 
-webpack-merge@^4.1.0:
-  version "4.2.1"
-  resolved 
"https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.1.tgz#5e923cf802ea2ace4fd5af1d3247368a633489b4";
-  integrity 
sha512-4p8WQyS98bUJcCvFMbdGZyZmsKuWjWVnVHnAS3FFg0HDaRVrPbkivx2RYCre8UiemD67RsiFFLfn4JhLAin8Vw==
+webpack-merge@^4.2.2:
+  version "4.2.2"
+  resolved 
"https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d";
+  integrity 
sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==
   dependencies:
-    lodash "^4.17.5"
+    lodash "^4.17.15"
 
 webpack-sources@^1.4.0, webpack-sources@^1.4.1:
   version "1.4.3"
@@ -6720,10 +7074,10 @@ webpack-sources@^1.4.0, webpack-sources@^1.4.1:
     source-list-map "^2.0.0"
     source-map "~0.6.1"
 
-webpack@^4.29.6:
-  version "4.39.2"
-  resolved 
"https://registry.yarnpkg.com/webpack/-/webpack-4.39.2.tgz#c9aa5c1776d7c309d1b3911764f0288c8c2816aa";
-  integrity 
sha512-AKgTfz3xPSsEibH00JfZ9sHXGUwIQ6eZ9tLN8+VLzachk1Cw2LVmy+4R7ZiwTa9cZZ15tzySjeMui/UnSCAZhA==
+webpack@^4.39.3:
+  version "4.39.3"
+  resolved 
"https://registry.yarnpkg.com/webpack/-/webpack-4.39.3.tgz#a02179d1032156b713b6ec2da7e0df9d037def50";
+  integrity 
sha512-BXSI9M211JyCVc3JxHWDpze85CvjC842EvpRsVTc/d15YJGlox7GIDd38kJgWrb3ZluyvIjgenbLDMBQPDcxYQ==
   dependencies:
     "@webassemblyjs/ast" "1.8.5"
     "@webassemblyjs/helper-module-context" "1.8.5"
@@ -6828,6 +7182,16 @@ write-file-atomic@^2.0.0, write-file-atomic@^2.4.2:
     imurmurhash "^0.1.4"
     signal-exit "^3.0.2"
 
+write-file-atomic@^3.0.0:
+  version "3.0.0"
+  resolved 
"https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.0.tgz#1b64dbbf77cb58fd09056963d63e62667ab4fb21";
+  integrity 
sha512-EIgkf60l2oWsffja2Sf2AL384dx328c0B+cIYPTQq5q2rOYuDV00/iPFBOUiDKKwKMOhkymH8AidPaRvzfxY+Q==
+  dependencies:
+    imurmurhash "^0.1.4"
+    is-typedarray "^1.0.0"
+    signal-exit "^3.0.2"
+    typedarray-to-buffer "^3.1.5"
+
 ws@^6.0.0:
   version "6.2.1"
   resolved 
"https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb";

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



reply via email to

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