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:
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}`);