taler-typescript-core

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

commit 92862389d2b189c910e2fc6489a540b8ec7be8b5
parent 6c3635e2ff0c73085853c35adc515ee4a0c3bb78
Author: Florian Dold <florian@dold.me>
Date:   Tue,  7 Jan 2025 17:25:45 +0100

harness: skeleton for the coin acceptor scenario test

Diffstat:
Mpackages/taler-harness/src/index.ts | 79++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Mpackages/taler-util/src/http-client/authentication.ts | 10+++++-----
Mpackages/taler-util/src/http-client/bank-core.ts | 17++++++++++++++++-
Mpackages/taler-util/src/operation.ts | 4++--
Mpackages/taler-util/src/types-taler-corebank.ts | 8++++++++
5 files changed, 97 insertions(+), 21 deletions(-)

diff --git a/packages/taler-harness/src/index.ts b/packages/taler-harness/src/index.ts @@ -41,7 +41,9 @@ import { decodeCrock, encodeCrock, generateIban, + getRandomBytes, j2s, + narrowOpSuccessOrThrow, randomBytes, rsaBlind, setGlobalLogLevelFromString, @@ -62,9 +64,9 @@ import { topupReserveWithBank, } from "@gnu-taler/taler-wallet-core/dbless"; import { deepStrictEqual } from "assert"; -import fs from "node:fs"; import { AML_PROGRAM_FROM_ATTRIBUTES_TO_CONTEXT } from "integrationtests/test-kyc-skip-expiration.js"; import { AML_PROGRAM_NEXT_MEASURE_FORM } from "integrationtests/test-kyc-two-forms.js"; +import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import { runBench1 } from "./bench1.js"; @@ -101,7 +103,7 @@ function printVersion(): void { process.exit(0); } -export const testingCli = clk +export const talerHarnessCli = clk .program("testing", { help: "Command line interface for the GNU Taler test/deployment harness.", }) @@ -118,7 +120,54 @@ export const testingCli = clk help: "Enable verbose output.", }); -const advancedCli = testingCli.subcommand("advancedArgs", "advanced", { +const testingCli = talerHarnessCli.subcommand("testingArgs", "testing", { + help: "Subcommands for advanced operations (only use if you know what you're doing!).", +}); + +testingCli + .subcommand("scenarioCoinAcceptor", "scenario-coin-acceptor", { + help: "Test scenario for coin acceptor.", + }) + .action(async (args) => { + const httpLib = createPlatformHttpLib(); + const bankUrl = "https://bank.test.taler.net/"; + const bank = new TalerCoreBankHttpClient(bankUrl, httpLib); + const bankAuth = new TalerAuthenticationHttpClient(bankUrl, httpLib); + + const username = "user-" + encodeCrock(getRandomBytes(10)).toLowerCase(); + const password = "pw-" + encodeCrock(getRandomBytes(10)).toLowerCase(); + const createRes = await bank.createAccount(undefined, { + name: username, + username, + password, + }); + narrowOpSuccessOrThrow("create", createRes); + // It's a test account, so it's safe to log credentials. + logger.info( + `Created test bank account ${username} with password ${password}`, + ); + const tokRes = await bankAuth.createAccessTokenBasic(username, password, { + scope: "readwrite", + }); + narrowOpSuccessOrThrow("token", tokRes); + const token = tokRes.body.access_token; + logger.info(`Test account access token ${token}`); + const createWithdrawalResp = await bank.createWithdrawal( + { + username, + token, + }, + { + no_amount_to_wallet: true, + }, + ); + narrowOpSuccessOrThrow("create-withdrawal", createWithdrawalResp); + logger.info( + `Created withdrawal operation ${createWithdrawalResp.body.taler_withdraw_uri}`, + ); + }); + +const advancedCli = talerHarnessCli.subcommand("advancedArgs", "advanced", { help: "Subcommands for advanced operations (only use if you know what you're doing!).", }); @@ -358,7 +407,7 @@ advancedCli ); }); -const configCli = testingCli +const configCli = talerHarnessCli .subcommand("configArgs", "config", { help: "Subcommands for handling the Taler configuration.", }) @@ -441,9 +490,13 @@ configCli } }); -const deploymentCli = testingCli.subcommand("deploymentArgs", "deployment", { - help: "Subcommands for handling GNU Taler deployments.", -}); +const deploymentCli = talerHarnessCli.subcommand( + "deploymentArgs", + "deployment", + { + help: "Subcommands for handling GNU Taler deployments.", + }, +); deploymentCli .subcommand("testTalerdotnetDemo", "test-demodottalerdotnet") @@ -1307,14 +1360,14 @@ deploymentCli console.log(out); }); -testingCli.subcommand("logtest", "logtest").action(async (args) => { +talerHarnessCli.subcommand("logtest", "logtest").action(async (args) => { logger.trace("This is a trace message."); logger.info("This is an info message."); logger.warn("This is an warning message."); logger.error("This is an error message."); }); -testingCli +talerHarnessCli .subcommand("listIntegrationtests", "list-integrationtests") .action(async (args) => { for (const t of getTestInfo()) { @@ -1329,7 +1382,7 @@ testingCli } }); -testingCli +talerHarnessCli .subcommand("runIntegrationtests", "run-integrationtests") .maybeArgument("pattern", clk.STRING, { help: "Glob pattern to select which tests to run", @@ -1374,7 +1427,7 @@ async function read(stream: NodeJS.ReadStream) { return Buffer.concat(chunks).toString("utf8"); } -testingCli.subcommand("tvgcheck", "tvgcheck").action(async (args) => { +talerHarnessCli.subcommand("tvgcheck", "tvgcheck").action(async (args) => { const data = await read(process.stdin); const lines = data.match(/[^\r\n]+/g); @@ -1426,7 +1479,7 @@ testingCli.subcommand("tvgcheck", "tvgcheck").action(async (args) => { console.log("check passed!"); }); -export const amlProgramCli = testingCli.subcommand( +export const amlProgramCli = talerHarnessCli.subcommand( "amlProgram", "aml-program", { @@ -1577,5 +1630,5 @@ amlProgramCli }); export function main() { - testingCli.run(); + talerHarnessCli.run(); } diff --git a/packages/taler-util/src/http-client/authentication.ts b/packages/taler-util/src/http-client/authentication.ts @@ -89,8 +89,8 @@ export class TalerAuthenticationHttpClient { /** * FIXME: merge this with createAccessTokenBearer the protocol of both - * services need to reply the same - * + * services need to reply the same + * * @returns */ async createAccessTokenBearer_BANK(token: AccessToken, body: TokenRequest) { @@ -116,9 +116,9 @@ export class TalerAuthenticationHttpClient { } /** - * - * @returns - */ + * + * @returns + */ async createAccessTokenBearer(token: AccessToken, body: TokenRequest) { const url = new URL(`token`, this.baseUrl); const resp = await this.httpLib.fetch(url.href, { diff --git a/packages/taler-util/src/http-client/bank-core.ts b/packages/taler-util/src/http-client/bank-core.ts @@ -187,7 +187,22 @@ export class TalerCoreBankHttpClient { async createAccount( auth: AccessToken | undefined, body: TalerCorebankApi.RegisterAccountRequest, - ) { + ): Promise< + | OperationOk<TalerCorebankApi.RegisterAccountResponse> + | OperationFail<HttpStatusCode.BadRequest> + | OperationFail<HttpStatusCode.Unauthorized> + | OperationFail<TalerErrorCode.BANK_REGISTER_USERNAME_REUSE> + | OperationFail<TalerErrorCode.BANK_REGISTER_PAYTO_URI_REUSE> + | OperationFail<TalerErrorCode.BANK_UNALLOWED_DEBIT> + | OperationFail<TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT> + | OperationFail<TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT> + | OperationFail<TalerErrorCode.BANK_NON_ADMIN_SET_MIN_CASHOUT> + | OperationFail<TalerErrorCode.BANK_NON_ADMIN_SET_TAN_CHANNEL> + | OperationFail<TalerErrorCode.BANK_TAN_CHANNEL_NOT_SUPPORTED> + | OperationFail<TalerErrorCode.BANK_MISSING_TAN_INFO> + | OperationFail<TalerErrorCode.BANK_PASSWORD_TOO_SHORT> + | OperationFail<TalerErrorCode.BANK_PASSWORD_TOO_LONG> + > { const url = new URL(`accounts`, this.baseUrl); const headers: Record<string, string> = {}; if (auth) { diff --git a/packages/taler-util/src/operation.ts b/packages/taler-util/src/operation.ts @@ -170,9 +170,9 @@ export function opUnknownFailure( /** * Convenience function to throw an error if the operation is not a success. */ -export function narrowOpSuccessOrThrow<Body, ErrorEnum>( +export function narrowOpSuccessOrThrow<Body>( opName: string, - opRes: OperationResult<Body, ErrorEnum>, + opRes: OperationResult<Body, unknown>, ): asserts opRes is OperationOk<Body> { if (opRes.type !== "ok") { throw TalerError.fromDetail( diff --git a/packages/taler-util/src/types-taler-corebank.ts b/packages/taler-util/src/types-taler-corebank.ts @@ -144,6 +144,14 @@ export interface BankAccountCreateWithdrawalRequest { // still change the suggestion. // @since **vC2EC** suggested_amount?: AmountString; + + // If true, tell the wallet not to allow the user to + // specify an amount to withdraw and to not provide + // any amount when registering with the withdrawal + // operation. The amount to withdraw will be set + // by the final /withdrawals/$WITHDRAWAL_ID/confirm step. + // @since **v8** + no_amount_to_wallet?: boolean; } export interface BankAccountConfirmWithdrawalRequest {