From cbe325cb0f3e492e28ee148106c6c81e4db7d6bf Mon Sep 17 00:00:00 2001
From: Florian Dold
Date: Fri, 14 Aug 2020 00:13:51 +0530
Subject: web extension WIP
---
.../src/pageEntryPoint.ts | 3 +
.../taler-wallet-webextension/src/pages/popup.tsx | 8 +-
.../src/pages/withdraw.tsx | 102 +-------
packages/taler-wallet-webextension/src/wxApi.ts | 61 ++---
.../taler-wallet-webextension/src/wxBackend.ts | 280 +++------------------
.../static/benchmark.html | 6 +-
packages/taler-wallet-webextension/static/pay.html | 8 +-
.../taler-wallet-webextension/static/popup.html | 10 +-
.../taler-wallet-webextension/static/withdraw.html | 8 +-
9 files changed, 98 insertions(+), 388 deletions(-)
(limited to 'packages')
diff --git a/packages/taler-wallet-webextension/src/pageEntryPoint.ts b/packages/taler-wallet-webextension/src/pageEntryPoint.ts
index 9fd1d36f1..216cb83c3 100644
--- a/packages/taler-wallet-webextension/src/pageEntryPoint.ts
+++ b/packages/taler-wallet-webextension/src/pageEntryPoint.ts
@@ -26,6 +26,7 @@ import { createWithdrawPage } from "./pages/withdraw";
import { createWelcomePage } from "./pages/welcome";
import { createPayPage } from "./pages/pay";
import { createRefundPage } from "./pages/refund";
+import { setupI18n } from "taler-wallet-core";
function main(): void {
try {
@@ -65,6 +66,8 @@ function main(): void {
}
}
+setupI18n("en-US");
+
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", main);
} else {
diff --git a/packages/taler-wallet-webextension/src/pages/popup.tsx b/packages/taler-wallet-webextension/src/pages/popup.tsx
index 61edcfe50..e833f5950 100644
--- a/packages/taler-wallet-webextension/src/pages/popup.tsx
+++ b/packages/taler-wallet-webextension/src/pages/popup.tsx
@@ -397,19 +397,19 @@ function actionForTalerUri(talerUri: string): string | undefined {
const uriType = classifyTalerUri(talerUri);
switch (uriType) {
case TalerUriType.TalerWithdraw:
- return makeExtensionUrlWithParams("withdraw.html", {
+ return makeExtensionUrlWithParams("static/withdraw.html", {
talerWithdrawUri: talerUri,
});
case TalerUriType.TalerPay:
- return makeExtensionUrlWithParams("pay.html", {
+ return makeExtensionUrlWithParams("static/pay.html", {
talerPayUri: talerUri,
});
case TalerUriType.TalerTip:
- return makeExtensionUrlWithParams("tip.html", {
+ return makeExtensionUrlWithParams("static/tip.html", {
talerTipUri: talerUri,
});
case TalerUriType.TalerRefund:
- return makeExtensionUrlWithParams("refund.html", {
+ return makeExtensionUrlWithParams("static/refund.html", {
talerRefundUri: talerUri,
});
case TalerUriType.TalerNotifyReserve:
diff --git a/packages/taler-wallet-webextension/src/pages/withdraw.tsx b/packages/taler-wallet-webextension/src/pages/withdraw.tsx
index 4a92704b3..1637176a9 100644
--- a/packages/taler-wallet-webextension/src/pages/withdraw.tsx
+++ b/packages/taler-wallet-webextension/src/pages/withdraw.tsx
@@ -29,11 +29,13 @@ import React, { useState, useEffect } from "react";
import {
acceptWithdrawal,
onUpdateNotification,
+ getWithdrawalDetailsForUri,
} from "../wxApi";
+import { WithdrawUriInfoResponse } from "taler-wallet-core";
function WithdrawalDialog(props: { talerWithdrawUri: string }): JSX.Element {
const [details, setDetails] = useState<
- any | undefined
+ WithdrawUriInfoResponse | undefined
>();
const [selectedExchange, setSelectedExchange] = useState<
string | undefined
@@ -54,55 +56,12 @@ function WithdrawalDialog(props: { talerWithdrawUri: string }): JSX.Element {
useEffect(() => {
const fetchData = async (): Promise => {
- // FIXME: re-implement with new API
- // console.log("getting from", talerWithdrawUri);
- // let d: WithdrawalDetailsResponse | undefined = undefined;
- // try {
- // d = await getWithdrawDetails(talerWithdrawUri, selectedExchange);
- // } catch (e) {
- // console.error(
- // `error getting withdraw details for uri ${talerWithdrawUri}, exchange ${selectedExchange}`,
- // e,
- // );
- // setErrMsg(e.message);
- // return;
- // }
- // console.log("got withdrawDetails", d);
- // if (!selectedExchange && d.bankWithdrawDetails.suggestedExchange) {
- // console.log("setting selected exchange");
- // setSelectedExchange(d.bankWithdrawDetails.suggestedExchange);
- // }
- // setDetails(d);
+ const res = await getWithdrawalDetailsForUri({talerWithdrawUri: props.talerWithdrawUri});
+ setDetails(res);
};
fetchData();
}, [selectedExchange, errMsg, selecting, talerWithdrawUri, updateCounter]);
- if (errMsg) {
- return (
-
-
- Could not get details for withdraw operation:
-
-
{errMsg}
-
- {
- setSelecting(true);
- setErrMsg(undefined);
- setSelectedExchange(undefined);
- setDetails(undefined);
- }}
- >
- {i18n.str`Chose different exchange provider`}
-
-
-
- );
- }
-
if (!details) {
return Loading... ;
}
@@ -111,51 +70,6 @@ function WithdrawalDialog(props: { talerWithdrawUri: string }): JSX.Element {
return Withdraw operation has been cancelled. ;
}
- if (selecting) {
- const bankSuggestion =
- details && details.bankWithdrawDetails.suggestedExchange;
- return (
-
- {i18n.str`Please select an exchange. You can review the details before after your selection.`}
- {bankSuggestion && (
-
-
Bank Suggestion
- {
- setDetails(undefined);
- setSelectedExchange(bankSuggestion);
- setSelecting(false);
- }}
- >
-
- Select {bankSuggestion}
-
-
-
- )}
-
Custom Selection
-
- setCustomUrl(e.target.value)}
- value={customUrl}
- />
-
-
{
- setDetails(undefined);
- setSelectedExchange(customUrl);
- setSelecting(false);
- }}
- >
- Select custom exchange
-
-
- );
- }
-
const accept = async (): Promise => {
if (!selectedExchange) {
throw Error("can't accept, no exchange selected");
@@ -173,7 +87,7 @@ function WithdrawalDialog(props: { talerWithdrawUri: string }): JSX.Element {
Digital Cash Withdrawal
You are about to withdraw{" "}
- {renderAmount(details.bankWithdrawDetails.amount)} from
+ {renderAmount(details.amount)} from
your bank account into your wallet.
{selectedExchange ? (
@@ -211,9 +125,9 @@ function WithdrawalDialog(props: { talerWithdrawUri: string }): JSX.Element {
- {details.exchangeWithdrawDetails ? (
+ {/* {details.exchangeWithdrawDetails ? (
- ) : null}
+ ) : null} */}
);
diff --git a/packages/taler-wallet-webextension/src/wxApi.ts b/packages/taler-wallet-webextension/src/wxApi.ts
index 1bcee1285..836466ff3 100644
--- a/packages/taler-wallet-webextension/src/wxApi.ts
+++ b/packages/taler-wallet-webextension/src/wxApi.ts
@@ -21,14 +21,26 @@
/**
* Imports.
*/
-import { AmountJson, ConfirmPayResult, BalancesResponse, PurchaseDetails, TipStatus, BenchmarkResult, PreparePayResult, AcceptWithdrawalResponse, WalletDiagnostics } from "taler-wallet-core";
-
+import {
+ AmountJson,
+ ConfirmPayResult,
+ BalancesResponse,
+ PurchaseDetails,
+ TipStatus,
+ BenchmarkResult,
+ PreparePayResult,
+ AcceptWithdrawalResponse,
+ WalletDiagnostics,
+ CoreApiResponse,
+ OperationFailedError,
+ GetWithdrawalDetailsForUriRequest,
+ WithdrawUriInfoResponse,
+} from "taler-wallet-core";
export interface ExtendedPermissionsResponse {
newValue: boolean;
}
-
/**
* Response with information about available version upgrades.
*/
@@ -50,23 +62,9 @@ export interface UpgradeResponse {
oldDbVersion: string;
}
-/**
- * Error thrown when the function from the backend (via RPC) threw an error.
- */
-export class WalletApiError extends Error {
- constructor(message: string, public detail: any) {
- super(message);
- // restore prototype chain
- Object.setPrototypeOf(this, new.target.prototype);
- }
-}
-
-async function callBackend(
- type: string,
- detail: any,
-): Promise {
+async function callBackend(operation: string, payload: any): Promise {
return new Promise((resolve, reject) => {
- chrome.runtime.sendMessage({ type, detail }, (resp) => {
+ chrome.runtime.sendMessage({ operation, payload, id: "(none)" }, (resp) => {
if (chrome.runtime.lastError) {
console.log("Error calling backend");
reject(
@@ -75,19 +73,17 @@ async function callBackend(
),
);
}
- if (typeof resp === "object" && resp && resp.error) {
- console.warn("response error:", resp);
- const e = new WalletApiError(resp.error.message, resp.error);
- reject(e);
- } else {
- resolve(resp);
+ console.log("got response", resp);
+ const r = resp as CoreApiResponse;
+ if (r.type === "error") {
+ reject(new OperationFailedError(r.error));
+ return;
}
+ resolve(r.result);
});
});
}
-
-
/**
* Start refreshing a coin.
*/
@@ -123,7 +119,7 @@ export function resetDb(): Promise {
* Get balances for all currencies/exchanges.
*/
export function getBalance(): Promise {
- return callBackend("balances", {});
+ return callBackend("getBalances", {});
}
/**
@@ -227,6 +223,15 @@ export function getExtendedPermissions(): Promise {
return callBackend("get-extended-permissions", {});
}
+/**
+ * Get diagnostics information
+ */
+export function getWithdrawalDetailsForUri(
+ req: GetWithdrawalDetailsForUriRequest,
+): Promise {
+ return callBackend("getWithdrawalDetailsForUri", req);
+}
+
export function onUpdateNotification(f: () => void): () => void {
const port = chrome.runtime.connect({ name: "notifications" });
const listener = (): void => {
diff --git a/packages/taler-wallet-webextension/src/wxBackend.ts b/packages/taler-wallet-webextension/src/wxBackend.ts
index ce024e096..86008dd99 100644
--- a/packages/taler-wallet-webextension/src/wxBackend.ts
+++ b/packages/taler-wallet-webextension/src/wxBackend.ts
@@ -28,7 +28,21 @@ import * as wxApi from "./wxApi";
import MessageSender = chrome.runtime.MessageSender;
import { extendedPermissions } from "./permissions";
-import { Wallet, OpenedPromise, openPromise, deleteTalerDatabase, WALLET_DB_MINOR_VERSION, WalletDiagnostics, openTalerDatabase, Database, classifyTalerUri, TalerUriType } from "taler-wallet-core";
+import {
+ Wallet,
+ OpenedPromise,
+ openPromise,
+ deleteTalerDatabase,
+ WALLET_DB_MINOR_VERSION,
+ WalletDiagnostics,
+ openTalerDatabase,
+ Database,
+ classifyTalerUri,
+ TalerUriType,
+ makeErrorDetails,
+ TalerErrorCode,
+ handleCoreApiRequest,
+} from "taler-wallet-core";
import { BrowserHttpLib } from "./browserHttpLib";
import { BrowserCryptoWorkerFactory } from "./browserCryptoWorkerFactory";
@@ -51,254 +65,28 @@ const walletInit: OpenedPromise = openPromise();
const notificationPorts: chrome.runtime.Port[] = [];
-async function handleMessage(
- sender: MessageSender,
- type: string,
- detail: any,
-): Promise {
- function needsWallet(): Wallet {
- if (!currentWallet) {
- throw NeedsWallet;
- }
- return currentWallet;
- }
- switch (type) {
- case "balances": {
- return needsWallet().getBalances();
- }
- case "dump-db": {
- const db = needsWallet().db;
- return db.exportDatabase();
- }
- case "import-db": {
- const db = needsWallet().db;
- return db.importDatabase(detail.dump);
- }
- case "ping": {
- return Promise.resolve();
- }
- case "reset-db": {
- deleteTalerDatabase(indexedDB);
- setBadgeText({ text: "" });
- console.log("reset done");
- if (!currentWallet) {
- reinitWallet();
- }
- return Promise.resolve({});
- }
- case "confirm-pay": {
- if (typeof detail.proposalId !== "string") {
- throw Error("proposalId must be string");
- }
- return needsWallet().confirmPay(detail.proposalId, detail.sessionId);
- }
- case "exchange-info": {
- if (!detail.baseUrl) {
- return Promise.resolve({ error: "bad url" });
- }
- return needsWallet().updateExchangeFromUrl(detail.baseUrl);
- }
- case "get-exchanges": {
- return needsWallet().getExchangeRecords();
- }
- case "get-currencies": {
- return needsWallet().getCurrencies();
- }
- case "update-currency": {
- return needsWallet().updateCurrency(detail.currencyRecord);
- }
- case "get-reserves": {
- if (typeof detail.exchangeBaseUrl !== "string") {
- return Promise.reject(Error("exchangeBaseUrl missing"));
- }
- return needsWallet().getReserves(detail.exchangeBaseUrl);
- }
- case "get-coins": {
- if (typeof detail.exchangeBaseUrl !== "string") {
- return Promise.reject(Error("exchangBaseUrl missing"));
- }
- return needsWallet().getCoinsForExchange(detail.exchangeBaseUrl);
- }
- case "get-denoms": {
- if (typeof detail.exchangeBaseUrl !== "string") {
- return Promise.reject(Error("exchangBaseUrl missing"));
- }
- return needsWallet().getDenoms(detail.exchangeBaseUrl);
- }
- case "refresh-coin": {
- if (typeof detail.coinPub !== "string") {
- return Promise.reject(Error("coinPub missing"));
- }
- return needsWallet().refresh(detail.coinPub);
- }
- case "get-sender-wire-infos": {
- return needsWallet().getSenderWireInfos();
- }
- case "return-coins": {
- const d = {
- amount: detail.amount,
- exchange: detail.exchange,
- senderWire: detail.senderWire,
- };
- return needsWallet().returnCoins(d);
- }
- case "check-upgrade": {
- let dbResetRequired = false;
- if (!currentWallet) {
- dbResetRequired = true;
- }
- const resp: wxApi.UpgradeResponse = {
- currentDbVersion: WALLET_DB_MINOR_VERSION.toString(),
- dbResetRequired,
- oldDbVersion: (outdatedDbVersion || "unknown").toString(),
- };
- return resp;
- }
- case "get-purchase-details": {
- const proposalId = detail.proposalId;
- if (!proposalId) {
- throw Error("proposalId missing");
- }
- if (typeof proposalId !== "string") {
- throw Error("proposalId must be a string");
- }
- return needsWallet().getPurchaseDetails(proposalId);
- }
- case "accept-refund":
- return needsWallet().applyRefund(detail.refundUrl);
- case "get-tip-status": {
- return needsWallet().getTipStatus(detail.talerTipUri);
- }
- case "accept-tip": {
- return needsWallet().acceptTip(detail.talerTipUri);
- }
- case "abort-failed-payment": {
- if (!detail.contractTermsHash) {
- throw Error("contracTermsHash not given");
- }
- return needsWallet().abortFailedPayment(detail.contractTermsHash);
- }
- case "benchmark-crypto": {
- if (!detail.repetitions) {
- throw Error("repetitions not given");
- }
- return needsWallet().benchmarkCrypto(detail.repetitions);
- }
- case "accept-withdrawal": {
- return needsWallet().acceptWithdrawal(
- detail.talerWithdrawUri,
- detail.selectedExchange,
- );
- }
- case "get-diagnostics": {
- const manifestData = chrome.runtime.getManifest();
- const errors: string[] = [];
- let firefoxIdbProblem = false;
- let dbOutdated = false;
- try {
- await walletInit.promise;
- } catch (e) {
- errors.push("Error during wallet initialization: " + e);
- if (
- currentDatabase === undefined &&
- outdatedDbVersion === undefined &&
- isFirefox()
- ) {
- firefoxIdbProblem = true;
- }
- }
- if (!currentWallet) {
- errors.push("Could not create wallet backend.");
- }
- if (!currentDatabase) {
- errors.push("Could not open database");
- }
- if (outdatedDbVersion !== undefined) {
- errors.push(`Outdated DB version: ${outdatedDbVersion}`);
- dbOutdated = true;
- }
- const diagnostics: WalletDiagnostics = {
- walletManifestDisplayVersion:
- manifestData.version_name || "(undefined)",
- walletManifestVersion: manifestData.version,
- errors,
- firefoxIdbProblem,
- dbOutdated,
- };
- return diagnostics;
- }
- case "prepare-pay":
- return needsWallet().preparePayForUri(detail.talerPayUri);
- case "set-extended-permissions": {
- const newVal = detail.value;
- console.log("new extended permissions value", newVal);
- if (newVal) {
- setupHeaderListener();
- return { newValue: true };
- } else {
- await new Promise((resolve, reject) => {
- getPermissionsApi().remove(extendedPermissions, (rem) => {
- console.log("permissions removed:", rem);
- resolve();
- });
- });
- return { newVal: false };
- }
- }
- case "get-extended-permissions": {
- const res = await new Promise((resolve, reject) => {
- getPermissionsApi().contains(extendedPermissions, (result: boolean) => {
- resolve(result);
- });
- });
- return { newValue: res };
- }
- default:
- console.error(`Request type ${type} unknown`);
- console.error(`Request detail was ${detail}`);
- return {
- error: {
- message: `request type ${type} unknown`,
- requestType: type,
- },
- };
- }
-}
-
async function dispatch(
req: any,
sender: any,
sendResponse: any,
): Promise {
+ const w = currentWallet;
+ if (!w) {
+ sendResponse(
+ makeErrorDetails(
+ TalerErrorCode.WALLET_CORE_NOT_AVAILABLE,
+ "wallet core not available",
+ {},
+ ),
+ );
+ return;
+ }
+
+ const r = await handleCoreApiRequest(w, req.operation, req.id, req.payload);
try {
- const p = handleMessage(sender, req.type, req.detail);
- const r = await p;
- try {
- sendResponse(r);
- } catch (e) {
- // might fail if tab disconnected
- }
+ sendResponse(r);
} catch (e) {
- console.log(`exception during wallet handler for '${req.type}'`);
- console.log("request", req);
- console.error(e);
- let stack;
- try {
- stack = e.stack.toString();
- } catch (e) {
- // might fail
- }
- try {
- sendResponse({
- error: {
- message: e.message,
- stack,
- },
- });
- } catch (e) {
- console.log(e);
- // might fail if tab disconnected
- }
+ // might fail if tab disconnected
}
}
@@ -436,7 +224,7 @@ function headerListener(
switch (uriType) {
case TalerUriType.TalerWithdraw:
return makeSyncWalletRedirect(
- "withdraw.html",
+ "/static/withdraw.html",
details.tabId,
details.url,
{
@@ -445,7 +233,7 @@ function headerListener(
);
case TalerUriType.TalerPay:
return makeSyncWalletRedirect(
- "pay.html",
+ "/static/pay.html",
details.tabId,
details.url,
{
@@ -454,7 +242,7 @@ function headerListener(
);
case TalerUriType.TalerTip:
return makeSyncWalletRedirect(
- "tip.html",
+ "/static/tip.html",
details.tabId,
details.url,
{
@@ -463,7 +251,7 @@ function headerListener(
);
case TalerUriType.TalerRefund:
return makeSyncWalletRedirect(
- "refund.html",
+ "/static/refund.html",
details.tabId,
details.url,
{
diff --git a/packages/taler-wallet-webextension/static/benchmark.html b/packages/taler-wallet-webextension/static/benchmark.html
index a29fe0725..d0ca32aeb 100644
--- a/packages/taler-wallet-webextension/static/benchmark.html
+++ b/packages/taler-wallet-webextension/static/benchmark.html
@@ -3,9 +3,9 @@
Taler Wallet: Benchmarks
-
-
-
+
+
+
diff --git a/packages/taler-wallet-webextension/static/pay.html b/packages/taler-wallet-webextension/static/pay.html
index 452c56df0..129765815 100644
--- a/packages/taler-wallet-webextension/static/pay.html
+++ b/packages/taler-wallet-webextension/static/pay.html
@@ -4,10 +4,10 @@
Taler Wallet: Confirm Contract
-
-
-
-
+
+
+
+