taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit ade2bece8c11877989c78ef5df98e3d7faa8c831
parent b8a1443edcbb68eafd6f16de428a2905af829600
Author: Florian Dold <dold@taler.net>
Date:   Sun,  9 Aug 2026 23:51:50 +0200

wallet-cli: manage known bank accounts

Diffstat:
Mpackages/taler-wallet-cli/src/index.ts | 127++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 123 insertions(+), 4 deletions(-)

diff --git a/packages/taler-wallet-cli/src/index.ts b/packages/taler-wallet-cli/src/index.ts @@ -2827,13 +2827,122 @@ bankAccountsCli.subcommand("listArgs", "list").action(async (args) => { }); }); +bankAccountsCli + .subcommand("addBankAccountArgs", "add", { + help: "Add a known bank account.", + }) + .requiredArgument("paytoUri", clk.STRING, { + metavar: "PAYTO_URI", + help: "Payto URI of the bank account.", + }) + .requiredArgument("label", clk.STRING, { + metavar: "LABEL", + help: "Label used to refer to this account in other commands.", + }) + .action(async (args) => { + await runCliAction(() => + withWallet(args, { lazyTaskLoop: true }, async (wallet) => { + const resp = await wallet.client.call( + WalletApiOperation.AddBankAccount, + { + paytoUri: args.addBankAccountArgs.paytoUri, + label: args.addBankAccountArgs.label, + }, + ); + console.log(`Added bank account ${resp.bankAccountId}`); + }), + ); + }); + +async function resolveKnownBankAccountId( + wallet: WalletContext, + account: string, +): Promise<string> { + const { accounts } = await wallet.client.call( + WalletApiOperation.ListBankAccounts, + {}, + ); + const matches = accounts.filter( + (knownAccount) => + knownAccount.bankAccountId === account || knownAccount.label === account, + ); + if (matches.length === 0) { + throw new CliUsageError( + `unknown bank account '${account}'`, + "pass an account ID or the label of an account shown by 'bank-accounts list'", + ); + } + if (matches.length > 1) { + throw new CliUsageError( + `bank account '${account}' is ambiguous`, + "use the account ID shown by 'bank-accounts list' instead", + ); + } + return matches[0].bankAccountId; +} + +bankAccountsCli + .subcommand("deleteBankAccountArgs", "delete", { + help: "Delete a known bank account.", + }) + .requiredArgument("account", clk.STRING, { + metavar: "ACCOUNT_ID_OR_LABEL", + help: "Account ID or label of the account to delete.", + }) + .action(async (args) => { + await runCliAction(() => + withWallet(args, { lazyTaskLoop: true }, async (wallet) => { + const bankAccountId = await resolveKnownBankAccountId( + wallet, + args.deleteBankAccountArgs.account, + ); + await wallet.client.call(WalletApiOperation.ForgetBankAccount, { + bankAccountId, + }); + console.log(`Deleted bank account ${bankAccountId}`); + }), + ); + }); + +async function resolveDepositPaytoUri( + wallet: WalletContext, + amount: AmountString, + target: string, +): Promise<string> { + if (target.toLowerCase().startsWith("payto:")) { + return target; + } + + const { accounts } = await wallet.client.call( + WalletApiOperation.ListBankAccounts, + { currency: Amounts.currencyOf(amount) }, + ); + const matches = accounts.filter((account) => account.label === target); + if (matches.length === 0) { + throw new CliUsageError( + `unknown bank account label '${target}'`, + "pass a payto URI or the label of an account shown by 'bank-accounts list'", + ); + } + if (matches.length > 1) { + throw new CliUsageError( + `bank account label '${target}' is ambiguous`, + "use the account's payto URI instead", + ); + } + return matches[0].paytoUri; +} + const depositCli = walletCli.subcommand("depositArgs", "deposit", { - help: "Deposit money to a payto:// account.", + help: "Deposit money to a payto:// account or known bank account.", }); depositCli .requiredArgument("amount", clk.AMOUNT) - .requiredArgument("targetPayto", clk.STRING) + .requiredArgument("target", clk.STRING, { + metavar: "PAYTO_OR_LABEL", + help: "Target payto URI or label of a known bank account.", + }) .flag("check", ["--check"], { help: "Check the deposit without creating it.", }) @@ -2847,11 +2956,16 @@ depositCli if (args.depositArgs.check) { await runCliAction(() => withWallet(args, { lazyTaskLoop: true }, async (wallet) => { + const depositPaytoUri = await resolveDepositPaytoUri( + wallet, + args.depositArgs.amount, + args.depositArgs.target, + ); const resp = await wallet.client.call( WalletApiOperation.CheckDeposit, { amount: args.depositArgs.amount, - depositPaytoUri: args.depositArgs.targetPayto, + depositPaytoUri, }, ); console.log(`Check deposit result: ${j2s(resp)}`); @@ -2862,11 +2976,16 @@ depositCli await runCliAction(() => withWallet(args, { lazyTaskLoop: true }, async (wallet) => { + const depositPaytoUri = await resolveDepositPaytoUri( + wallet, + args.depositArgs.amount, + args.depositArgs.target, + ); const resp = await wallet.client.call( WalletApiOperation.CreateDepositGroup, { amount: args.depositArgs.amount, - depositPaytoUri: args.depositArgs.targetPayto, + depositPaytoUri, }, ); console.log(`Created deposit ${resp.depositGroupId}`);