commit 250e2cbcf9a370643ac1020943844722eb8306f4
parent d9544b558919d780f095c0219f4c3e4579be9bdf
Author: Florian Dold <florian@dold.me>
Date: Fri, 24 Jul 2026 17:26:30 +0200
add more convenient subcommand for peer-send
Diffstat:
1 file changed, 83 insertions(+), 8 deletions(-)
diff --git a/packages/taler-wallet-cli/src/index.ts b/packages/taler-wallet-cli/src/index.ts
@@ -19,7 +19,6 @@
*/
import {
AbsoluteTime,
- addPaytoQueryParams,
AgeRestriction,
Amounts,
AmountString,
@@ -33,13 +32,13 @@ import {
ExchangeTosStatus,
getErrorDetailFromException,
getRandomBytes,
+ getSampleWalletCoreTransactions,
InitRequest,
j2s,
Logger,
NotificationType,
Paytos,
Result,
- getSampleWalletCoreTransactions,
setDangerousTimetravel,
setGlobalLogLevelFromString,
summarizeTalerErrorDetail,
@@ -50,6 +49,7 @@ import {
TransactionMinorState,
TransactionType,
WalletNotification,
+ WithdrawalType,
} from "@gnu-taler/taler-util";
import { clk } from "@gnu-taler/taler-util/clk";
import {
@@ -760,6 +760,67 @@ walletCli
});
});
+walletCli
+ .subcommand("payPush", "peer-send", {
+ help: "Initiate a peer-push payment.",
+ })
+ .requiredArgument("amount", clk.AMOUNT, {
+ help: "Amount to pay",
+ })
+ .maybeOption("summary", ["--summary"], clk.STRING, {
+ help: "Summary to use in the contract terms.",
+ })
+ .maybeOption("purseExpiration", ["--purse-expiration"], clk.STRING)
+ .action(async (args) => {
+ let purseExpiration: AbsoluteTime;
+
+ if (args.payPush.purseExpiration) {
+ purseExpiration = AbsoluteTime.addDuration(
+ AbsoluteTime.now(),
+ Duration.fromPrettyString(args.payPush.purseExpiration),
+ );
+ } else {
+ purseExpiration = AbsoluteTime.addDuration(
+ AbsoluteTime.now(),
+ Duration.fromSpec({ hours: 1 }),
+ );
+ }
+
+ await withWallet(args, { lazyTaskLoop: true }, async (wallet) => {
+ const resp = await wallet.client.call(
+ WalletApiOperation.InitiatePeerPushDebit,
+ {
+ partialContractTerms: {
+ amount: args.payPush.amount,
+ summary: args.payPush.summary ?? "Payment",
+ purse_expiration: AbsoluteTime.toProtocolTimestamp(purseExpiration),
+ },
+ },
+ );
+ await wallet.client.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: resp.transactionId,
+ txState: {
+ major: TransactionMajorState.Pending,
+ minor: TransactionMinorState.Ready,
+ },
+ });
+ const txDet = await wallet.client.call(
+ WalletApiOperation.GetTransactionById,
+ {
+ transactionId: resp.transactionId,
+ },
+ );
+ if (txDet.type !== TransactionType.PeerPushDebit) {
+ throw Error("assertion failed");
+ }
+ if (txDet.talerUri == null) {
+ throw Error("assertion failed");
+ }
+ console.log("peer payment ready to send");
+ console.log(txDet.talerUri);
+ });
+ });
+
const withdrawCli = walletCli.subcommand("withdraw", "withdraw", {
help: "Withdraw with a taler://withdraw/ URI",
});
@@ -1142,13 +1203,27 @@ withdrawCli
forceReservePriv: args.withdrawManually.forcedReservePriv,
},
);
- const reservePub = resp.reservePub;
- const completePaytoUri = addPaytoQueryParams(acct.paytoUri, {
- amount: args.withdrawManually.amount,
- message: `Taler top-up ${reservePub}`,
+ await wallet.client.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: resp.transactionId,
+ txState: {
+ major: TransactionMajorState.Pending,
+ minor: TransactionMinorState.ExchangeWaitReserve,
+ },
});
- console.log("Created reserve", reservePub);
- console.log("Payto URI", completePaytoUri);
+ const txDet = await wallet.client.call(
+ WalletApiOperation.GetTransactionById,
+ {
+ transactionId: resp.transactionId,
+ },
+ );
+ if (txDet.type !== TransactionType.Withdrawal) {
+ throw Error("assertion failed");
+ }
+ if (txDet.withdrawalDetails.type !== WithdrawalType.ManualTransfer) {
+ throw Error("assertion failed");
+ }
+ console.log("transfer accounts:");
+ console.log(j2s(txDet.withdrawalDetails.exchangeCreditAccountDetails));
});
});