From 3da1e82a245851c384c22293c928fcef1c4c2f34 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 12 Oct 2022 21:19:09 +0200 Subject: wallet-core: skeleton for dev-experiments --- .vscode/settings.json | 1 - packages/taler-util/src/taleruri.ts | 21 ++++++++++++ packages/taler-util/src/walletTypes.ts | 10 ++++++ packages/taler-wallet-cli/src/index.ts | 8 +++++ packages/taler-wallet-core/src/dev-experiments.ts | 38 ++++++++++++++++++++++ packages/taler-wallet-core/src/wallet-api-types.ts | 17 +++++++++- packages/taler-wallet-core/src/wallet.ts | 7 ++++ 7 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 packages/taler-wallet-core/src/dev-experiments.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 97596d26c..803c58a07 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -21,7 +21,6 @@ // Defines whether an open brace is put onto a new line for control blocks or not "typescript.format.placeOpenBraceOnNewLineForControlBlocks": false, "typescript.preferences.autoImportFileExcludePatterns": [ - "index.js", "index.*.js", "index.ts", "index.*.ts" diff --git a/packages/taler-util/src/taleruri.ts b/packages/taler-util/src/taleruri.ts index e7d66d7d5..baca3efac 100644 --- a/packages/taler-util/src/taleruri.ts +++ b/packages/taler-util/src/taleruri.ts @@ -50,6 +50,10 @@ export interface PayPullUriResult { contractPriv: string; } +export interface DevExperimentUri { + devExperimentId: string; +} + /** * Parse a taler[+http]://withdraw URI. * Return undefined if not passed a valid URI. @@ -91,6 +95,7 @@ export enum TalerUriType { TalerNotifyReserve = "taler-notify-reserve", TalerPayPush = "taler-pay-push", TalerPayPull = "taler-pay-pull", + TalerDevExperiment = "taler-dev-experiment", Unknown = "unknown", } @@ -141,6 +146,9 @@ export function classifyTalerUri(s: string): TalerUriType { if (sl.startsWith("taler://notify-reserve/")) { return TalerUriType.TalerNotifyReserve; } + if (sl.startsWith("taler://dev-experiment/")) { + return TalerUriType.TalerDevExperiment; + } return TalerUriType.Unknown; } @@ -300,6 +308,19 @@ export function parseRefundUri(s: string): RefundUriResult | undefined { }; } +export function parseDevExperimentUri(s: string): DevExperimentUri | undefined { + const pi = parseProtoInfo(s, "dev-experiment"); + const c = pi?.rest.split("?"); + if (!c) { + return undefined; + } + // const q = new URLSearchParams(c[1] ?? ""); + const parts = c[0].split("/"); + return { + devExperimentId: parts[0], + }; +} + export function constructPayPushUri(args: { exchangeBaseUrl: string; contractPriv: string; diff --git a/packages/taler-util/src/walletTypes.ts b/packages/taler-util/src/walletTypes.ts index 7495e02d6..05b18fe6d 100644 --- a/packages/taler-util/src/walletTypes.ts +++ b/packages/taler-util/src/walletTypes.ts @@ -1683,6 +1683,16 @@ export interface AcceptPeerPullPaymentRequest { peerPullPaymentIncomingId: string; } +export interface ApplyDevExperimentRequest { + devExperimentUri: string; +} + +export const codecForApplyDevExperiment = + (): Codec => + buildCodecForObject() + .property("devExperimentUri", codecForString()) + .build("ApplyDevExperimentRequest"); + export const codecForAcceptPeerPullPaymentRequest = (): Codec => buildCodecForObject() diff --git a/packages/taler-wallet-cli/src/index.ts b/packages/taler-wallet-cli/src/index.ts index 7ff369a5e..09ab414ac 100644 --- a/packages/taler-wallet-cli/src/index.ts +++ b/packages/taler-wallet-cli/src/index.ts @@ -43,6 +43,7 @@ import { setDangerousTimetravel, setGlobalLogLevelFromString, TalerUriType, + parseDevExperimentUri, } from "@gnu-taler/taler-util"; import { CryptoDispatcher, @@ -67,6 +68,7 @@ import { runEnv1 } from "./env1.js"; import { GlobalTestState, runTestWithState } from "./harness/harness.js"; import { getTestInfo, runTests } from "./integrationtests/testrunner.js"; import { lintExchangeDeployment } from "./lint.js"; +import { checkLogicInvariant } from "@gnu-taler/taler-wallet-core/src/util/invariants.js"; // @ts-ignore global.TextEncoder = TextEncoder; // @ts-ignore @@ -498,6 +500,12 @@ walletCli console.log("accept withdrawal response", res); } break; + case TalerUriType.TalerDevExperiment: { + await wallet.client.call(WalletApiOperation.ApplyDevExperiment, { + devExperimentUri: uri, + }); + break; + } default: console.log(`URI type (${uriType}) not handled`); break; diff --git a/packages/taler-wallet-core/src/dev-experiments.ts b/packages/taler-wallet-core/src/dev-experiments.ts new file mode 100644 index 000000000..8e2ce5882 --- /dev/null +++ b/packages/taler-wallet-core/src/dev-experiments.ts @@ -0,0 +1,38 @@ +/* + This file is part of GNU Taler + (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ + +/** + * Implementation of dev experiments, i.e. scenarios + * triggered by taler://dev-experiment URIs. + * + * @author Florian Dold + */ + +/** + * Imports. + */ + +import { Logger } from "@gnu-taler/taler-util"; +import { InternalWalletState } from "./internal-wallet-state.js"; + +const logger = new Logger("dev-experiments.ts"); + +export async function applyDevExperiment( + ws: InternalWalletState, + uri: string, +): Promise { + logger.info(`applying dev experiment ${uri}`); +} diff --git a/packages/taler-wallet-core/src/wallet-api-types.ts b/packages/taler-wallet-core/src/wallet-api-types.ts index 15de5faf9..cecdd1281 100644 --- a/packages/taler-wallet-core/src/wallet-api-types.ts +++ b/packages/taler-wallet-core/src/wallet-api-types.ts @@ -80,6 +80,7 @@ import { WithdrawTestBalanceRequest, WithdrawUriInfoResponse, } from "@gnu-taler/taler-util"; +import { ApplyDevExperimentRequest } from "@gnu-taler/taler-util"; import { AddBackupProviderRequest, BackupInfo, @@ -139,6 +140,7 @@ export enum WalletApiOperation { AcceptPeerPullPayment = "acceptPeerPullPayment", ClearDb = "clearDb", Recycle = "recycle", + ApplyDevExperiment = "applyDevExperiment", } // group: Initialization @@ -487,7 +489,7 @@ export type AcceptPeerPullPaymentOp = { // group: Database Management /** - * Exoport the wallet database's contents to JSON. + * Export the wallet database's contents to JSON. */ export type ExportDbOp = { op: WalletApiOperation.ExportDb; @@ -515,6 +517,18 @@ export type RecycleOp = { // group: Testing and Debugging +/** + * Apply a developer experiment to the current wallet state. + * + * This allows UI developers / testers to play around without + * an elaborate test environment. + */ +export type ApplyDevExperimentOp = { + op: WalletApiOperation.ApplyDevExperiment; + request: ApplyDevExperimentRequest; + response: {}; +}; + /** * Run a simple integration test on a test deployment * of the exchange and merchant. @@ -661,6 +675,7 @@ export type WalletOperations = { [WalletApiOperation.AcceptPeerPullPayment]: AcceptPeerPullPaymentOp; [WalletApiOperation.ClearDb]: ClearDbOp; [WalletApiOperation.Recycle]: RecycleOp; + [WalletApiOperation.ApplyDevExperiment]: ApplyDevExperimentOp; }; export type RequestType< diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index 357dd586a..e25b4bd95 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -90,6 +90,7 @@ import { parsePaytoUri, RefreshReason, TalerErrorCode, + codecForApplyDevExperiment, URL, WalletCoreVersion, WalletNotification, @@ -109,6 +110,7 @@ import { importDb, WalletStoresV1, } from "./db.js"; +import { applyDevExperiment } from "./dev-experiments.js"; import { getErrorDetailFromException, TalerError } from "./errors.js"; import { ActiveLongpollInfo, @@ -1325,6 +1327,11 @@ async function dispatchRequestInternal( const req = codecForAcceptPeerPullPaymentRequest().decode(payload); return await acceptPeerPullPayment(ws, req); } + case "applyDevExperiment": { + const req = codecForApplyDevExperiment().decode(payload); + await applyDevExperiment(ws, req.devExperimentUri); + return {}; + } case "getVersion": { const version: WalletCoreVersion = { hash: GIT_HASH, -- cgit v1.2.3