aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2020-07-28 14:22:35 +0530
committerFlorian Dold <florian.dold@gmail.com>2020-07-28 14:22:35 +0530
commit4365cd6401713b2e207d8c032c0558487e860154 (patch)
treef66b4bc5aa9dd7e92b72546e0b2fe79c18ed6573
parent472307a607b046e32f50b05a8be44c47c4b153d4 (diff)
towards the new withdrawal API (temporarily breaks WebExtension wallet)
-rw-r--r--src/headless/taler-wallet-cli.ts5
-rw-r--r--src/operations/withdraw.ts59
-rw-r--r--src/types/talerTypes.ts9
-rw-r--r--src/types/walletTypes.ts5
-rw-r--r--src/wallet.ts16
-rw-r--r--src/walletCoreApiHandler.ts17
-rw-r--r--src/webex/messages.ts159
-rw-r--r--src/webex/pages/withdraw.tsx42
-rw-r--r--src/webex/wxApi.ts28
-rw-r--r--src/webex/wxBackend.ts32
10 files changed, 101 insertions, 271 deletions
diff --git a/src/headless/taler-wallet-cli.ts b/src/headless/taler-wallet-cli.ts
index 63698bf69..4bae298a0 100644
--- a/src/headless/taler-wallet-cli.ts
+++ b/src/headless/taler-wallet-cli.ts
@@ -306,9 +306,8 @@ walletCli
break;
case TalerUriType.TalerWithdraw:
{
- const withdrawInfo = await wallet.getWithdrawDetailsForUri(uri);
- const selectedExchange =
- withdrawInfo.bankWithdrawDetails.suggestedExchange;
+ const withdrawInfo = await wallet.getWithdrawalDetailsForUri(uri);
+ const selectedExchange = withdrawInfo.defaultExchangeBaseUrl;
if (!selectedExchange) {
console.error("no suggested exchange!");
process.exit(1);
diff --git a/src/operations/withdraw.ts b/src/operations/withdraw.ts
index 6f591602d..486375300 100644
--- a/src/operations/withdraw.ts
+++ b/src/operations/withdraw.ts
@@ -32,12 +32,13 @@ import {
import {
BankWithdrawDetails,
ExchangeWithdrawDetails,
- WithdrawalDetailsResponse,
OperationErrorDetails,
+ ExchangeListItem,
} from "../types/walletTypes";
import {
codecForWithdrawOperationStatusResponse,
codecForWithdrawResponse,
+ WithdrawUriInfoResponse,
} from "../types/talerTypes";
import { InternalWalletState } from "./state";
import { parseWithdrawUri } from "../util/taleruri";
@@ -154,7 +155,7 @@ export async function getBankWithdrawalInfo(
return {
amount: Amounts.parseOrThrow(status.amount),
confirmTransferUrl: status.confirm_transfer_url,
- extractedStatusUrl: uriResult.bankIntegrationApiBaseUrl,
+ extractedStatusUrl: reqUrl.href,
selectionDone: status.selection_done,
senderWire: status.sender_wire,
suggestedExchange: status.suggested_exchange,
@@ -706,22 +707,50 @@ export async function getExchangeWithdrawalInfo(
return ret;
}
-export async function getWithdrawDetailsForUri(
+export async function getWithdrawalDetailsForUri(
ws: InternalWalletState,
talerWithdrawUri: string,
- maybeSelectedExchange?: string,
-): Promise<WithdrawalDetailsResponse> {
+): Promise<WithdrawUriInfoResponse> {
const info = await getBankWithdrawalInfo(ws, talerWithdrawUri);
- let rci: ExchangeWithdrawDetails | undefined = undefined;
- if (maybeSelectedExchange) {
- rci = await getExchangeWithdrawalInfo(
- ws,
- maybeSelectedExchange,
- info.amount,
- );
+ if (info.suggestedExchange) {
+ // FIXME: right now the exchange gets permanently added,
+ // we might want to only temporarily add it.
+ try {
+ await updateExchangeFromUrl(ws, info.suggestedExchange);
+ } catch (e) {
+ // We still continued if it failed, as other exchanges might be available.
+ // We don't want to fail if the bank-suggested exchange is broken/offline.
+ logger.trace(`querying bank-suggested exchange (${info.suggestedExchange}) failed`)
+ }
}
+
+ const exchangesRes: (ExchangeListItem | undefined)[] = await ws.db
+ .iter(Stores.exchanges)
+ .map((x) => {
+ const details = x.details;
+ if (!details) {
+ return undefined;
+ }
+ if (!x.addComplete) {
+ return undefined;
+ }
+ if (!x.wireInfo) {
+ return undefined;
+ }
+ if (details.currency !== info.amount.currency) {
+ return undefined;
+ }
+ return {
+ exchangeBaseUrl: x.baseUrl,
+ currency: details.currency,
+ paytoUris: x.wireInfo.accounts.map((x) => x.payto_uri),
+ };
+ });
+ const exchanges = exchangesRes.filter((x) => !!x) as ExchangeListItem[];
+
return {
- bankWithdrawDetails: info,
- exchangeWithdrawDetails: rci,
- };
+ amount: Amounts.stringify(info.amount),
+ defaultExchangeBaseUrl: info.suggestedExchange,
+ possibleExchanges: exchanges,
+ }
}
diff --git a/src/types/talerTypes.ts b/src/types/talerTypes.ts
index 1dfcd80a2..823f437b5 100644
--- a/src/types/talerTypes.ts
+++ b/src/types/talerTypes.ts
@@ -39,8 +39,6 @@ import {
Codec,
makeCodecForConstNumber,
makeCodecForUnion,
- makeCodecForConstTrue,
- makeCodecForConstFalse,
makeCodecForConstString,
} from "../util/codec";
import {
@@ -49,6 +47,7 @@ import {
Duration,
codecForDuration,
} from "../util/time";
+import { ExchangeListItem } from "./walletTypes";
/**
* Denomination as found in the /keys response from the exchange.
@@ -935,6 +934,12 @@ export interface MerchantOrderStatusUnpaid {
already_paid_order_id?: string;
}
+export interface WithdrawUriInfoResponse {
+ amount: AmountString;
+ defaultExchangeBaseUrl?: string;
+ possibleExchanges: ExchangeListItem[];
+}
+
export type AmountString = string;
export type Base32String = string;
export type EddsaSignatureString = string;
diff --git a/src/types/walletTypes.ts b/src/types/walletTypes.ts
index 95ec47b67..2ca95bf48 100644
--- a/src/types/walletTypes.ts
+++ b/src/types/walletTypes.ts
@@ -146,11 +146,6 @@ export interface ExchangeWithdrawDetails {
walletVersion: string;
}
-export interface WithdrawalDetailsResponse {
- bankWithdrawDetails: BankWithdrawDetails;
- exchangeWithdrawDetails: ExchangeWithdrawDetails | undefined;
-}
-
/**
* Mapping from currency/exchange to detailed balance
* information.
diff --git a/src/wallet.ts b/src/wallet.ts
index c47acbace..2abd6c0c8 100644
--- a/src/wallet.ts
+++ b/src/wallet.ts
@@ -29,8 +29,8 @@ import { Database } from "./util/query";
import { Amounts, AmountJson } from "./util/amounts";
import {
- getWithdrawDetailsForUri,
getExchangeWithdrawalInfo,
+ getWithdrawalDetailsForUri,
} from "./operations/withdraw";
import {
@@ -53,7 +53,7 @@ import {
CoinSourceType,
RefundState,
} from "./types/dbTypes";
-import { CoinDumpJson } from "./types/talerTypes";
+import { CoinDumpJson, WithdrawUriInfoResponse } from "./types/talerTypes";
import {
BenchmarkResult,
ConfirmPayResult,
@@ -62,7 +62,6 @@ import {
TipStatus,
WalletBalance,
PreparePayResult,
- WithdrawalDetailsResponse,
AcceptWithdrawalResponse,
PurchaseDetails,
RefreshReason,
@@ -479,15 +478,8 @@ export class Wallet {
return getExchangeTrust(this.ws, exchangeInfo);
}
- async getWithdrawDetailsForUri(
- talerWithdrawUri: string,
- maybeSelectedExchange?: string,
- ): Promise<WithdrawalDetailsResponse> {
- return getWithdrawDetailsForUri(
- this.ws,
- talerWithdrawUri,
- maybeSelectedExchange,
- );
+ async getWithdrawalDetailsForUri(talerWithdrawUri: string): Promise<WithdrawUriInfoResponse> {
+ return getWithdrawalDetailsForUri(this.ws, talerWithdrawUri);
}
/**
diff --git a/src/walletCoreApiHandler.ts b/src/walletCoreApiHandler.ts
index 6c32fd888..64039c0c1 100644
--- a/src/walletCoreApiHandler.ts
+++ b/src/walletCoreApiHandler.ts
@@ -108,16 +108,16 @@ const codecForApplyRefundRequest = (): Codec<ApplyRefundRequest> =>
.property("talerRefundUri", codecForString)
.build("ApplyRefundRequest");
-interface GetWithdrawUriInfoRequest {
+interface GetWithdrawalDetailsForUriRequest {
talerWithdrawUri: string;
}
-const codecForGetWithdrawUriInfoRequest = (): Codec<
- GetWithdrawUriInfoRequest
+const codecForGetWithdrawalDetailsForUri = (): Codec<
+ GetWithdrawalDetailsForUriRequest
> =>
- makeCodecForObject<GetWithdrawUriInfoRequest>()
+ makeCodecForObject<GetWithdrawalDetailsForUriRequest>()
.property("talerWithdrawUri", codecForString)
- .build("GetWithdrawUriInfoRequest");
+ .build("GetWithdrawalDetailsForUriRequest");
interface AbortProposalRequest {
proposalId: string;
@@ -172,10 +172,9 @@ async function dispatchRequestInternal(
case "listExchanges": {
return await wallet.getExchanges();
}
- case "getWithdrawUriInfo": {
- const req = codecForGetWithdrawUriInfoRequest().decode(payload);
- // FIXME: implement "natively"
- throw Error("not implemented");
+ case "getWithdrawalDetailsForUri": {
+ const req = codecForGetWithdrawalDetailsForUri().decode(payload);
+ return await wallet.getWithdrawalDetailsForUri(req.talerWithdrawUri);
}
case "acceptManualWithdrawal": {
const req = codecForAcceptManualWithdrawalRequet().decode(payload);
diff --git a/src/webex/messages.ts b/src/webex/messages.ts
deleted file mode 100644
index 5f63697c1..000000000
--- a/src/webex/messages.ts
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- This file is part of TALER
- (C) 2017 Inria and 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/>
- */
-
-/**
- * Type definitions for messages between content scripts/pages and backend.
- */
-
-// Messages are already documented in wxApi.
-/* tslint:disable:completed-docs */
-
-import * as dbTypes from "../types/dbTypes";
-import * as walletTypes from "../types/walletTypes";
-
-import { UpgradeResponse } from "./wxApi";
-
-/**
- * Message type information.
- */
-export interface MessageMap {
- balances: {
- request: {};
- response: walletTypes.WalletBalance;
- };
- "dump-db": {
- request: {};
- response: any;
- };
- "import-db": {
- request: {
- dump: object;
- };
- response: void;
- };
- ping: {
- request: {};
- response: void;
- };
- "reset-db": {
- request: {};
- response: void;
- };
- "confirm-pay": {
- request: { proposalId: string; sessionId?: string };
- response: walletTypes.ConfirmPayResult;
- };
- "exchange-info": {
- request: { baseUrl: string };
- response: dbTypes.ExchangeRecord;
- };
- "get-coins": {
- request: { exchangeBaseUrl: string };
- response: any;
- };
- "refresh-coin": {
- request: { coinPub: string };
- response: any;
- };
- "get-currencies": {
- request: {};
- response: dbTypes.CurrencyRecord[];
- };
- "update-currency": {
- request: { currencyRecord: dbTypes.CurrencyRecord };
- response: void;
- };
- "get-exchanges": {
- request: {};
- response: dbTypes.ExchangeRecord[];
- };
- "get-reserves": {
- request: { exchangeBaseUrl: string };
- response: dbTypes.ReserveRecord[];
- };
- "get-denoms": {
- request: { exchangeBaseUrl: string };
- response: dbTypes.DenominationRecord[];
- };
- "check-upgrade": {
- request: {};
- response: UpgradeResponse;
- };
- "get-sender-wire-infos": {
- request: {};
- response: walletTypes.SenderWireInfos;
- };
- "return-coins": {
- request: {};
- response: void;
- };
- "get-purchase-details": {
- request: { proposalId: string };
- response: walletTypes.PurchaseDetails;
- };
- "accept-tip": {
- request: { talerTipUri: string };
- response: void;
- };
- "get-tip-status": {
- request: { talerTipUri: string };
- response: walletTypes.TipStatus;
- };
- "accept-refund": {
- request: { refundUrl: string };
- response: { contractTermsHash: string; proposalId: string };
- };
- "abort-failed-payment": {
- request: { contractTermsHash: string };
- response: void;
- };
- "benchmark-crypto": {
- request: { repetitions: number };
- response: walletTypes.BenchmarkResult;
- };
- "get-withdraw-details": {
- request: {
- talerWithdrawUri: string;
- maybeSelectedExchange: string | undefined;
- };
- response: walletTypes.WithdrawalDetailsResponse;
- };
- "accept-withdrawal": {
- request: { talerWithdrawUri: string; selectedExchange: string };
- response: walletTypes.AcceptWithdrawalResponse;
- };
- "prepare-pay": {
- request: { talerPayUri: string };
- response: walletTypes.PreparePayResult;
- };
- "get-diagnostics": {
- request: {};
- response: walletTypes.WalletDiagnostics;
- };
- "set-extended-permissions": {
- request: { value: boolean };
- response: walletTypes.ExtendedPermissionsResponse;
- };
- "get-extended-permissions": {
- request: {};
- response: walletTypes.ExtendedPermissionsResponse;
- };
-}
-
-/**
- * String literal types for messages.
- */
-export type MessageType = keyof MessageMap;
diff --git a/src/webex/pages/withdraw.tsx b/src/webex/pages/withdraw.tsx
index 0216cdb4f..4a92704b3 100644
--- a/src/webex/pages/withdraw.tsx
+++ b/src/webex/pages/withdraw.tsx
@@ -23,20 +23,17 @@
import * as i18n from "../i18n";
-import { WithdrawalDetailsResponse } from "../../types/walletTypes";
-
import { WithdrawDetailView, renderAmount } from "../renderHtml";
import React, { useState, useEffect } from "react";
import {
- getWithdrawDetails,
acceptWithdrawal,
onUpdateNotification,
} from "../wxApi";
function WithdrawalDialog(props: { talerWithdrawUri: string }): JSX.Element {
const [details, setDetails] = useState<
- WithdrawalDetailsResponse | undefined
+ any | undefined
>();
const [selectedExchange, setSelectedExchange] = useState<
string | undefined
@@ -57,24 +54,25 @@ function WithdrawalDialog(props: { talerWithdrawUri: string }): JSX.Element {
useEffect(() => {
const fetchData = async (): Promise<void> => {
- 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);
+ // 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);
};
fetchData();
}, [selectedExchange, errMsg, selecting, talerWithdrawUri, updateCounter]);
diff --git a/src/webex/wxApi.ts b/src/webex/wxApi.ts
index de37b3639..99a581007 100644
--- a/src/webex/wxApi.ts
+++ b/src/webex/wxApi.ts
@@ -37,14 +37,11 @@ import {
WalletBalance,
PurchaseDetails,
WalletDiagnostics,
- WithdrawalDetailsResponse,
PreparePayResult,
AcceptWithdrawalResponse,
ExtendedPermissionsResponse,
} from "../types/walletTypes";
-import { MessageMap, MessageType } from "./messages";
-
/**
* Response with information about available version upgrades.
*/
@@ -77,11 +74,11 @@ export class WalletApiError extends Error {
}
}
-async function callBackend<T extends MessageType>(
- type: T,
- detail: MessageMap[T]["request"],
-): Promise<MessageMap[T]["response"]> {
- return new Promise<MessageMap[T]["response"]>((resolve, reject) => {
+async function callBackend(
+ type: string,
+ detail: any,
+): Promise<any> {
+ return new Promise<any>((resolve, reject) => {
chrome.runtime.sendMessage({ type, detail }, (resp) => {
if (chrome.runtime.lastError) {
console.log("Error calling backend");
@@ -206,7 +203,7 @@ export function getSenderWireInfos(): Promise<SenderWireInfos> {
export function returnCoins(args: {
amount: AmountJson;
exchange: string;
- senderWire: object;
+ senderWire: string;
}): Promise<void> {
return callBackend("return-coins", args);
}
@@ -259,19 +256,6 @@ export function benchmarkCrypto(repetitions: number): Promise<BenchmarkResult> {
}
/**
- * Get details about a withdraw operation.
- */
-export function getWithdrawDetails(
- talerWithdrawUri: string,
- maybeSelectedExchange: string | undefined,
-): Promise<WithdrawalDetailsResponse> {
- return callBackend("get-withdraw-details", {
- talerWithdrawUri,
- maybeSelectedExchange,
- });
-}
-
-/**
* Get details about a pay operation.
*/
export function preparePay(talerPayUri: string): Promise<PreparePayResult> {
diff --git a/src/webex/wxBackend.ts b/src/webex/wxBackend.ts
index 793f4b5d3..39fcf899e 100644
--- a/src/webex/wxBackend.ts
+++ b/src/webex/wxBackend.ts
@@ -35,7 +35,6 @@ import { OpenedPromise, openPromise } from "../util/promiseUtils";
import { classifyTalerUri, TalerUriType } from "../util/taleruri";
import { Wallet } from "../wallet";
import { isFirefox, getPermissionsApi } from "./compat";
-import { MessageType } from "./messages";
import * as wxApi from "./wxApi";
import MessageSender = chrome.runtime.MessageSender;
import { Database } from "../util/query";
@@ -62,19 +61,9 @@ const notificationPorts: chrome.runtime.Port[] = [];
async function handleMessage(
sender: MessageSender,
- type: MessageType,
+ type: string,
detail: any,
): Promise<any> {
- function assertNotFound(t: never): never {
- console.error(`Request type ${t as string} unknown`);
- console.error(`Request detail was ${detail}`);
- return {
- error: {
- message: `request type ${t as string} unknown`,
- requestType: type,
- },
- } as never;
- }
function needsWallet(): Wallet {
if (!currentWallet) {
throw NeedsWallet;
@@ -204,12 +193,6 @@ async function handleMessage(
}
return needsWallet().benchmarkCrypto(detail.repetitions);
}
- case "get-withdraw-details": {
- return needsWallet().getWithdrawDetailsForUri(
- detail.talerWithdrawUri,
- detail.maybeSelectedExchange,
- );
- }
case "accept-withdrawal": {
return needsWallet().acceptWithdrawal(
detail.talerWithdrawUri,
@@ -280,9 +263,14 @@ async function handleMessage(
return { newValue: res };
}
default:
- // Exhaustiveness check.
- // See https://www.typescriptlang.org/docs/handbook/advanced-types.html
- return assertNotFound(type);
+ console.error(`Request type ${type} unknown`);
+ console.error(`Request detail was ${detail}`);
+ return {
+ error: {
+ message: `request type ${type} unknown`,
+ requestType: type,
+ },
+ };
}
}
@@ -354,7 +342,7 @@ function makeSyncWalletRedirect(
tabId: number,
oldUrl: string,
params?: { [name: string]: string | undefined },
-): object {
+): Record<string, unknown> {
const innerUrl = new URL(chrome.extension.getURL("/" + url));
if (params) {
for (const key in params) {