diff options
Diffstat (limited to 'packages/taler-wallet-cli/src/index.ts')
-rw-r--r-- | packages/taler-wallet-cli/src/index.ts | 400 |
1 files changed, 240 insertions, 160 deletions
diff --git a/packages/taler-wallet-cli/src/index.ts b/packages/taler-wallet-cli/src/index.ts index 32b1eb901..5bde7db01 100644 --- a/packages/taler-wallet-cli/src/index.ts +++ b/packages/taler-wallet-cli/src/index.ts @@ -29,6 +29,7 @@ import { encodeCrock, getErrorDetailFromException, getRandomBytes, + InitRequest, j2s, Logger, NotificationType, @@ -57,6 +58,7 @@ import { JsonMessage, runRpcServer } from "@gnu-taler/taler-util/twrpc"; import { AccessStats, createNativeWalletHost2, + nativeCrypto, Wallet, WalletApiOperation, WalletCoreApiClient, @@ -89,7 +91,8 @@ setUnhandledRejectionHandler((error: any) => { processExit(1); }); -const defaultWalletDbPath = pathHomedir() + "/" + ".talerwalletdb.json"; +const defaultWalletDbPath = pathHomedir() + "/" + ".talerwalletdb.sqlite3"; +const defaultWalletCoreSocket = pathHomedir() + "/" + ".wallet-core.sock"; function assertUnreachable(x: never): never { throw new Error("Didn't expect to get here"); @@ -250,8 +253,8 @@ interface CreateWalletResult { async function createLocalWallet( walletCliArgs: WalletCliArgsType, + args: WalletRunArgs, notificationHandler?: (n: WalletNotification) => void, - noInit?: boolean, ): Promise<CreateWalletResult> { const dbPath = walletCliArgs.wallet.walletDbFile ?? defaultWalletDbPath; const myHttpLib = createPlatformHttpLib({ @@ -273,23 +276,27 @@ async function createLocalWallet( applyVerbose(walletCliArgs.wallet.verbose); const res = { wallet: wh.wallet, getStats: wh.getDbStats }; - if (noInit) { + if (args.noInit) { return res; } try { - await wh.wallet.handleCoreApiRequest("initWallet", "native-init", { - config: { - features: {}, - testing: { - devModeActive: checkEnvFlag("TALER_WALLET_DEV_MODE"), - denomselAllowLate: checkEnvFlag( - "TALER_WALLET_DEBUG_DENOMSEL_ALLOW_LATE", - ), - emitObservabilityEvents: observabilityEventFile != null, - skipDefaults: walletCliArgs.wallet.skipDefaults, + await wh.wallet.handleCoreApiRequest( + WalletApiOperation.InitWallet, + "native-init", + { + config: { + lazyTaskLoop: args.lazyTaskLoop, + testing: { + devModeActive: checkEnvFlag("TALER_WALLET_DEV_MODE"), + denomselAllowLate: checkEnvFlag( + "TALER_WALLET_DEBUG_DENOMSEL_ALLOW_LATE", + ), + emitObservabilityEvents: observabilityEventFile != null, + skipDefaults: walletCliArgs.wallet.skipDefaults, + }, }, - }, - }); + } satisfies InitRequest, + ); return res; } catch (e) { const ed = getErrorDetailFromException(e); @@ -299,25 +306,32 @@ async function createLocalWallet( } } +function writeObservabilityLog(notif: WalletNotification): void { + if (observabilityEventFile) { + switch (notif.type) { + case NotificationType.RequestObservabilityEvent: + case NotificationType.TaskObservabilityEvent: + fs.appendFileSync(observabilityEventFile, JSON.stringify(notif) + "\n"); + break; + } + } +} + +export interface WalletRunArgs { + lazyTaskLoop?: boolean; + noInit?: boolean; +} + async function withWallet<T>( walletCliArgs: WalletCliArgsType, + args: WalletRunArgs = {}, f: (ctx: WalletContext) => Promise<T>, ): Promise<T> { const waiter = makeNotificationWaiter(); const onNotif = (notif: WalletNotification) => { waiter.notify(notif); - if (observabilityEventFile) { - switch (notif.type) { - case NotificationType.RequestObservabilityEvent: - case NotificationType.TaskObservabilityEvent: - fs.appendFileSync( - observabilityEventFile, - JSON.stringify(notif) + "\n", - ); - break; - } - } + writeObservabilityLog(notif); }; if (walletCliArgs.wallet.walletConnection) { @@ -338,7 +352,7 @@ async function withWallet<T>( w.close(); return res; } else { - const wh = await createLocalWallet(walletCliArgs, onNotif); + const wh = await createLocalWallet(walletCliArgs, args, onNotif); const ctx: WalletContext = { client: wh.wallet.client, waitForNotificationCond: waiter.waitForNotificationCond, @@ -347,7 +361,7 @@ async function withWallet<T>( }, }; const result = await f(ctx); - wh.wallet.stop(); + await wh.wallet.client.call(WalletApiOperation.Shutdown, {}); if (process.env.TALER_WALLET_DBSTATS) { console.log("database stats:"); console.log(j2s(wh.getStats())); @@ -356,36 +370,25 @@ async function withWallet<T>( } } -/** - * Run a function with a local wallet. - * - * Stops the wallet after the function is done. - */ -async function withLocalWallet<T>( - walletCliArgs: WalletCliArgsType, - f: (w: { client: WalletCoreApiClient; ws: Wallet }) => Promise<T>, -): Promise<T> { - const wh = await createLocalWallet(walletCliArgs); - const w = wh.wallet; - const res = await f({ client: w.client, ws: w }); - logger.info("Work done, stopping wallet."); - w.stop(); - return res; -} - walletCli .subcommand("balance", "balance", { help: "Show wallet balance." }) .flag("json", ["--json"], { help: "Show raw JSON.", }) .action(async (args) => { - await withWallet(args, async (wallet) => { - const balance = await wallet.client.call( - WalletApiOperation.GetBalances, - {}, - ); - console.log(JSON.stringify(balance, undefined, 2)); - }); + await withWallet( + args, + { + lazyTaskLoop: true, + }, + async (wallet) => { + const balance = await wallet.client.call( + WalletApiOperation.GetBalances, + {}, + ); + console.log(JSON.stringify(balance, undefined, 2)); + }, + ); }); walletCli @@ -396,7 +399,7 @@ walletCli help: "Exit with non-zero status code when request fails instead of returning error JSON.", }) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, {}, async (wallet) => { let requestJson; logger.info(`handling 'api' request (${args.api.operation})`); const jsonContent = args.api.request.startsWith("@") @@ -439,17 +442,24 @@ const transactionsCli = walletCli // Default action transactionsCli.action(async (args) => { - await withWallet(args, async (wallet) => { - const pending = await wallet.client.call( - WalletApiOperation.GetTransactions, - { - currency: args.transactions.currency, - search: args.transactions.search, - includeRefreshes: args.transactions.includeRefreshes, - }, - ); - console.log(JSON.stringify(pending, undefined, 2)); - }); + await withWallet( + args, + { + lazyTaskLoop: true, + }, + async (wallet) => { + const pending = await wallet.client.call( + WalletApiOperation.GetTransactions, + { + currency: args.transactions.currency, + search: args.transactions.search, + includeRefreshes: args.transactions.includeRefreshes, + sort: "stable-ascending", + }, + ); + console.log(JSON.stringify(pending, undefined, 2)); + }, + ); }); transactionsCli @@ -460,11 +470,18 @@ transactionsCli help: "Identifier of the transaction to delete", }) .action(async (args) => { - await withWallet(args, async (wallet) => { - await wallet.client.call(WalletApiOperation.DeleteTransaction, { - transactionId: args.deleteTransaction.transactionId as TransactionIdStr, - }); - }); + await withWallet( + args, + { + lazyTaskLoop: true, + }, + async (wallet) => { + await wallet.client.call(WalletApiOperation.DeleteTransaction, { + transactionId: args.deleteTransaction + .transactionId as TransactionIdStr, + }); + }, + ); }); transactionsCli @@ -475,12 +492,18 @@ transactionsCli help: "Identifier of the transaction to suspend.", }) .action(async (args) => { - await withWallet(args, async (wallet) => { - await wallet.client.call(WalletApiOperation.SuspendTransaction, { - transactionId: args.suspendTransaction - .transactionId as TransactionIdStr, - }); - }); + await withWallet( + args, + { + lazyTaskLoop: true, + }, + async (wallet) => { + await wallet.client.call(WalletApiOperation.SuspendTransaction, { + transactionId: args.suspendTransaction + .transactionId as TransactionIdStr, + }); + }, + ); }); transactionsCli @@ -491,11 +514,17 @@ transactionsCli help: "Identifier of the transaction to fail.", }) .action(async (args) => { - await withWallet(args, async (wallet) => { - await wallet.client.call(WalletApiOperation.FailTransaction, { - transactionId: args.fail.transactionId as TransactionIdStr, - }); - }); + await withWallet( + args, + { + lazyTaskLoop: true, + }, + async (wallet) => { + await wallet.client.call(WalletApiOperation.FailTransaction, { + transactionId: args.fail.transactionId as TransactionIdStr, + }); + }, + ); }); transactionsCli @@ -506,7 +535,7 @@ transactionsCli help: "Identifier of the transaction to suspend.", }) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { await wallet.client.call(WalletApiOperation.ResumeTransaction, { transactionId: args.resumeTransaction.transactionId as TransactionIdStr, }); @@ -521,7 +550,7 @@ transactionsCli help: "Identifier of the transaction to delete", }) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const tx = await wallet.client.call( WalletApiOperation.GetTransactionById, { @@ -540,7 +569,7 @@ transactionsCli help: "Identifier of the transaction to delete", }) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { await wallet.client.call(WalletApiOperation.AbortTransaction, { transactionId: args.abortTransaction.transactionId as TransactionIdStr, }); @@ -552,7 +581,7 @@ walletCli help: "Show version details.", }) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const versionInfo = await wallet.client.call( WalletApiOperation.GetVersion, {}, @@ -567,7 +596,7 @@ transactionsCli }) .requiredArgument("transactionId", clk.STRING) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { await wallet.client.call(WalletApiOperation.RetryTransaction, { transactionId: args.retryTransaction.transactionId as TransactionIdStr, }); @@ -579,12 +608,8 @@ walletCli help: "Run until no more work is left.", }) .action(async (args) => { - await withLocalWallet(args, async (wallet) => { - logger.info("running until pending operations are finished"); - await wallet.ws.runTaskLoop({ - stopWhenDone: true, - }); - wallet.ws.stop(); + await withWallet(args, { lazyTaskLoop: false }, async (ctx) => { + await ctx.client.call(WalletApiOperation.TestingWaitTasksDone, {}); }); }); @@ -600,7 +625,7 @@ withdrawCli const uri = args.withdrawCheckUri.uri; const restrictAge = args.withdrawCheckUri.restrictAge; console.log(`age restriction requested (${restrictAge})`); - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const withdrawInfo = await wallet.client.call( WalletApiOperation.GetWithdrawalDetailsForUri, { @@ -620,7 +645,7 @@ withdrawCli .action(async (args) => { const restrictAge = args.withdrawCheckAmount.restrictAge; console.log(`age restriction requested (${restrictAge})`); - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const withdrawInfo = await wallet.client.call( WalletApiOperation.GetWithdrawalDetailsForAmount, { @@ -642,7 +667,7 @@ withdrawCli const uri = args.withdrawAcceptUri.uri; const restrictAge = args.withdrawAcceptUri.restrictAge; console.log(`age restriction requested (${restrictAge})`); - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const res = await wallet.client.call( WalletApiOperation.AcceptBankIntegratedWithdrawal, { @@ -666,7 +691,7 @@ walletCli .maybeOption("restrictAge", ["--restrict-age"], clk.INT) .flag("autoYes", ["-y", "--yes"]) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { let uri; if (args.handleUri.uri) { uri = args.handleUri.uri; @@ -724,7 +749,7 @@ walletCli break; } default: - console.log(`URI type (${parsedTalerUri}) not handled`); + console.log(`URI type (${parsedTalerUri.type}) not handled`); break; } return; @@ -741,9 +766,10 @@ withdrawCli .requiredOption("amount", ["--amount"], clk.AMOUNT, { help: "Amount to withdraw", }) + .maybeOption("forcedReservePriv", ["--forced-reserve-priv"], clk.STRING, {}) .maybeOption("restrictAge", ["--restrict-age"], clk.INT) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const exchangeBaseUrl = args.withdrawManually.exchange; const amount = args.withdrawManually.amount; const d = await wallet.client.call( @@ -753,7 +779,7 @@ withdrawCli exchangeBaseUrl: exchangeBaseUrl, }, ); - const acct = d.paytoUris[0]; + const acct = d.withdrawalAccountsList[0]; if (!acct) { console.log("exchange has no accounts"); return; @@ -764,10 +790,11 @@ withdrawCli amount, exchangeBaseUrl, restrictAge: parseInt(String(args.withdrawManually.restrictAge), 10), + forceReservePriv: args.withdrawManually.forcedReservePriv, }, ); const reservePub = resp.reservePub; - const completePaytoUri = addPaytoQueryParams(acct, { + const completePaytoUri = addPaytoQueryParams(acct.paytoUri, { amount: args.withdrawManually.amount, message: `Taler top-up ${reservePub}`, }); @@ -786,7 +813,7 @@ exchangesCli }) .action(async (args) => { console.log("Listing exchanges ..."); - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const exchanges = await wallet.client.call( WalletApiOperation.ListExchanges, {}, @@ -804,7 +831,7 @@ exchangesCli }) .flag("force", ["-f", "--force"]) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { await wallet.client.call(WalletApiOperation.UpdateExchangeEntry, { exchangeBaseUrl: args.exchangesUpdateCmd.url, force: args.exchangesUpdateCmd.force, @@ -820,7 +847,7 @@ exchangesCli help: "Base URL of the exchange.", }) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const resp = await wallet.client.call( WalletApiOperation.GetExchangeDetailedInfo, { @@ -839,7 +866,7 @@ exchangesCli help: "Base URL of the exchange.", }) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { await wallet.client.call(WalletApiOperation.AddExchange, { exchangeBaseUrl: args.exchangesAddCmd.url, }); @@ -855,7 +882,7 @@ exchangesCli }) .flag("purge", ["--purge"]) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { await wallet.client.call(WalletApiOperation.DeleteExchange, { exchangeBaseUrl: args.exchangesAddCmd.url, purge: args.exchangesAddCmd.purge, @@ -871,7 +898,7 @@ exchangesCli help: "Base URL of the exchange.", }) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { await wallet.client.call(WalletApiOperation.SetExchangeTosAccepted, { exchangeBaseUrl: args.exchangesAcceptTosCmd.url, }); @@ -894,7 +921,7 @@ exchangesCli .map((x) => x.trim()); acceptedFormat = split; } - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const tosResult = await wallet.client.call( WalletApiOperation.GetExchangeTos, { @@ -911,14 +938,14 @@ const backupCli = walletCli.subcommand("backupArgs", "backup", { }); backupCli.subcommand("exportDb", "export-db").action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const backup = await wallet.client.call(WalletApiOperation.ExportDb, {}); console.log(JSON.stringify(backup, undefined, 2)); }); }); backupCli.subcommand("storeBackup", "store").action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const resp = await wallet.client.call( WalletApiOperation.CreateStoredBackup, {}, @@ -928,7 +955,7 @@ backupCli.subcommand("storeBackup", "store").action(async (args) => { }); backupCli.subcommand("storeBackup", "list-stored").action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const resp = await wallet.client.call( WalletApiOperation.ListStoredBackups, {}, @@ -941,7 +968,7 @@ backupCli .subcommand("storeBackup", "delete-stored") .requiredArgument("name", clk.STRING) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const resp = await wallet.client.call( WalletApiOperation.DeleteStoredBackup, { @@ -956,7 +983,7 @@ backupCli .subcommand("recoverBackup", "recover-stored") .requiredArgument("name", clk.STRING) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const resp = await wallet.client.call( WalletApiOperation.RecoverStoredBackup, { @@ -968,7 +995,7 @@ backupCli }); backupCli.subcommand("importDb", "import-db").action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const dumpRaw = await read(process.stdin); const dump = JSON.parse(dumpRaw); await wallet.client.call(WalletApiOperation.ImportDb, { @@ -986,7 +1013,7 @@ depositCli .requiredArgument("amount", clk.AMOUNT) .requiredArgument("targetPayto", clk.STRING) .action(async (args) => { - await withLocalWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const resp = await wallet.client.call( WalletApiOperation.CreateDepositGroup, { @@ -1010,7 +1037,7 @@ peerCli help: "Amount to pay", }) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const resp = await wallet.client.call( WalletApiOperation.CheckPeerPushDebit, { @@ -1029,7 +1056,7 @@ peerCli help: "Amount to request", }) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const resp = await wallet.client.call( WalletApiOperation.CheckPeerPullCredit, { @@ -1044,7 +1071,7 @@ peerCli .subcommand("prepareIncomingPayPull", "prepare-pull-debit") .requiredArgument("talerUri", clk.STRING) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const resp = await wallet.client.call( WalletApiOperation.PreparePeerPullDebit, { @@ -1059,7 +1086,7 @@ peerCli .subcommand("confirmIncomingPayPull", "confirm-pull-debit") .requiredArgument("transactionId", clk.STRING) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const resp = await wallet.client.call( WalletApiOperation.ConfirmPeerPullDebit, { @@ -1075,7 +1102,7 @@ peerCli .subcommand("confirmIncomingPayPush", "confirm-push-credit") .requiredArgument("transactionId", clk.STRING) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const resp = await wallet.client.call( WalletApiOperation.ConfirmPeerPushCredit, { @@ -1113,7 +1140,7 @@ peerCli ); } - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const resp = await wallet.client.call( WalletApiOperation.InitiatePeerPullCredit, { @@ -1133,7 +1160,7 @@ peerCli .subcommand("preparePushCredit", "prepare-push-credit") .requiredArgument("talerUri", clk.STRING) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const resp = await wallet.client.call( WalletApiOperation.PreparePeerPushCredit, { @@ -1170,7 +1197,7 @@ peerCli ); } - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const resp = await wallet.client.call( WalletApiOperation.InitiatePeerPushDebit, { @@ -1190,6 +1217,44 @@ const advancedCli = walletCli.subcommand("advancedArgs", "advanced", { }); advancedCli + .subcommand("genReserve", "gen-reserve", { + help: "Generate a reserve key pair (not stored in the DB).", + }) + .action(async (args) => { + const pair = await nativeCrypto.createEddsaKeypair({}); + console.log( + j2s({ + reservePub: pair.pub, + reservePriv: pair.priv, + }), + ); + }); + +advancedCli + .subcommand("resetAllRetries", "reset-all-retries", { + help: "Reset all retry counters.", + }) + .action(async (args) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { + await wallet.client.call(WalletApiOperation.TestingResetAllRetries, {}); + }); + }); + +advancedCli + .subcommand("tasks", "tasks", { + help: "Show active wallet-core tasks.", + }) + .action(async (args) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { + const tasks = await wallet.client.call( + WalletApiOperation.GetActiveTasks, + {}, + ); + console.log(j2s(tasks)); + }); + }); + +advancedCli .subcommand("sampleTransactions", "sample-transactions", { help: "Print sample wallet-core transactions", }) @@ -1202,27 +1267,40 @@ advancedCli help: "Serve the wallet API via a unix domain socket.", }) .requiredOption("unixPath", ["--unix-path"], clk.STRING, { - default: "wallet-core.sock", + default: defaultWalletCoreSocket, }) .flag("noInit", ["--no-init"], { help: "Do not initialize the wallet. The client must send the initWallet message.", }) .action(async (args) => { - logger.info(`serving at ${args.serve.unixPath}`); - const onNotif = (notif: WalletNotification) => { - if (observabilityEventFile) { - switch (notif.type) { - case NotificationType.RequestObservabilityEvent: - case NotificationType.TaskObservabilityEvent: - fs.appendFileSync( - observabilityEventFile, - JSON.stringify(notif) + "\n", - ); - break; - } + const socketPath = args.serve.unixPath; + logger.info(`serving at ${socketPath}`); + let cleanupCalled = false; + + const cleanupSocket = (signal: string, code: number) => { + if (cleanupCalled) { + return; + } + cleanupCalled = true; + try { + logger.info("cleaning up socket"); + fs.unlinkSync(socketPath); + } catch (e) { + logger.warn(`unable to clean up socket: ${e}`); } + process.exit(128 + code); }; - const wh = await createLocalWallet(args, onNotif, args.serve.noInit); + process.on("SIGTERM", cleanupSocket); + process.on("SIGINT", cleanupSocket); + + const onNotif = (notif: WalletNotification) => { + writeObservabilityLog(notif); + }; + const wh = await createLocalWallet( + args, + { lazyTaskLoop: false, noInit: args.serve.noInit }, + onNotif, + ); const w = wh.wallet; let nextClientId = 1; const notifyHandlers = new Map<number, (n: WalletNotification) => void>(); @@ -1271,7 +1349,7 @@ advancedCli help: "Initialize the wallet (with DB) and exit.", }) .action(async (args) => { - await withWallet(args, async () => {}); + await withWallet(args, { lazyTaskLoop: true }, async () => {}); }); advancedCli @@ -1287,7 +1365,7 @@ advancedCli advancedCli .subcommand("pending", "pending", { help: "Show pending operations." }) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const pending = await wallet.client.call( WalletApiOperation.GetPendingOperations, {}, @@ -1316,10 +1394,8 @@ advancedCli exchangeBaseUrl: "http://localhost:8081/", merchantBaseUrl: "http://localhost:8083/", }); - await wallet.runTaskLoop({ - stopWhenDone: true, - }); - wallet.stop(); + await wallet.client.call(WalletApiOperation.TestingWaitTasksDone, {}); + await wallet.client.call(WalletApiOperation.Shutdown, {}); }); advancedCli @@ -1340,7 +1416,7 @@ currenciesCli help: "List global-currency auditors.", }) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const currencies = await wallet.client.call( WalletApiOperation.ListGlobalCurrencyAuditors, {}, @@ -1354,7 +1430,7 @@ currenciesCli help: "List global-currency exchanges.", }) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const currencies = await wallet.client.call( WalletApiOperation.ListGlobalCurrencyExchanges, {}, @@ -1371,7 +1447,7 @@ currenciesCli .requiredOption("exchangeBaseUrl", ["--url"], clk.STRING) .requiredOption("exchangePub", ["--pub"], clk.STRING) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const currencies = await wallet.client.call( WalletApiOperation.AddGlobalCurrencyExchange, { @@ -1392,7 +1468,7 @@ currenciesCli .requiredOption("exchangeBaseUrl", ["--url"], clk.STRING) .requiredOption("exchangePub", ["--pub"], clk.STRING) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const currencies = await wallet.client.call( WalletApiOperation.RemoveGlobalCurrencyExchange, { @@ -1413,7 +1489,7 @@ currenciesCli .requiredOption("auditorBaseUrl", ["--url"], clk.STRING) .requiredOption("auditorPub", ["--pub"], clk.STRING) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const currencies = await wallet.client.call( WalletApiOperation.AddGlobalCurrencyAuditor, { @@ -1434,7 +1510,7 @@ currenciesCli .requiredOption("auditorBaseUrl", ["--url"], clk.STRING) .requiredOption("auditorPub", ["--pub"], clk.STRING) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const currencies = await wallet.client.call( WalletApiOperation.RemoveGlobalCurrencyAuditor, { @@ -1452,7 +1528,7 @@ advancedCli help: "Clear the database, irrevocable deleting all data in the wallet.", }) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { await wallet.client.call(WalletApiOperation.ClearDb, {}); }); }); @@ -1462,7 +1538,7 @@ advancedCli help: "Export, clear and re-import the database via the backup mechanism.", }) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { await wallet.client.call(WalletApiOperation.Recycle, {}); }); }); @@ -1473,7 +1549,7 @@ advancedCli }) .requiredArgument("url", clk.STRING) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const res = await wallet.client.call( WalletApiOperation.PreparePayForUri, { @@ -1506,7 +1582,7 @@ advancedCli }) .requiredArgument("transactionId", clk.STRING) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { await wallet.client.call(WalletApiOperation.StartRefundQuery, { transactionId: args.queryRefund.transactionId as TransactionIdStr, }); @@ -1520,7 +1596,7 @@ advancedCli .requiredArgument("proposalId", clk.STRING) .maybeOption("sessionIdOverride", ["--session-id"], clk.STRING) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { await wallet.client.call(WalletApiOperation.ConfirmPay, { proposalId: args.payConfirm.proposalId, sessionId: args.payConfirm.sessionIdOverride, @@ -1534,9 +1610,13 @@ advancedCli }) .requiredArgument("coinPub", clk.STRING) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { await wallet.client.call(WalletApiOperation.ForceRefresh, { - coinPubList: [args.refresh.coinPub], + refreshCoinSpecs: [ + { + coinPub: args.refresh.coinPub, + }, + ], }); }); }); @@ -1546,7 +1626,7 @@ advancedCli help: "Dump coins in an easy-to-process format.", }) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const coinDump = await wallet.client.call( WalletApiOperation.DumpCoins, {}, @@ -1563,7 +1643,7 @@ advancedCli }) .requiredArgument("coinPubSpec", clk.STRING) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { let coinPubList: string[]; try { coinPubList = coinPubListCodec.decode( @@ -1588,7 +1668,7 @@ advancedCli }) .requiredArgument("coinPubSpec", clk.STRING) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { let coinPubList: string[]; try { coinPubList = coinPubListCodec.decode( @@ -1612,7 +1692,7 @@ advancedCli help: "List coins.", }) .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { const coins = await wallet.client.call(WalletApiOperation.DumpCoins, {}); for (const coin of coins.coins) { console.log(`coin ${coin.coin_pub}`); @@ -1630,13 +1710,13 @@ const testCli = walletCli.subcommand("testingArgs", "testing", { testCli .subcommand("withdrawTestkudos", "withdraw-testkudos") .action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { await wallet.client.call(WalletApiOperation.WithdrawTestkudos, {}); }); }); testCli.subcommand("withdrawKudos", "withdraw-kudos").action(async (args) => { - await withWallet(args, async (wallet) => { + await withWallet(args, { lazyTaskLoop: true }, async (wallet) => { await wallet.client.call(WalletApiOperation.WithdrawTestBalance, { amount: "KUDOS:50" as AmountString, corebankApiBaseUrl: "https://bank.demo.taler.net/", |