/*
This file is part of GNU Taler
(C) 2020 Taler Systems S.A.
GNU 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.
GNU 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
GNU Taler; see the file COPYING. If not, see
*/
import { Logger } from "../util/logging";
import {
HttpRequestLibrary,
readSuccessResponseJsonOrThrow,
checkSuccessResponseOrThrow,
} from "../util/http";
import { codecForAny } from "../util/codec";
import { AmountString } from "../types/talerTypes";
import { InternalWalletState } from "./state";
import { createTalerWithdrawReserve } from "./reserves";
import { URL } from "../util/url";
const logger = new Logger("operations/testing.ts");
interface BankUser {
username: string;
password: string;
}
interface BankWithdrawalResponse {
taler_withdraw_uri: string;
withdrawal_id: string;
}
/**
* Generate a random alphanumeric ID. Does *not* use cryptographically
* secure randomness.
*/
function makeId(length: number): string {
let result = "";
const characters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * characters.length));
}
return result;
}
/**
* Helper function to generate the "Authorization" HTTP header.
*/
function makeAuth(username: string, password: string): string {
const auth = `${username}:${password}`;
const authEncoded: string = Buffer.from(auth).toString("base64");
return `Basic ${authEncoded}`;
}
export async function withdrawTestBalance(
ws: InternalWalletState,
amount = "TESTKUDOS:10",
bankBaseUrl = "https://bank.test.taler.net/",
exchangeBaseUrl = "https://exchange.test.taler.net/",
): Promise {
const bankUser = await registerRandomBankUser(ws.http, bankBaseUrl);
logger.trace(`Registered bank user ${JSON.stringify(bankUser)}`);
const wresp = await createBankWithdrawalUri(
ws.http,
bankBaseUrl,
bankUser,
amount,
);
await createTalerWithdrawReserve(
ws,
wresp.taler_withdraw_uri,
exchangeBaseUrl,
);
await confirmBankWithdrawalUri(
ws.http,
bankBaseUrl,
bankUser,
wresp.withdrawal_id,
);
}
async function createBankWithdrawalUri(
http: HttpRequestLibrary,
bankBaseUrl: string,
bankUser: BankUser,
amount: AmountString,
): Promise {
const reqUrl = new URL(
`accounts/${bankUser.username}/withdrawals`,
bankBaseUrl,
).href;
const resp = await http.postJson(
reqUrl,
{
amount,
},
{
headers: {
Authorization: makeAuth(bankUser.username, bankUser.password),
},
},
);
const respJson = await readSuccessResponseJsonOrThrow(resp, codecForAny());
return respJson;
}
async function confirmBankWithdrawalUri(
http: HttpRequestLibrary,
bankBaseUrl: string,
bankUser: BankUser,
withdrawalId: string,
): Promise {
const reqUrl = new URL(
`accounts/${bankUser.username}/withdrawals/${withdrawalId}/confirm`,
bankBaseUrl,
).href;
const resp = await http.postJson(
reqUrl,
{},
{
headers: {
Authorization: makeAuth(bankUser.username, bankUser.password),
},
},
);
await readSuccessResponseJsonOrThrow(resp, codecForAny());
return;
}
async function registerRandomBankUser(
http: HttpRequestLibrary,
bankBaseUrl: string,
): Promise {
const reqUrl = new URL("testing/register", bankBaseUrl).href;
const randId = makeId(8);
const bankUser: BankUser = {
username: `testuser-${randId}`,
password: `testpw-${randId}`,
};
const resp = await http.postJson(reqUrl, bankUser);
await checkSuccessResponseOrThrow(resp);
return bankUser;
}