···
1
+
import ../../make-test-python.nix (
4
+
cfgNodes = pkgs.callPackage ../common/nodes.nix { inherit lib; };
7
+
# NOTE: The Nexus conversion subtest requires internet access, so to run it
8
+
# you must run the test with:
9
+
# - nix run .#nixosTests.taler.basic.driver
11
+
# - nix run .#nixosTests.taler.basic.driverInteractive
14
+
name = "GNU Taler Basic Test";
16
+
maintainers = lib.teams.ngi.members;
19
+
# Taler components virtual-machine nodes
21
+
inherit (cfgNodes.nodes)
29
+
# TODO: make tests for each component?
33
+
cfgScripts = pkgs.callPackage ../common/scripts.nix { inherit lib pkgs nodes; };
35
+
inherit (cfgNodes) CURRENCY FIAT_CURRENCY;
36
+
inherit (cfgScripts) commonScripts;
38
+
bankConfig = nodes.bank.config.environment.etc."libeufin/libeufin.conf".source;
39
+
bankSettings = nodes.bank.services.libeufin.settings.libeufin-bank;
40
+
nexusSettings = nodes.bank.services.libeufin.nexus.settings;
42
+
# Bank admin account credentials
49
+
exchangeAccount = ../conf/exchange-account.json;
56
+
# import common scripts
60
+
# NOTE: start components up individually so they don't conflict before their setup is done
63
+
bank.wait_for_open_port(8082)
65
+
with subtest("Set up Libeufin bank"):
66
+
# Modify admin account password, increase debit threshold
67
+
systemd_run(bank, 'libeufin-bank passwd -c "${bankConfig}" "${AUSER}" "${APASS}"', "libeufin-bank")
68
+
systemd_run(bank, 'libeufin-bank edit-account -c ${bankConfig} --debit_threshold="${bankSettings.CURRENCY}:1000000" ${AUSER}', "libeufin-bank")
70
+
# NOTE: the exchange is enabled before the bank starts using the `initialAccounts` option
71
+
# TODO: just use that option instead of this?
72
+
with subtest("Register bank accounts"):
73
+
# username, password, name
74
+
register_bank_account("testUser", "testUser", "User")
75
+
register_bank_account("merchant", "merchant", "Merchant")
79
+
exchange.wait_for_open_port(8081)
82
+
with subtest("Set up exchange"):
83
+
exchange.wait_until_succeeds("taler-exchange-offline download sign upload")
84
+
# Enable exchange wire account
85
+
exchange.succeed('taler-exchange-offline upload < ${exchangeAccount}')
87
+
# NOTE: cannot deposit coins/pay merchant if wire fees are not set up
88
+
exchange.succeed('taler-exchange-offline wire-fee now x-taler-bank "${CURRENCY}:0" "${CURRENCY}:0" upload')
89
+
exchange.succeed('taler-exchange-offline global-fee now "${CURRENCY}:0" "${CURRENCY}:0" "${CURRENCY}:0" 1h 6a 0 upload')
92
+
# Verify that exchange keys exist
93
+
bank.succeed("curl -s http://exchange:8081/keys")
97
+
merchant.wait_for_open_port(8083)
100
+
with subtest("Set up merchant"):
101
+
# Create default instance (similar to admin)
102
+
succeed(merchant, [
104
+
"-H 'Authorization: Bearer secret-token:super_secret'",
107
+
"auth": { "method": "external" },
110
+
"user_type": "business",
112
+
"jurisdiction": {},
113
+
"use_stefan": true,
114
+
"default_wire_transfer_delay": { "d_us": 3600000000 },
115
+
"default_pay_delay": { "d_us": 3600000000 }
118
+
"-sSfL 'http://merchant:8083/management/instances'"
120
+
# Register bank account address
121
+
succeed(merchant, [
123
+
"-H 'Content-Type: application/json'",
126
+
"payto_uri": "payto://x-taler-bank/bank:8082/merchant?receiver-name=Merchant",
127
+
"credit_facade_url": "http://bank:8082/accounts/merchant/taler-revenue/",
128
+
"credit_facade_credentials":{"type":"basic","username":"merchant","password":"merchant"}
131
+
"-sSfL 'http://merchant:8083/private/accounts'"
133
+
# Register a new product to be ordered
134
+
succeed(merchant, [
136
+
"-H 'Content-Type: application/json'",
140
+
"description": "Product with id 1 and price 1",
141
+
"price": "${CURRENCY}:1",
143
+
"unit": "packages",
144
+
"next_restock": { "t_s": "never" }
147
+
"-sSfL 'http://merchant:8083/private/products'"
151
+
client.succeed("curl -s http://exchange:8081/")
154
+
# Make a withdrawal from the CLI wallet
155
+
with subtest("Make a withdrawal from the CLI wallet"):
156
+
balanceWanted = "${CURRENCY}:10"
158
+
# Register exchange
159
+
with subtest("Register exchange"):
160
+
wallet_cli("exchanges add http://exchange:8081/")
161
+
wallet_cli("exchanges accept-tos http://exchange:8081/")
163
+
# Request withdrawal from the bank
164
+
withdrawal = json.loads(
167
+
"-u ${TUSER}:${TPASS}",
168
+
"-H 'Content-Type: application/json'",
169
+
f"""--data '{{"amount": "{balanceWanted}"}}'""", # double brackets escapes them
170
+
"-sSfL 'http://bank:8082/accounts/${TUSER}/withdrawals'"
174
+
# Accept & confirm withdrawal
175
+
with subtest("Accept & confirm withdrawal"):
176
+
wallet_cli(f"withdraw accept-uri {withdrawal["taler_withdraw_uri"]} --exchange http://exchange:8081/")
179
+
"-u ${TUSER}:${TPASS}",
180
+
"-H 'Content-Type: application/json'",
181
+
f"-sSfL 'http://bank:8082/accounts/${TUSER}/withdrawals/{withdrawal["withdrawal_id"]}/confirm'"
184
+
# Process transactions
185
+
wallet_cli("run-until-done")
187
+
verify_balance(balanceWanted)
190
+
with subtest("Pay for an order"):
191
+
balanceWanted = "${CURRENCY}:9" # after paying
193
+
# Create an order to be paid
194
+
response = json.loads(
195
+
succeed(merchant, [
197
+
"-H 'Content-Type: application/json'",
200
+
"order": { "amount": "${CURRENCY}:1", "summary": "Test Order" },
201
+
"inventory_products": [{ "product_id": "1", "quantity": 1 }]
204
+
"-sSfL 'http://merchant:8083/private/orders'"
207
+
order_id = response["order_id"]
208
+
token = response["token"]
210
+
# Get order pay URI
211
+
response = json.loads(
212
+
succeed(merchant, [
214
+
f"http://merchant:8083/private/orders/{order_id}"
217
+
wallet_cli("run-until-done")
219
+
# Process transaction
220
+
wallet_cli(f"""handle-uri -y '{response["taler_pay_uri"]}'""")
221
+
wallet_cli("run-until-done")
223
+
verify_balance(balanceWanted)
225
+
# Only run Nexus conversion test if ebics server is available
226
+
(status, out) = bank.execute('curl -sSfL "${nexusSettings.nexus-ebics.HOST_BASE_URL}"')
229
+
bank.log("Can't connect to ebics server. Skipping Nexus conversion subtest.")
231
+
with subtest("Libeufin Nexus currency conversion"):
232
+
regionalWanted = "20"
234
+
# Setup Nexus ebics keys
235
+
systemd_run(bank, "libeufin-nexus ebics-setup -L debug -c /etc/libeufin/libeufin.conf", "libeufin-nexus")
237
+
# Set currency conversion rates (1:1)
240
+
"-H 'Content-Type: application/json'",
241
+
"-u ${AUSER}:${APASS}",
244
+
"cashin_ratio": "1",
245
+
"cashin_fee": "${CURRENCY}:0",
246
+
"cashin_tiny_amount": "${CURRENCY}:0.01",
247
+
"cashin_rounding_mode": "nearest",
248
+
"cashin_min_amount": "${FIAT_CURRENCY}:1",
249
+
"cashout_ratio": "1",
250
+
"cashout_fee": "${FIAT_CURRENCY}:0",
251
+
"cashout_tiny_amount": "${FIAT_CURRENCY}:0.01",
252
+
"cashout_rounding_mode": "nearest",
253
+
"cashout_min_amount": "${CURRENCY}:1"
256
+
"-sSfL 'http://bank:8082/conversion-info/conversion-rate'"
259
+
# Make fake transaction (we only need reservePub)
260
+
response = wallet_cli("""api 'acceptManualWithdrawal' '{ "exchangeBaseUrl":"http://exchange:8081/", "amount":"${CURRENCY}:5" }'""")
261
+
reservePub = json.loads(response)["result"]["reservePub"]
263
+
# Convert fiat currency to regional
264
+
systemd_run(bank, f"""libeufin-nexus testing fake-incoming -c ${bankConfig} --amount="${FIAT_CURRENCY}:{regionalWanted}" --subject="{reservePub}" "payto://iban/CH4740123RW4167362694" """, "libeufin-nexus")
265
+
wallet_cli("run-until-done")
267
+
verify_conversion(regionalWanted)