From 164d5f20c3dbb60c8898fb4aa7d729ec8d9b7537 Mon Sep 17 00:00:00 2001
From: Florian Dold <florian.dold@gmail.com>
Date: Thu, 11 Feb 2016 11:29:57 +0100
Subject: refactoring; make wallet follow new bank protocol

---
 extension/pages/confirm-create-reserve.tsx | 177 ++++++++++++++++++++++++-----
 1 file changed, 148 insertions(+), 29 deletions(-)

(limited to 'extension/pages/confirm-create-reserve.tsx')

diff --git a/extension/pages/confirm-create-reserve.tsx b/extension/pages/confirm-create-reserve.tsx
index 6a130eeff..8cb46559b 100644
--- a/extension/pages/confirm-create-reserve.tsx
+++ b/extension/pages/confirm-create-reserve.tsx
@@ -14,40 +14,107 @@
  TALER; see the file COPYING.  If not, If not, see <http://www.gnu.org/licenses/>
  */
 
-import {amountToPretty} from "../lib/web-common";
-import {AmountJson, CreateReserveResponse} from "../lib/wallet/wallet";
+import {amountToPretty, canonicalizeBaseUrl} from "../lib/wallet/helpers";
+import {AmountJson, CreateReserveResponse} from "../lib/wallet/types";
+
 "use strict";
 
+declare var m: any;
 
-export function main() {
-  function updateAmount() {
-    let showAmount = document.getElementById("show-amount");
-    console.log("Query is " + JSON.stringify(query));
-    let amount = AmountJson.checked(JSON.parse(query.amount));
-    showAmount.textContent = amountToPretty(amount);
+
+/**
+ * Execute something after a delay, with the possibility
+ * to reset the delay.
+ */
+class DelayTimer {
+  ms: number;
+  f;
+  timerId: number = null;
+
+  constructor(ms: number, f) {
+    this.f = f;
+    this.ms = ms;
+  }
+
+  bump() {
+    if (this.timerId !== null) {
+      window.clearTimeout(this.timerId);
+    }
+    const handler = () => {
+      this.f();
+    };
+    this.timerId = window.setTimeout(handler, this.ms);
   }
+}
 
-  let url = URI(document.location.href);
-  let query: any = URI.parseQuery(url.query());
 
-  updateAmount();
+class Controller {
+  url = null;
+  errorString = null;
+  isValidMint = false;
+  private timer: DelayTimer;
+  private request: XMLHttpRequest;
 
-  document.getElementById("confirm").addEventListener("click", (e) => {
-    const d = {
-      mint: (document.getElementById('mint-url') as HTMLInputElement).value,
-      amount: JSON.parse(query.amount)
+  constructor() {
+    this.update();
+    this.timer = new DelayTimer(800, () => this.update());
+  }
+
+  update() {
+    const doUpdate = () => {
+      if (!this.url) {
+        this.errorString = i18n`Please enter a URL`;
+        return;
+      }
+      this.errorString = null;
+      let parsedUrl = URI(this.url);
+      if (parsedUrl.is("relative")) {
+        this.errorString = i18n`The URL you've entered is not valid (must be absolute)`;
+        return;
+      }
+
+      const keysUrl = URI("/keys").absoluteTo(canonicalizeBaseUrl(this.url));
+
+      console.log(`requesting keys from '${keysUrl}'`);
+
+      this.request = new XMLHttpRequest();
+      this.request.onreadystatechange = () => {
+        if (this.request.readyState == XMLHttpRequest.DONE) {
+          switch (this.request.status) {
+            case 200:
+              this.isValidMint = true;
+              break;
+            case 0:
+              this.errorString = `unknown request error`;
+              break;
+            default:
+              this.errorString = `request failed with status ${this.request.status}`;
+              break;
+          }
+          m.redraw();
+        }
+      };
+      this.request.open("get", keysUrl.href());
+      this.request.send();
     };
 
-    if (!d.mint) {
-      // FIXME: indicate error instead!
-      throw Error("mint missing");
-    }
+    doUpdate();
+    m.redraw();
+    console.log("got update");
+  }
 
-    if (!d.amount) {
-      // FIXME: indicate error instead!
-      throw Error("amount missing");
+  reset() {
+    this.isValidMint = false;
+    this.errorString = null;
+    if (this.request) {
+      this.request.abort();
+      this.request = null;
     }
+    m.redraw();
+  }
 
+  confirmReserve(mint: string, amount: AmountJson, callback_url: string) {
+    const d = {mint, amount};
     const cb = (rawResp) => {
       if (!rawResp) {
         throw Error("empty response");
@@ -57,20 +124,72 @@ export function main() {
         let q = {
           mint: resp.mint,
           reserve_pub: resp.reservePub,
-          amount: query.amount,
+          amount_value: amount.value,
+          amount_fraction: amount.fraction,
+          amount_currency: amount.currency,
         };
-        let url = URI(query.callback_url).addQuery(q);
+        let url = 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 {
-        document.body.innerHTML =
-          `Oops, something went wrong.  It looks like the bank could not
-            transfer funds to the mint.  Please go back to your bank's website
-            to check what happened.`;
+        this.reset();
+        this.errorString = (
+        `Oops, something went wrong.` +
+        `The wallet responded with error status (${rawResp.error}).`);
       }
     };
     chrome.runtime.sendMessage({type: 'create-reserve', detail: d}, cb);
-  });
+  }
+
+  onUrlChanged(url: string) {
+    this.reset();
+    this.url = url;
+    this.timer.bump();
+  }
+}
+
+
+export function main() {
+  const url = URI(document.location.href);
+  const query: any = URI.parseQuery(url.query());
+  const amount = AmountJson.checked(JSON.parse(query.amount));
+  const callback_url = query.callback_url;
+
+  var MintSelection = {
+    controller: () => new Controller(),
+    view(ctrl: Controller) {
+      let controls = [];
+      let mx = (...args) => controls.push(m(...args));
+
+      mx("p",
+         i18n`The bank wants to create a reserve over ${amountToPretty(
+           amount)}.`);
+      mx("input.url",
+         {
+           type: "text",
+           spellcheck: false,
+           oninput: m.withAttr("value", ctrl.onUrlChanged.bind(ctrl)),
+         });
+
+      if (ctrl.isValidMint) {
+        mx("button", {
+             onclick: () => ctrl.confirmReserve(ctrl.url,
+                                                amount,
+                                                callback_url)
+           },
+           "Confirm mint selection");
+      }
+
+      if (ctrl.errorString) {
+        mx("p", ctrl.errorString);
+      }
+
+      return m("div", controls);
+    }
+  };
+
+  m.mount(document.getElementById("mint-selection"), MintSelection);
 }
\ No newline at end of file
-- 
cgit v1.2.3

