/*
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
*/
/**
* Imports.
*/
import {
encodeCrock,
ExchangeWalletKycStatus,
hashPaytoUri,
j2s,
TalerCorebankApiClient,
} from "@gnu-taler/taler-util";
import {
createSyncCryptoApi,
EddsaKeyPairStrings,
WalletApiOperation,
} from "@gnu-taler/taler-wallet-core";
import { CoinConfig, defaultCoinConfig } from "../harness/denomStructures.js";
import {
BankService,
DbInfo,
ExchangeService,
getTestHarnessPaytoForLabel,
GlobalTestState,
HarnessExchangeBankAccount,
setupDb,
WalletClient,
WalletService,
} from "../harness/harness.js";
import { EnvOptions, postAmlDecisionNoRules } from "../harness/helpers.js";
interface KycTestEnv {
commonDb: DbInfo;
bankClient: TalerCorebankApiClient;
exchange: ExchangeService;
exchangeBankAccount: HarnessExchangeBankAccount;
walletClient: WalletClient;
walletService: WalletService;
amlKeypair: EddsaKeyPairStrings;
}
async function createKycTestkudosEnvironment(
t: GlobalTestState,
coinConfig: CoinConfig[] = defaultCoinConfig.map((x) => x("TESTKUDOS")),
opts: EnvOptions = {},
): Promise {
const db = await setupDb(t);
const bank = await BankService.create(t, {
allowRegistrations: true,
currency: "TESTKUDOS",
database: db.connStr,
httpPort: 8082,
});
const exchange = ExchangeService.create(t, {
name: "testexchange-1",
currency: "TESTKUDOS",
httpPort: 8081,
database: db.connStr,
});
let receiverName = "Exchange";
let exchangeBankUsername = "exchange";
let exchangeBankPassword = "mypw";
let exchangePaytoUri = getTestHarnessPaytoForLabel(exchangeBankUsername);
await exchange.addBankAccount("1", {
accountName: exchangeBankUsername,
accountPassword: exchangeBankPassword,
wireGatewayApiBaseUrl: new URL(
"accounts/exchange/taler-wire-gateway/",
bank.baseUrl,
).href,
accountPaytoUri: exchangePaytoUri,
});
bank.setSuggestedExchange(exchange, exchangePaytoUri);
await bank.start();
await bank.pingUntilAvailable();
const bankClient = new TalerCorebankApiClient(bank.corebankApiBaseUrl, {
auth: {
username: "admin",
password: "adminpw",
},
});
await bankClient.registerAccountExtended({
name: receiverName,
password: exchangeBankPassword,
username: exchangeBankUsername,
is_taler_exchange: true,
payto_uri: exchangePaytoUri,
});
exchange.addCoinConfigList(coinConfig);
await exchange.modifyConfig(async (config) => {
config.setString("exchange", "enable_kyc", "yes");
config.setString("KYC-RULE-R1", "operation_type", "balance");
config.setString("KYC-RULE-R1", "enabled", "yes");
config.setString("KYC-RULE-R1", "exposed", "yes");
config.setString("KYC-RULE-R1", "is_and_combinator", "yes");
config.setString("KYC-RULE-R1", "threshold", "TESTKUDOS:5");
config.setString("KYC-RULE-R1", "timeframe", "forever");
config.setString("KYC-RULE-R1", "next_measures", "M1");
config.setString("KYC-MEASURE-M1", "check_name", "C1");
config.setString("KYC-MEASURE-M1", "context", "{}");
config.setString("KYC-MEASURE-M1", "program", "P1");
config.setString("AML-PROGRAM-P1", "command", "/bin/true");
config.setString("AML-PROGRAM-P1", "enabled", "true");
config.setString("AML-PROGRAM-P1", "description", "this does nothing");
config.setString("AML-PROGRAM-P1", "fallback", "M1");
config.setString("KYC-CHECK-C1", "type", "INFO");
config.setString("KYC-CHECK-C1", "description", "my check!");
config.setString("KYC-CHECK-C1", "fallback", "M1");
});
await exchange.start();
const cryptoApi = createSyncCryptoApi();
const amlKeypair = await cryptoApi.createEddsaKeypair({});
await exchange.enableAmlAccount(amlKeypair.pub, "Alice");
const walletService = new WalletService(t, {
name: "wallet",
useInMemoryDb: true,
});
await walletService.start();
await walletService.pingUntilAvailable();
const walletClient = new WalletClient({
name: "wallet",
unixPath: walletService.socketPath,
onNotification(n) {
console.log("got notification", n);
},
});
await walletClient.connect();
await walletClient.client.call(WalletApiOperation.InitWallet, {
config: {
testing: {
skipDefaults: true,
},
},
});
console.log("setup done!");
return {
commonDb: db,
exchange,
walletClient,
walletService,
bankClient,
exchangeBankAccount: {
accountName: "",
accountPassword: "",
accountPaytoUri: "",
wireGatewayApiBaseUrl: "",
},
amlKeypair,
};
}
export async function runKycExchangeWalletTest(t: GlobalTestState) {
// Set up test environment
const { walletClient, exchange, amlKeypair } =
await createKycTestkudosEnvironment(t);
await walletClient.call(WalletApiOperation.AddExchange, {
exchangeBaseUrl: exchange.baseUrl,
});
await walletClient.call(WalletApiOperation.StartExchangeWalletKyc, {
amount: "TESTKUDOS:20",
exchangeBaseUrl: exchange.baseUrl,
});
await walletClient.call(WalletApiOperation.TestingWaitExchangeWalletKyc, {
amount: "TESTKUDOS:20",
exchangeBaseUrl: exchange.baseUrl,
passed: false,
});
const exchangeEntry = await walletClient.call(
WalletApiOperation.GetExchangeEntryByUrl,
{
exchangeBaseUrl: exchange.baseUrl,
},
);
console.log(j2s(exchangeEntry));
t.assertDeepEqual(
exchangeEntry.walletKycStatus,
ExchangeWalletKycStatus.Legi,
);
const kycReservePub = exchangeEntry.walletKycReservePub;
t.assertTrue(!!kycReservePub);
// FIXME: Create/user helper function for this!
const hPayto = hashPaytoUri(
`payto://taler-reserve-http/localhost:${exchange.port}/${kycReservePub}`,
);
console.log(`hPayto: ${hPayto}`);
await postAmlDecisionNoRules(t, {
amlPriv: amlKeypair.priv,
amlPub: amlKeypair.pub,
exchangeBaseUrl: exchange.baseUrl,
paytoHash: encodeCrock(hPayto),
});
await walletClient.call(WalletApiOperation.TestingWaitExchangeWalletKyc, {
amount: "TESTKUDOS:20",
exchangeBaseUrl: exchange.baseUrl,
passed: true,
});
}
runKycExchangeWalletTest.suites = ["wallet"];