From 63ebe1b2e296aabb79cb1756d5dfc82c1ba4fe02 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 9 Jul 2020 18:56:18 +0530 Subject: android APIs for withdrawal and exchange listing --- src/android/index.ts | 13 +++++++++++++ src/db.ts | 6 +++--- src/headless/taler-wallet-cli.ts | 33 ++++++++++++++++++++++++++++++++- src/operations/exchanges.ts | 3 +++ src/types/dbTypes.ts | 13 +++++++++++++ src/types/walletTypes.ts | 10 ++++++++++ src/wallet.ts | 34 +++++++++++++++++++++++++++++++++- src/webex/wxBackend.ts | 6 +++--- 8 files changed, 110 insertions(+), 8 deletions(-) diff --git a/src/android/index.ts b/src/android/index.ts index 4a62a0239..e7a248476 100644 --- a/src/android/index.ts +++ b/src/android/index.ts @@ -184,6 +184,19 @@ class AndroidWalletMessageHandler { const wallet = await this.wp.promise; return await wallet.getPendingOperations(); } + case "listExchanges": { + const wallet = await this.wp.promise; + return await wallet.getExchanges(); + } + case "addExchange": { + const wallet = await this.wp.promise; + await wallet.updateExchangeFromUrl(args.exchangeBaseUrl); + return {}; + } + case "getWithdrawalDetailsForAmount": { + const wallet = await this.wp.promise; + return await wallet.getWithdrawDetailsForAmount(args.exchangeBaseUrl, args.amount); + } case "withdrawTestkudos": { const wallet = await this.wp.promise; try { diff --git a/src/db.ts b/src/db.ts index 197372024..072b7844e 100644 --- a/src/db.ts +++ b/src/db.ts @@ -7,7 +7,7 @@ import { openDatabase, Database, Store, Index } from "./util/query"; * with each major change. When incrementing the major version, * the wallet should import data from the previous version. */ -const TALER_DB_NAME = "taler-walletdb-v4"; +const TALER_DB_NAME = "taler-walletdb-v5"; /** * Current database minor version, should be incremented @@ -16,7 +16,7 @@ const TALER_DB_NAME = "taler-walletdb-v4"; * backwards-compatible way or object stores and indices * are added. */ -export const WALLET_DB_VERSION = 1; +export const WALLET_DB_MINOR_VERSION = 1; /** * Return a promise that resolves @@ -54,7 +54,7 @@ export function openTalerDatabase( return openDatabase( idbFactory, TALER_DB_NAME, - WALLET_DB_VERSION, + WALLET_DB_MINOR_VERSION, onVersionChange, onUpgradeNeeded, ); diff --git a/src/headless/taler-wallet-cli.ts b/src/headless/taler-wallet-cli.ts index 99d7b5a0a..23ae4da44 100644 --- a/src/headless/taler-wallet-cli.ts +++ b/src/headless/taler-wallet-cli.ts @@ -337,7 +337,7 @@ exchangesCli console.log("Listing exchanges ..."); await withWallet(args, async (wallet) => { const exchanges = await wallet.getExchanges(); - console.log("exchanges", exchanges); + console.log(JSON.stringify(exchanges, undefined, 2)); }); }); @@ -358,11 +358,42 @@ exchangesCli }); }); +exchangesCli + .subcommand("exchangesAddCmd", "add", { + help: "Add an exchange by base URL.", + }) + .requiredArgument("url", clk.STRING, { + help: "Base URL of the exchange.", + }) + .action(async (args) => { + await withWallet(args, async (wallet) => { + await wallet.updateExchangeFromUrl( + args.exchangesAddCmd.url, + ); + }); + }); + const advancedCli = walletCli.subcommand("advancedArgs", "advanced", { help: "Subcommands for advanced operations (only use if you know what you're doing!).", }); +advancedCli + .subcommand("manualWithdrawalDetails", "manual-withdrawal-details", { + help: "Query withdrawal fees.", + }) + .requiredArgument("exchange", clk.STRING) + .requiredArgument("amount", clk.STRING) + .action(async (args) => { + await withWallet(args, async (wallet) => { + const details = await wallet.getWithdrawDetailsForAmount( + args.manualWithdrawalDetails.exchange, + Amounts.parseOrThrow(args.manualWithdrawalDetails.amount), + ); + console.log(JSON.stringify(details, undefined, 2)); + }); + }); + advancedCli .subcommand("decode", "decode", { help: "Decode base32-crockford.", diff --git a/src/operations/exchanges.ts b/src/operations/exchanges.ts index a9e5158e9..6f5ff1d30 100644 --- a/src/operations/exchanges.ts +++ b/src/operations/exchanges.ts @@ -301,6 +301,7 @@ async function updateExchangeFinalize( if (r.updateStatus != ExchangeUpdateStatus.FinalizeUpdate) { return; } + r.addComplete = true; r.updateStatus = ExchangeUpdateStatus.Finished; await tx.put(Stores.exchanges, r); const updateEvent: ExchangeUpdatedEventRecord = { @@ -485,6 +486,8 @@ async function updateExchangeFromUrlImpl( if (!r) { const newExchangeRecord: ExchangeRecord = { builtIn: false, + addComplete: false, + permanent: true, baseUrl: baseUrl, details: undefined, wireInfo: undefined, diff --git a/src/types/dbTypes.ts b/src/types/dbTypes.ts index 82649d9f6..6693e22a2 100644 --- a/src/types/dbTypes.ts +++ b/src/types/dbTypes.ts @@ -555,6 +555,16 @@ export interface ExchangeRecord { */ baseUrl: string; + /** + * Did we finish adding the exchange? + */ + addComplete: boolean; + + /** + * Is this a permanent or temporary exchange record? + */ + permanent: boolean; + /** * Was the exchange added as a built-in exchange? */ @@ -601,6 +611,9 @@ export interface ExchangeRecord { */ updateStarted: Timestamp | undefined; + /** + * Status of updating the info about the exchange. + */ updateStatus: ExchangeUpdateStatus; updateReason?: ExchangeUpdateReason; diff --git a/src/types/walletTypes.ts b/src/types/walletTypes.ts index e58352e01..8bc4f97af 100644 --- a/src/types/walletTypes.ts +++ b/src/types/walletTypes.ts @@ -479,3 +479,13 @@ export interface DepositInfo { export interface ExtendedPermissionsResponse { newValue: boolean; } + +export interface ExchangesListRespose { + exchanges: ExchangeListItem[]; +} + +export interface ExchangeListItem { + exchangeBaseUrl: string; + currency: string; + paytoUris: string[]; +} diff --git a/src/wallet.ts b/src/wallet.ts index 31f9af8c2..780f8eafd 100644 --- a/src/wallet.ts +++ b/src/wallet.ts @@ -69,6 +69,8 @@ import { PurchaseDetails, ExchangeWithdrawDetails, RefreshReason, + ExchangeListItem, + ExchangesListRespose, } from "./types/walletTypes"; import { Logger } from "./util/logging"; @@ -549,10 +551,40 @@ export class Wallet { return denoms; } - async getExchanges(): Promise { + /** + * Get all exchanges known to the exchange. + * + * @deprecated Use getExchanges instead + */ + async getExchangeRecords(): Promise { return await this.db.iter(Stores.exchanges).toArray(); } + async getExchanges(): Promise { + const exchanges: (ExchangeListItem | undefined)[] = await this.db + .iter(Stores.exchanges) + .map((x) => { + const details = x.details; + if (!details) { + return undefined; + } + if (!x.addComplete) { + return undefined; + } + if (!x.wireInfo) { + return undefined; + } + return { + exchangeBaseUrl: x.baseUrl, + currency: details.currency, + paytoUris: x.wireInfo.accounts.map(x => x.payto_uri), + }; + }); + return { + exchanges: exchanges.filter((x) => !!x) as ExchangeListItem[], + }; + } + async getCurrencies(): Promise { return await this.db.iter(Stores.currencies).toArray(); } diff --git a/src/webex/wxBackend.ts b/src/webex/wxBackend.ts index 88d5545d9..5cf61a78a 100644 --- a/src/webex/wxBackend.ts +++ b/src/webex/wxBackend.ts @@ -27,7 +27,7 @@ import { BrowserCryptoWorkerFactory } from "../crypto/workers/cryptoApi"; import { deleteTalerDatabase, openTalerDatabase, - WALLET_DB_VERSION, + WALLET_DB_MINOR_VERSION, } from "../db"; import { ReturnCoinsRequest, @@ -151,7 +151,7 @@ async function handleMessage( return needsWallet().getHistory(); } case "get-exchanges": { - return needsWallet().getExchanges(); + return needsWallet().getExchangeRecords(); } case "get-currencies": { return needsWallet().getCurrencies(); @@ -201,7 +201,7 @@ async function handleMessage( dbResetRequired = true; } const resp: wxApi.UpgradeResponse = { - currentDbVersion: WALLET_DB_VERSION.toString(), + currentDbVersion: WALLET_DB_MINOR_VERSION.toString(), dbResetRequired, oldDbVersion: (outdatedDbVersion || "unknown").toString(), }; -- cgit v1.2.3