CONVERSION-TESTING.md (7619B)
1 # Test currency conversion without a fiat bank 2 3 This runbook tests a complete cash-in and cash-out cycle while the conversion 4 account is not connected to a real bank. It uses a command-line Taler wallet 5 and the LibEuFin Nexus testing commands. No EBICS enrollment or payment 6 submission is needed. 7 8 Only use this mode for a disposable testing deployment. Enabling conversion 9 records the fiat currency, IBAN, BIC, and account name as part of the 10 deployment identity. The normal playbook will reject later changes to those 11 values or an attempt to disable conversion. 12 13 ## Configure and deploy test mode 14 15 Set these values in the target's private inventory file: 16 17 ```yaml 18 regional_currency_testing_deployment: true 19 regional_currency_enable_conversion: true 20 regional_currency_conversion_test_mode: true 21 regional_currency_fiat_currency: CHF 22 regional_currency_fiat_bank_name: Synthetic CHF Test Bank 23 regional_currency_fiat_account_iban: CH8615624QG38ANY0UVER 24 regional_currency_fiat_account_bic: TSTRCHZZXXX 25 regional_currency_fiat_account_name: FLODOS Conversion Test 26 regional_currency_enable_nexus_services: false 27 ``` 28 29 Generate a fresh valid test IBAN instead of copying the example IBAN: 30 31 ```console 32 $ libeufin-nexus testing iban gen --country CH 33 CH... 34 ``` 35 36 Conversion test mode is valid only when both testing and conversion are 37 enabled. It rejects an inventory that enables the Nexus services and configures 38 Nexus to require manual acknowledgement before an initiated payment can be 39 submitted. 40 41 Deploy only the intended host: 42 43 ```console 44 $ ansible -i inventory regio -m ping 45 $ ansible-playbook -i inventory site.yml --limit regio 46 ``` 47 48 Verify the public configuration from the operator machine: 49 50 ```console 51 $ curl -fsS https://bank.regio.taler.net/config | jq '{currency, allow_conversion}' 52 $ curl -fsS https://bank.regio.taler.net/conversion-info/config | 53 jq '{regional_currency, fiat_currency, conversion_rate}' 54 $ curl -fsS https://exchange.regio.taler.net/keys | 55 jq '[.accounts[] | {payto_uri, conversion_url, bank_label, priority}]' 56 ``` 57 58 The bank must report FLODOS conversion enabled with CHF as the fiat currency. 59 The exchange must advertise a priority-10 IBAN account whose conversion URL is 60 `https://bank.regio.taler.net/conversion-info/`. 61 62 On the managed host, verify that no EBICS worker is running: 63 64 ```console 65 # systemctl is-active libeufin-nexus.target \ 66 libeufin-nexus-ebics-fetch.service \ 67 libeufin-nexus-ebics-submit.service 68 inactive 69 inactive 70 inactive 71 ``` 72 73 ## Simulate a conversion withdrawal 74 75 On the operator machine, create a temporary wallet and start a manual 76 withdrawal. Keep this directory until the whole test has finished: 77 78 ```console 79 $ REGIO_TEST_DIR=$(mktemp -d) 80 $ REGIO_WALLET_DB="$REGIO_TEST_DIR/wallet.sqlite3" 81 $ taler-wallet-cli --wallet-db "$REGIO_WALLET_DB" \ 82 withdraw \ 83 --exchange https://exchange.regio.taler.net/ \ 84 --amount FLODOS:10 | tee "$REGIO_TEST_DIR/withdraw.out" 85 $ REGIO_TX_ID=$(sed -n 's/^transaction //p' "$REGIO_TEST_DIR/withdraw.out") 86 $ taler-wallet-cli --wallet-db "$REGIO_WALLET_DB" \ 87 transactions show "$REGIO_TX_ID" > "$REGIO_TEST_DIR/withdraw.json" 88 $ REGIO_CREDIT_PAYTO=$(jq -r ' 89 [.withdrawalDetails.exchangeCreditAccountDetails[] 90 | select(.transferAmount | startswith("CHF:")) 91 | .transferOptions[] 92 | select(.type == "payto") 93 | .paytoUri][0] 94 ' "$REGIO_TEST_DIR/withdraw.json") 95 $ printf '%s\n' "$REGIO_CREDIT_PAYTO" 96 ``` 97 98 The selected URI includes the synthetic conversion IBAN, the CHF amount, and 99 the reserve public key as its transfer subject. Copy the complete URI to the 100 managed host and inject it exactly as produced by the wallet: 101 102 ```console 103 # REGIO_CREDIT_PAYTO='payto://iban/...?...' 104 # sudo -u libeufin-nexus \ 105 libeufin-nexus testing fake-incoming \ 106 -c /etc/libeufin/libeufin-nexus.conf \ 107 --credit-payto "$REGIO_CREDIT_PAYTO" 108 # sudo -u libeufin-nexus \ 109 libeufin-nexus testing list incoming \ 110 -c /etc/libeufin/libeufin-nexus.conf 111 ``` 112 113 Back on the operator machine, wait for the exchange and wallet to process the 114 reserve, then check the balance: 115 116 ```console 117 $ taler-wallet-cli --wallet-db "$REGIO_WALLET_DB" \ 118 transactions wait "$REGIO_TX_ID" --state final --timeout 2m 119 $ taler-wallet-cli --wallet-db "$REGIO_WALLET_DB" balance --pretty 120 ``` 121 122 With the one-to-one rate and zero fees, the wallet balance must be 123 `FLODOS:10`. 124 125 ## Deposit and cash out 126 127 Create a dedicated zero-debt bank account on the managed host. Its cash-out 128 IBAN must be different from the synthetic conversion account: 129 130 ```console 131 # REGIO_TEST_USERNAME="conversion-test-$(date -u +%Y%m%d%H%M%S)" 132 # REGIO_TEST_PASSWORD=$(uuidgen) 133 # REGIO_CASHOUT_IBAN=$(libeufin-nexus testing iban gen --country CH) 134 # REGIO_ACCOUNT_PAYTO=$(sudo -u libeufin-bank \ 135 libeufin-bank create-account \ 136 --username "$REGIO_TEST_USERNAME" \ 137 --password "$REGIO_TEST_PASSWORD" \ 138 --name 'Conversion Test Customer' \ 139 --cashout_payto_uri \ 140 "payto://iban/TSTRCHZZXXX/$REGIO_CASHOUT_IBAN" \ 141 --debit_threshold FLODOS:0) 142 # printf 'username: %s\naccount: %s\ncash-out IBAN: %s\n' \ 143 "$REGIO_TEST_USERNAME" "$REGIO_ACCOUNT_PAYTO" "$REGIO_CASHOUT_IBAN" 144 ``` 145 146 Copy `REGIO_ACCOUNT_PAYTO` to the operator machine and deposit the complete 147 wallet balance into it: 148 149 ```console 150 $ REGIO_ACCOUNT_PAYTO='payto://x-taler-bank/...' 151 $ taler-wallet-cli --wallet-db "$REGIO_WALLET_DB" \ 152 deposit FLODOS:10 "$REGIO_ACCOUNT_PAYTO" --timeout 2m 153 ``` 154 155 On the managed host, create a one-hour API token and wait until the account 156 shows a `FLODOS:10` credit balance: 157 158 ```console 159 # REGIO_TEST_TOKEN=$(sudo -u libeufin-bank \ 160 libeufin-bank create-token \ 161 --username "$REGIO_TEST_USERNAME" \ 162 --scope readwrite \ 163 --duration 3600000000 \ 164 --description 'conversion test') 165 # curl -fsS \ 166 -H "Authorization: Bearer $REGIO_TEST_TOKEN" \ 167 "https://bank.regio.taler.net/accounts/$REGIO_TEST_USERNAME" | jq .balance 168 ``` 169 170 Ask the bank for the current cash-out quote, then submit exactly that debit and 171 credit amount with a fresh idempotency key: 172 173 ```console 174 # REGIO_QUOTE=$(curl -fsS \ 175 "https://bank.regio.taler.net/conversion-info/cashout-rate?amount_debit=FLODOS:10") 176 # REGIO_CASHOUT_CREDIT=$(printf '%s' "$REGIO_QUOTE" | jq -r .amount_credit) 177 # REGIO_REQUEST_UID=$(head -c 32 /dev/urandom | gnunet-base32) 178 # jq -n \ 179 --arg uid "$REGIO_REQUEST_UID" \ 180 --arg debit 'FLODOS:10' \ 181 --arg credit "$REGIO_CASHOUT_CREDIT" \ 182 --arg subject "regio conversion test $REGIO_TEST_USERNAME" \ 183 '{request_uid: $uid, amount_debit: $debit, 184 amount_credit: $credit, subject: $subject}' | 185 curl -fsS \ 186 -H "Authorization: Bearer $REGIO_TEST_TOKEN" \ 187 -H 'Content-Type: application/json' \ 188 --data-binary @- \ 189 "https://bank.regio.taler.net/accounts/$REGIO_TEST_USERNAME/cashouts" | 190 jq . 191 ``` 192 193 Verify that the bank balance has returned to zero and that Nexus contains the 194 CHF payment it would send to the fiat bank: 195 196 ```console 197 # curl -fsS \ 198 -H "Authorization: Bearer $REGIO_TEST_TOKEN" \ 199 "https://bank.regio.taler.net/accounts/$REGIO_TEST_USERNAME" | jq .balance 200 # sudo -u libeufin-nexus \ 201 libeufin-nexus testing list initiated \ 202 -c /etc/libeufin/libeufin-nexus.conf 203 ``` 204 205 The initiated entry must show `CHF:10`, the generated cash-out IBAN, and the 206 unique test subject. This queued entry is the proof of the outgoing cash-out; 207 there is deliberately no matching outgoing bank statement in simulated mode. 208 209 Do not run `libeufin-nexus ebics-submit` or manually acknowledge the transfer. 210 Those operations belong to a deployment connected to a real fiat bank.