From 39035139130925bf596175ad8a3419a4cea401a8 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Sun, 21 Jun 2020 18:19:27 +0530 Subject: implement manual withdrawal --- src/headless/taler-wallet-cli.ts | 37 +++++++++++++++++++++++++++++++++++++ src/util/payto.ts | 19 ++++++++++++++++--- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/src/headless/taler-wallet-cli.ts b/src/headless/taler-wallet-cli.ts index b45b0eae8..839ee9992 100644 --- a/src/headless/taler-wallet-cli.ts +++ b/src/headless/taler-wallet-cli.ts @@ -34,6 +34,7 @@ import { setDangerousTimetravel } from "../util/time"; import { makeCodecForList, codecForString } from "../util/codec"; import { NodeHttpLib } from "./NodeHttpLib"; import * as nacl from "../crypto/primitives/nacl-fast"; +import { addPaytoQueryParams } from "../util/payto"; const logger = new Logger("taler-wallet-cli.ts"); @@ -367,6 +368,42 @@ advancedCli fs.writeFileSync(1, decodeCrock(enc.trim())); }); + +advancedCli +.subcommand("withdrawManually", "withdraw-manually", { + help: "Withdraw manually from an exchange.", +}) +.requiredOption("exchange", ["--exchange"], clk.STRING, { + help: "Base URL of the exchange.", +}) +.requiredOption("amount", ["--amount"], clk.STRING, { + help: "Amount to withdraw", +}) +.action(async (args) => { + await withWallet(args, async (wallet) => { + const exchange = await wallet.updateExchangeFromUrl(args.withdrawManually.exchange); + const acct = exchange.wireInfo?.accounts[0]; + if (!acct) { + console.log("exchange has no accounts"); + return; + } + const reserve = await wallet.createReserve({ + amount: Amounts.parseOrThrow(args.withdrawManually.amount), + exchangeWire: acct.payto_uri, + exchange: exchange.baseUrl, + }); + await wallet.confirmReserve({ + reservePub: reserve.reservePub, + }); + const completePaytoUri = addPaytoQueryParams(acct.payto_uri, { + amount: args.withdrawManually.amount, + message: `Taler top-up ${reserve.reservePub}`, + }); + console.log("Created reserve", reserve.reservePub); + console.log("Payto URI", completePaytoUri); + }); +}); + const reservesCli = advancedCli.subcommand("reserves", "reserves", { help: "Manage reserves.", }); diff --git a/src/util/payto.ts b/src/util/payto.ts index ac5bc0c7f..0f624de67 100644 --- a/src/util/payto.ts +++ b/src/util/payto.ts @@ -20,13 +20,26 @@ interface PaytoUri { params: { [name: string]: string }; } +const paytoPfx = "payto://"; + +/** + * Add query parameters to a payto URI + */ +export function addPaytoQueryParams(s: string, params: { [name: string]: string }): string { + const [acct, search] = s.slice(paytoPfx.length).split("?"); + const searchParams = new URLSearchParams(search || ""); + for (let k of Object.keys(params)) { + searchParams.set(k, params[k]); + } + return paytoPfx + acct + "?" + searchParams.toString(); +} + export function parsePaytoUri(s: string): PaytoUri | undefined { - const pfx = "payto://"; - if (!s.startsWith(pfx)) { + if (!s.startsWith(paytoPfx)) { return undefined; } - const [acct, search] = s.slice(pfx.length).split("?"); + const [acct, search] = s.slice(paytoPfx.length).split("?"); const firstSlashPos = acct.indexOf("/"); -- cgit v1.2.3