test for manual withdrawal
This commit is contained in:
parent
e8c0a43dd3
commit
5fb9dae13c
@ -69,8 +69,7 @@ export async function sh(
|
|||||||
logName: string,
|
logName: string,
|
||||||
command: string,
|
command: string,
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
console.log("runing command");
|
console.log("runing command", command);
|
||||||
console.log(command);
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const stdoutChunks: Buffer[] = [];
|
const stdoutChunks: Buffer[] = [];
|
||||||
const proc = spawn(command, {
|
const proc = spawn(command, {
|
||||||
@ -89,8 +88,8 @@ export async function sh(
|
|||||||
flags: "a",
|
flags: "a",
|
||||||
});
|
});
|
||||||
proc.stderr.pipe(stderrLog);
|
proc.stderr.pipe(stderrLog);
|
||||||
proc.on("exit", (code) => {
|
proc.on("exit", (code, signal) => {
|
||||||
console.log("child process exited");
|
console.log(`child process exited (${code} / ${signal})`);
|
||||||
if (code != 0) {
|
if (code != 0) {
|
||||||
reject(Error(`Unexpected exit code ${code} for '${command}'`));
|
reject(Error(`Unexpected exit code ${code} for '${command}'`));
|
||||||
return;
|
return;
|
||||||
@ -419,6 +418,13 @@ async function pingProc(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ExchangeBankAccount {
|
||||||
|
accountName: string;
|
||||||
|
accountPassword: string;
|
||||||
|
accountPaytoUri: string;
|
||||||
|
wireGatewayApiBaseUrl: string;
|
||||||
|
}
|
||||||
|
|
||||||
export class BankService {
|
export class BankService {
|
||||||
proc: ProcessWrapper | undefined;
|
proc: ProcessWrapper | undefined;
|
||||||
|
|
||||||
@ -454,6 +460,18 @@ export class BankService {
|
|||||||
);
|
);
|
||||||
const cfgFilename = gc.testDir + "/bank.conf";
|
const cfgFilename = gc.testDir + "/bank.conf";
|
||||||
config.write(cfgFilename);
|
config.write(cfgFilename);
|
||||||
|
|
||||||
|
await sh(
|
||||||
|
gc,
|
||||||
|
"taler-bank-manage_django",
|
||||||
|
`taler-bank-manage -c '${cfgFilename}' django migrate`,
|
||||||
|
);
|
||||||
|
await sh(
|
||||||
|
gc,
|
||||||
|
"taler-bank-manage_django",
|
||||||
|
`taler-bank-manage -c '${cfgFilename}' django provide_accounts`,
|
||||||
|
);
|
||||||
|
|
||||||
return new BankService(gc, bc, cfgFilename);
|
return new BankService(gc, bc, cfgFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -463,6 +481,33 @@ export class BankService {
|
|||||||
config.setString("bank", "suggested_exchange_payto", exchangePayto);
|
config.setString("bank", "suggested_exchange_payto", exchangePayto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async createExchangeAccount(
|
||||||
|
accountName: string,
|
||||||
|
password: string,
|
||||||
|
): Promise<ExchangeBankAccount> {
|
||||||
|
await sh(
|
||||||
|
this.globalTestState,
|
||||||
|
"taler-bank-manage_django",
|
||||||
|
`taler-bank-manage -c '${this.configFile}' django add_bank_account ${accountName}`,
|
||||||
|
);
|
||||||
|
await sh(
|
||||||
|
this.globalTestState,
|
||||||
|
"taler-bank-manage_django",
|
||||||
|
`taler-bank-manage -c '${this.configFile}' django changepassword_unsafe ${accountName} ${password}`,
|
||||||
|
);
|
||||||
|
await sh(
|
||||||
|
this.globalTestState,
|
||||||
|
"taler-bank-manage_django",
|
||||||
|
`taler-bank-manage -c '${this.configFile}' django top_up ${accountName} ${this.bankConfig.currency}:100000`,
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
accountName: accountName,
|
||||||
|
accountPassword: password,
|
||||||
|
accountPaytoUri: `payto://x-taler-bank/${accountName}`,
|
||||||
|
wireGatewayApiBaseUrl: `http://localhost:${this.bankConfig.httpPort}/taler-wire-gateway/${accountName}/`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
get port() {
|
get port() {
|
||||||
return this.bankConfig.httpPort;
|
return this.bankConfig.httpPort;
|
||||||
}
|
}
|
||||||
@ -495,10 +540,12 @@ export class BankService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async createRandomBankUser(): Promise<BankUser> {
|
async createRandomBankUser(): Promise<BankUser> {
|
||||||
|
const username =
|
||||||
|
"user-" + talerCrypto.encodeCrock(talerCrypto.getRandomBytes(10));
|
||||||
const bankUser: BankUser = {
|
const bankUser: BankUser = {
|
||||||
username:
|
username,
|
||||||
"user-" + talerCrypto.encodeCrock(talerCrypto.getRandomBytes(10)),
|
|
||||||
password: "pw-" + talerCrypto.encodeCrock(talerCrypto.getRandomBytes(10)),
|
password: "pw-" + talerCrypto.encodeCrock(talerCrypto.getRandomBytes(10)),
|
||||||
|
accountPaytoUri: `payto://x-taler-bank/localhost/${username}`,
|
||||||
};
|
};
|
||||||
await this.createAccount(bankUser.username, bankUser.password);
|
await this.createAccount(bankUser.username, bankUser.password);
|
||||||
return bankUser;
|
return bankUser;
|
||||||
@ -521,6 +568,29 @@ export class BankService {
|
|||||||
return codecForWithdrawalOperationInfo().decode(resp.data);
|
return codecForWithdrawalOperationInfo().decode(resp.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async adminAddIncoming(params: {
|
||||||
|
exchangeBankAccount: ExchangeBankAccount;
|
||||||
|
amount: string;
|
||||||
|
reservePub: string;
|
||||||
|
debitAccountPayto: string;
|
||||||
|
}) {
|
||||||
|
const url = `http://localhost:${this.bankConfig.httpPort}/taler-wire-gateway/${params.exchangeBankAccount.accountName}/admin/add-incoming`;
|
||||||
|
await axios.post(
|
||||||
|
url,
|
||||||
|
{
|
||||||
|
amount: params.amount,
|
||||||
|
reserve_pub: params.reservePub,
|
||||||
|
debit_account: params.debitAccountPayto,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
auth: {
|
||||||
|
username: params.exchangeBankAccount.accountName,
|
||||||
|
password: params.exchangeBankAccount.accountPassword,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async confirmWithdrawalOperation(
|
async confirmWithdrawalOperation(
|
||||||
bankUser: BankUser,
|
bankUser: BankUser,
|
||||||
wopi: WithdrawalOperationInfo,
|
wopi: WithdrawalOperationInfo,
|
||||||
@ -539,6 +609,7 @@ export class BankService {
|
|||||||
export interface BankUser {
|
export interface BankUser {
|
||||||
username: string;
|
username: string;
|
||||||
password: string;
|
password: string;
|
||||||
|
accountPaytoUri: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WithdrawalOperationInfo {
|
export interface WithdrawalOperationInfo {
|
||||||
@ -600,6 +671,14 @@ export class ExchangeService implements ExchangeServiceInterface {
|
|||||||
return new ExchangeService(gc, ec, cfgFilename, keyPair);
|
return new ExchangeService(gc, ec, cfgFilename, keyPair);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async runWirewatchOnce() {
|
||||||
|
await sh(
|
||||||
|
this.globalState,
|
||||||
|
"wirewatch-test",
|
||||||
|
`taler-exchange-wirewatch -c '${this.configFilename}' -t`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
static create(gc: GlobalTestState, e: ExchangeConfig) {
|
static create(gc: GlobalTestState, e: ExchangeConfig) {
|
||||||
const config = new Configuration();
|
const config = new Configuration();
|
||||||
config.setString("taler", "currency", e.currency);
|
config.setString("taler", "currency", e.currency);
|
||||||
@ -686,13 +765,10 @@ export class ExchangeService implements ExchangeServiceInterface {
|
|||||||
return this.exchangeConfig.httpPort;
|
return this.exchangeConfig.httpPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
async setupTestBankAccount(
|
async addBankAccount(
|
||||||
bc: BankService,
|
|
||||||
localName: string,
|
localName: string,
|
||||||
accountName: string,
|
exchangeBankAccount: ExchangeBankAccount,
|
||||||
password: string,
|
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await bc.createAccount(accountName, password);
|
|
||||||
const config = Configuration.load(this.configFilename);
|
const config = Configuration.load(this.configFilename);
|
||||||
config.setString(
|
config.setString(
|
||||||
`exchange-account-${localName}`,
|
`exchange-account-${localName}`,
|
||||||
@ -702,22 +778,30 @@ export class ExchangeService implements ExchangeServiceInterface {
|
|||||||
config.setString(
|
config.setString(
|
||||||
`exchange-account-${localName}`,
|
`exchange-account-${localName}`,
|
||||||
"payto_uri",
|
"payto_uri",
|
||||||
`payto://x-taler-bank/localhost/${accountName}`,
|
exchangeBankAccount.accountPaytoUri,
|
||||||
);
|
);
|
||||||
config.setString(`exchange-account-${localName}`, "enable_credit", "yes");
|
config.setString(`exchange-account-${localName}`, "enable_credit", "yes");
|
||||||
config.setString(`exchange-account-${localName}`, "enable_debit", "yes");
|
config.setString(`exchange-account-${localName}`, "enable_debit", "yes");
|
||||||
config.setString(
|
config.setString(
|
||||||
`exchange-account-${localName}`,
|
`exchange-account-${localName}`,
|
||||||
"wire_gateway_url",
|
"wire_gateway_url",
|
||||||
`http://localhost:${bc.port}/taler-wire-gateway/${accountName}/`,
|
exchangeBankAccount.wireGatewayApiBaseUrl,
|
||||||
);
|
);
|
||||||
config.setString(
|
config.setString(
|
||||||
`exchange-account-${localName}`,
|
`exchange-account-${localName}`,
|
||||||
"wire_gateway_auth_method",
|
"wire_gateway_auth_method",
|
||||||
"basic",
|
"basic",
|
||||||
);
|
);
|
||||||
config.setString(`exchange-account-${localName}`, "username", accountName);
|
config.setString(
|
||||||
config.setString(`exchange-account-${localName}`, "password", password);
|
`exchange-account-${localName}`,
|
||||||
|
"username",
|
||||||
|
exchangeBankAccount.accountName,
|
||||||
|
);
|
||||||
|
config.setString(
|
||||||
|
`exchange-account-${localName}`,
|
||||||
|
"password",
|
||||||
|
exchangeBankAccount.accountPassword,
|
||||||
|
);
|
||||||
config.write(this.configFilename);
|
config.write(this.configFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ import {
|
|||||||
setupDb,
|
setupDb,
|
||||||
BankService,
|
BankService,
|
||||||
defaultCoinConfig,
|
defaultCoinConfig,
|
||||||
|
ExchangeBankAccount,
|
||||||
} from "./harness";
|
} from "./harness";
|
||||||
import { AmountString } from "taler-wallet-core/lib/types/talerTypes";
|
import { AmountString } from "taler-wallet-core/lib/types/talerTypes";
|
||||||
|
|
||||||
@ -39,6 +40,7 @@ export interface SimpleTestEnvironment {
|
|||||||
commonDb: DbInfo;
|
commonDb: DbInfo;
|
||||||
bank: BankService;
|
bank: BankService;
|
||||||
exchange: ExchangeService;
|
exchange: ExchangeService;
|
||||||
|
exchangeBankAccount: ExchangeBankAccount;
|
||||||
merchant: MerchantService;
|
merchant: MerchantService;
|
||||||
wallet: WalletCli;
|
wallet: WalletCli;
|
||||||
}
|
}
|
||||||
@ -73,13 +75,15 @@ export async function createSimpleTestkudosEnvironment(
|
|||||||
database: db.connStr,
|
database: db.connStr,
|
||||||
});
|
});
|
||||||
|
|
||||||
bank.setSuggestedExchange(exchange, "payto://x-taler-bank/MyExchange");
|
const exchangeBankAccount = await bank.createExchangeAccount("MyExchange", "x");
|
||||||
|
exchange.addBankAccount("1", exchangeBankAccount);
|
||||||
|
|
||||||
|
bank.setSuggestedExchange(exchange, exchangeBankAccount.accountPaytoUri);
|
||||||
|
|
||||||
await bank.start();
|
await bank.start();
|
||||||
|
|
||||||
await bank.pingUntilAvailable();
|
await bank.pingUntilAvailable();
|
||||||
|
|
||||||
await exchange.setupTestBankAccount(bank, "1", "MyExchange", "x");
|
|
||||||
exchange.addOfferedCoins(defaultCoinConfig);
|
exchange.addOfferedCoins(defaultCoinConfig);
|
||||||
|
|
||||||
await exchange.start();
|
await exchange.start();
|
||||||
@ -112,6 +116,7 @@ export async function createSimpleTestkudosEnvironment(
|
|||||||
merchant,
|
merchant,
|
||||||
wallet,
|
wallet,
|
||||||
bank,
|
bank,
|
||||||
|
exchangeBankAccount,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,13 +56,15 @@ runTest(async (t: GlobalTestState) => {
|
|||||||
database: db.connStr,
|
database: db.connStr,
|
||||||
});
|
});
|
||||||
|
|
||||||
bank.setSuggestedExchange(exchange, "payto://x-taler-bank/MyExchange");
|
const exchangeBankAccount = await bank.createExchangeAccount("MyExchange", "x");
|
||||||
|
|
||||||
|
bank.setSuggestedExchange(exchange, exchangeBankAccount.accountPaytoUri);
|
||||||
|
|
||||||
await bank.start();
|
await bank.start();
|
||||||
|
|
||||||
await bank.pingUntilAvailable();
|
await bank.pingUntilAvailable();
|
||||||
|
|
||||||
await exchange.setupTestBankAccount(bank, "1", "MyExchange", "x");
|
await exchange.addBankAccount("1", exchangeBankAccount);
|
||||||
exchange.addOfferedCoins(defaultCoinConfig);
|
exchange.addOfferedCoins(defaultCoinConfig);
|
||||||
|
|
||||||
await exchange.start();
|
await exchange.start();
|
||||||
|
@ -51,15 +51,17 @@ async function setupTest(t: GlobalTestState): Promise<{
|
|||||||
database: db.connStr,
|
database: db.connStr,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const exchangeBankAccount = await bank.createExchangeAccount("MyExchange", "x");
|
||||||
|
|
||||||
exchange.addOfferedCoins([coin_ct10, coin_u1]);
|
exchange.addOfferedCoins([coin_ct10, coin_u1]);
|
||||||
|
|
||||||
bank.setSuggestedExchange(exchange, "payto://x-taler-bank/MyExchange");
|
bank.setSuggestedExchange(exchange, exchangeBankAccount.accountPaytoUri);
|
||||||
|
|
||||||
await bank.start();
|
await bank.start();
|
||||||
|
|
||||||
await bank.pingUntilAvailable();
|
await bank.pingUntilAvailable();
|
||||||
|
|
||||||
await exchange.setupTestBankAccount(bank, "1", "MyExchange", "x");
|
await exchange.addBankAccount("1", exchangeBankAccount);
|
||||||
|
|
||||||
await exchange.start();
|
await exchange.start();
|
||||||
await exchange.pingUntilAvailable();
|
await exchange.pingUntilAvailable();
|
||||||
|
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
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 <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports.
|
||||||
|
*/
|
||||||
|
import { runTest, GlobalTestState } from "./harness";
|
||||||
|
import { createSimpleTestkudosEnvironment } from "./helpers";
|
||||||
|
import { walletTypes } from "taler-wallet-core";
|
||||||
|
import { CoreApiResponse } from "taler-wallet-core/lib/walletCoreApiHandler";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run test for basic, bank-integrated withdrawal.
|
||||||
|
*/
|
||||||
|
runTest(async (t: GlobalTestState) => {
|
||||||
|
|
||||||
|
// Set up test environment
|
||||||
|
|
||||||
|
const { wallet, bank, exchange, exchangeBankAccount } = await createSimpleTestkudosEnvironment(t);
|
||||||
|
|
||||||
|
// Create a withdrawal operation
|
||||||
|
|
||||||
|
const user = await bank.createRandomBankUser();
|
||||||
|
|
||||||
|
let wresp: CoreApiResponse;
|
||||||
|
|
||||||
|
wresp = await wallet.apiRequest("addExchange", {
|
||||||
|
exchangeBaseUrl: exchange.baseUrl,
|
||||||
|
});
|
||||||
|
|
||||||
|
t.assertTrue(wresp.type === "response");
|
||||||
|
|
||||||
|
wresp = await wallet.apiRequest("acceptManualWithdrawal", {
|
||||||
|
exchangeBaseUrl: exchange.baseUrl,
|
||||||
|
amount: "TESTKUDOS:10",
|
||||||
|
});
|
||||||
|
|
||||||
|
t.assertTrue(wresp.type === "response");
|
||||||
|
|
||||||
|
const reservePub: string = (wresp.result as any).reservePub;
|
||||||
|
|
||||||
|
await bank.adminAddIncoming({
|
||||||
|
exchangeBankAccount,
|
||||||
|
amount: "TESTKUDOS:10",
|
||||||
|
debitAccountPayto: user.accountPaytoUri,
|
||||||
|
reservePub: reservePub,
|
||||||
|
});
|
||||||
|
|
||||||
|
await exchange.runWirewatchOnce();
|
||||||
|
|
||||||
|
await wallet.runUntilDone();
|
||||||
|
|
||||||
|
// Check balance
|
||||||
|
|
||||||
|
const balApiResp = await wallet.apiRequest("getBalances", {});
|
||||||
|
t.assertTrue(balApiResp.type === "response");
|
||||||
|
const balResp = walletTypes.codecForBalancesResponse().decode(balApiResp.result);
|
||||||
|
t.assertAmountEquals("TESTKUDOS:9.72", balResp.balances[0].available)
|
||||||
|
|
||||||
|
await t.shutdown();
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user