This tutorial shows how to setup LibEuFin to act as the bank of a local currency. The main features include the registration and removal of user accounts (only) by the admin, and the possibility to convert the local currency into fiat (a.k.a. cashing out).
The banking capabilities are offered by a LibEuFin service called Sandbox. In particular, the tutorial relies on the Circuit API. More information about libEufin can be found in the How-To page.
The following sections show how to install and launch Sandbox either from sources, or with Docker.
First build LibEuFin.
If the installation succeeded, configure Sandbox with the following command.
$ export LIBEUFIN_SANDBOX_DB_CONNECTION=jdbc:sqlite:/tmp/libeufin.sqlite3
$ libeufin-sandbox config --currency NB --without-registrations default
Note
The --without-registrations
option allows only the administrator
to add new accounts. Without this option, other APIs may offer
unrestricted registrations.
If the configuration step succeeded, Sandbox should be ready to serve the bank for a currency named NB.
In following step, we launch Sandbox by setting the administrator
password as secret
.
Note
The following command launches Sandbox so that it writes TANs on the filesystem to ease the cash-out operations without relying on an actual e-mail or SMS provider.
$ export LIBEUFIN_SANDBOX_ADMIN_PASSWORD=secret
$ libeufin-sandbox serve --port 5016
If Sandbox is running, jump to this part.
First, clone the deployment repository:
$ git clone git://git.taler.net/deployment
Then navigate to the Docker image location:
$ cd deployment/nlnet/task1
Now build the image with the following command.
$ docker build -t nlnet .
If the build step went well, the following command should suffice to start Sandbox and NGINX, by mapping the host’s 8080 port to the container’s 80.
$ export LIBEUFIN_EXPOSED_PORT=8080
$ docker run \
-e LIBEUFIN_EXPOSED_PORT=$LIBEUFIN_EXPOSED_PORT \
-p $LIBEUFIN_EXPOSED_PORT:80 \
-it nlnet
The previous command uses a default admin password of ‘admin’. Do CHANGE the admin password in a production scenario. The following command shows how to start the services with custom values.
Note
Start the services this way to provide the environment suitable for this tutorial.
$ export MY_ADMIN_PASSWORD=secret
$ export LIBEUFIN_EXPOSED_PORT=8080
$ docker run \
-e LIBEUFIN_SANDBOX_ADMIN_PASSWORD=$MY_ADMIN_PASSWORD \
-e CURRENCY=NB \
-e LIBEUFIN_EXPOSED_PORT=$LIBEUFIN_EXPOSED_PORT \
-v libeufin_data:/libeufin-data \
-v /tmp:/tmp \
-p $LIBEUFIN_EXPOSED_PORT:80 \
-p 5016:5016 \
-it nlnet
In the example above, Docker:
/tmp
to the host’s, to let
the reader obtain the file TAN in the same way the
source-based installation does.By success, Web browsers get the UI by visiting http://localhost:8080
The following command shows how to delete the database, by deleting its volume.
$ docker volume rm libeufin_data
Note: the removal might fail because the exited containers are seen as still using the container. Please refer to the Docker documentation for further information.
Sandbox should now be reachable on the port 5016. Check it with:
$ curl http://localhost:5016
If Sandbox is correctly running, it should respond with a greeting message. At this point, the administrator can add a new merchant to the bank with the following command.
Note
Consult this document, to learn all the CLI commands that address the (Circuit) API used in this tutorial.
export LIBEUFIN_SANDBOX_USERNAME=admin
export LIBEUFIN_SANDBOX_PASSWORD=secret
export LIBEUFIN_SANDBOX_URL=http://localhost:5016/
export LIBEUFIN_NEW_CIRCUIT_ACCOUNT_PASSWORD=shop-secret
libeufin-cli \
sandbox \
demobank \
circuit-register \
--name "Circuit Shop" \
--username circuit-shop \
--cashout-address payto://iban/CH463312 \
--internal-iban INT940993
If the previous step succeeded, the merchant should have access to their bank account with the circuit-shop username and shop-secret password.
Check it by asking the merchant balance with the following command. The two environment variables LIBEUFIN_SANDBOX_USERNAME and LIBEUFIN_SANDBOX_PASSWORD instruct the CLI to authenticate as the merchant.
export LIBEUFIN_SANDBOX_USERNAME=circuit-shop
export LIBEUFIN_SANDBOX_PASSWORD=shop-secret
libeufin-cli sandbox demobank info --bank-account circuit-shop
The expected response looks like the following one:
{
"balance" : {
"amount" : "NB:0",
"credit_debit_indicator" : "credit"
},
"paytoUri" : "payto://iban/SANDBOXX/INT940993?receiver-name=Circuit+Shop",
"iban" : "INT940993"
}
In the following example, the merchant creates a cash-out operation,
trying to convert 1 NB back to the fiat currency. The --amount-debit
option takes the amount that the merchant wants to be debited
in their local currency bank account, whereas the --amount-credit
option is the calculation of the conversion rates as expected
by the merchant. The two values will be checked by the bank along
this request, to make sure that both parties agree.
Note
The current version has a fixed 0.95 conversion rate for cashing out. Future version will make this value configurable.
libeufin-cli \
sandbox \
demobank \
circuit-cashout \
--amount-debit=NB:1 \
--amount-credit=CHF:0.95 \
--tan-channel=file
If the previous command succeeded, it returned a JSON looking like the following, although most likely having a different UUID.
{
"uuid" : "de12389b-e477-4a0c-829e-f779c1cfb3a0"
}
The uuid represents the cash-out operation being just created and waiting to be confirmed with a TAN.
Note
The current version provides only the local currency side of such operation. In other words, the merchant can now only see a deduction on their local currency bank account but no incoming payment in their fiat bank account. Future versions will implement this.
Confirm now the cash-out operation by sending to the
bank the TAN found in the file /tmp/libeufin-cashout-tan.txt
.
Assuming that the TAN for it is WXYZ
, the next command will confirm
it to the bank (please, use your UUID).
libeufin-cli \
sandbox demobank circuit-cashout-confirm \
--uuid de12389b-e477-4a0c-829e-f779c1cfb3a0 \
--tan WXYZ
Check now that the cash-out operation appears as a outgoing transaction for the merchant:
libeufin-cli \
sandbox demobank list-transactions \
--bank-account circuit-shop
The expected output should contain one line like the following. That witnesses that the cash-out was correctly confirmed and scheduled to be transferred to the fiat account.
"subject" : "Cash-out of NB:1 to CHF:0.95"
The next commands show how to delete one account from the local currency circuit. For the deletion to succeed, the account must have a balance of zero NB. Because of the cash-out operation, the merchant has now -1 NB to their account, therefore the deletion will fail. Check it, as the administrator, with the following command
export LIBEUFIN_SANDBOX_USERNAME=admin
export LIBEUFIN_SANDBOX_PASSWORD=secret
libeufin-cli \
sandbox demobank \
circuit-delete-account --username circuit-shop
The expected output is:
Unexpected response status: 412
Response: {
"error" : {
"type" : "sandbox-error",
"description" : "Account circuit-shop doesn't have zero balance. Won't delete it"
}
}
The bank may now award 1 NB to the merchant to bring their balance to zero and finally delete the account. With the following command, the administrator awards 1 NB to the merchant.
libeufin-cli \
sandbox demobank new-transaction \
--bank-account admin \
--payto-with-subject "payto://iban/SANDBOXX/INT940993?message=bring-to-zero" \
--amount NB:1
Check if the balance returned to zero with this command, and try again to delete the account like already done
Now the deletion command should have succeeded! Try to ask the balance again, and expect one error like the following:
{
"error" : {
"type" : "util-error",
"description" : "Customer 'circuit-shop' not found"
}
}
Note
Every Circuit API endpoint is addressed by a CLI subcommand
whose name starts with circuit-
. The following command
shows them.
libeufin-cli sandbox demobank | grep circuit
SMS and E-mail TANs get sent via commands that
are invoked by the Sandbox. Sandbox learns about those commands
via optional parameters to the serve
command.
Note
Future versions will allow setting the external commands via the configuration; follow #7527.
Hence, starting Sandbox as shown in the following commands is the only requirement to use the aforementioned TAN channels.
For the SMS TAN:
libeufin-sandbox serve --sms-tan sms_provider_command
Alternatively, for the e-mail TAN:
libeufin-sandbox serve --email-tan email_provider_command
Both commands will be passed the TAN to STDIN and the target phone number / e-mail address as their first command line argument.
Note
The way the invoked commands interact with their providers is out of the Sandbox scope.
Finally, Libeufin ships two TAN commands as example. The e-mail
command relies on GNU mail and the SMS command
on the service offered by telesign.com. Check contrib/libeufin-tan-sms.sh
and contrib/libeufin-tan-email.sh
in the Libeufin repository.