summaryrefslogtreecommitdiff
path: root/regional-currency
diff options
context:
space:
mode:
authorMS <ms@taler.net>2023-12-11 19:57:47 +0100
committerMS <ms@taler.net>2023-12-11 19:57:47 +0100
commit579d93541d44ef63ef036c565d7626c76cd80d8b (patch)
treeefb6cf61bfdfc10a1e861a23e4cf47934f80ff3c /regional-currency
parent29918880f335aff089a91b52716e24cea1199c9d (diff)
downloaddeployment-579d93541d44ef63ef036c565d7626c76cd80d8b.tar.gz
deployment-579d93541d44ef63ef036c565d7626c76cd80d8b.tar.bz2
deployment-579d93541d44ef63ef036c565d7626c76cd80d8b.zip
regional setup: rename to address any currency
Diffstat (limited to 'regional-currency')
-rw-r--r--regional-currency/.gitignore3
-rw-r--r--regional-currency/.shellcheckrc1
-rw-r--r--regional-currency/README2
-rwxr-xr-xregional-currency/config_libeufin.sh7
-rwxr-xr-xregional-currency/config_libeufin_bank.sh128
-rwxr-xr-xregional-currency/config_libeufin_nexus.sh19
-rwxr-xr-xregional-currency/config_nginx.sh38
-rwxr-xr-xregional-currency/functions.sh87
-rw-r--r--regional-currency/incoming_template.xml127
-rwxr-xr-xregional-currency/install_packages.sh60
-rwxr-xr-xregional-currency/main.sh86
-rw-r--r--regional-currency/nginx-conf/backend.taler-nginx.conf14
-rw-r--r--regional-currency/nginx-conf/bank.taler-nginx.conf18
-rw-r--r--regional-currency/nginx-conf/exchange.taler-nginx.conf12
-rwxr-xr-xregional-currency/setup-exchange.sh228
-rwxr-xr-xregional-currency/setup-merchant.sh13
-rwxr-xr-xregional-currency/transfer.sh24
-rw-r--r--regional-currency/vagrant/.gitignore1
-rw-r--r--regional-currency/vagrant/README2
-rw-r--r--regional-currency/vagrant/Vagrantfile77
-rwxr-xr-xregional-currency/withdraw.sh39
21 files changed, 986 insertions, 0 deletions
diff --git a/regional-currency/.gitignore b/regional-currency/.gitignore
new file mode 100644
index 0000000..4492389
--- /dev/null
+++ b/regional-currency/.gitignore
@@ -0,0 +1,3 @@
+nexus.log
+sandbox.log
+config/
diff --git a/regional-currency/.shellcheckrc b/regional-currency/.shellcheckrc
new file mode 100644
index 0000000..e170f39
--- /dev/null
+++ b/regional-currency/.shellcheckrc
@@ -0,0 +1 @@
+disable=SC2018,SC2019
diff --git a/regional-currency/README b/regional-currency/README
new file mode 100644
index 0000000..599336a
--- /dev/null
+++ b/regional-currency/README
@@ -0,0 +1,2 @@
+Refer to the following document:
+https://docs.taler.net/libeufin/regional-manual.html#guided-basic-setup
diff --git a/regional-currency/config_libeufin.sh b/regional-currency/config_libeufin.sh
new file mode 100755
index 0000000..ee9e707
--- /dev/null
+++ b/regional-currency/config_libeufin.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+set -eu
+
+libeufin-dbconfig
+./config_libeufin_nexus.sh
+./config_libeufin_bank.sh
diff --git a/regional-currency/config_libeufin_bank.sh b/regional-currency/config_libeufin_bank.sh
new file mode 100755
index 0000000..5a32844
--- /dev/null
+++ b/regional-currency/config_libeufin_bank.sh
@@ -0,0 +1,128 @@
+#!/bin/bash
+# This file is in the public domain.
+#
+# This script configure and launches libeufin-bank.
+# The setup provides the admin account at the bank, and
+# another account for the exchange at the bank.
+#
+# The environment must provide the following variables:
+# - BANK_ADMIN_PASSWORD: password of the Netzbon administrator.
+# - BANK_EXCHANGE_PASSWORD: password of the exchange
+# bank account hosted at Sandbox. The related
+# username is: exchange-at-sandbox
+# - BANK_NAME: human-readable name for the bank
+# - DOMAIN_NAME: DNS domain name to use for the setup
+# - ENABLE_TLS (http or https?)
+#
+# OUTPUTS:
+#
+# EXCHANGE_PAYTO -- payto-URI of the exchange
+# EXCHANGE_WIRE_GATEWAY_URL -- URL of the wire gateway for the exchange
+
+set -eu
+
+source functions.sh
+source config/user.conf
+source config/internal.conf
+
+if test -z "${BANK_NAME:-}"; then
+ say "Error: config/user.conf does not specify BANK_NAME"
+ exit 1
+fi
+if test -z "${DOMAIN_NAME:-}"; then
+ say "Error: config/user.conf does not specify DOMAIN_NAME"
+ exit 1
+fi
+if test -z "${BANK_ADMIN_PASSWORD:-}"; then
+ say "Error: config/user.conf does not specify BANK_ADMIN_PASSWORD"
+ exit 1
+fi
+if test -z "${BANK_EXCHANGE_PASSWORD:-}"; then
+ say "Error: config/user.conf does not specify BANK_EXCHANGE_PASSWORD"
+ exit 1
+fi
+
+say "Configure the bank with ${CURRENCY}..."
+
+cat <<EOF > /etc/libeufin/libeufin-bank.conf
+[libeufin-bank]
+CURRENCY=${CURRENCY}
+DEFAULT_EXCHANGE=${PROTO}://exchange.${DOMAIN_NAME}
+SERVE=tcp
+PORT=${BANK_PORT}
+ALLOW_CONVERSION=yes
+FIAT_CURRENCY=${FIAT_CURRENCY}
+TAN_SMS=libeufin-tan-sms.sh
+TAN_EMAIL=libeufin-tan-email.sh
+ALLOW_EDIT_CASHOUT_PAYTO_URI=yes
+
+[CURRENCY-NETZBON]
+enabled=yes
+name=NetzBon
+code=NETZBON
+fractional_input_digits=2
+fractional_normal_digits=2
+fractional_trailing_zero_digits=2
+alt_unit_names={"0":"NETZBON"}
+
+EOF
+
+# FIXME: include this in the bank _and_ make sure it gets loaded
+
+say "Setting up libeufin-bank admin account..."
+sudo -u libeufin-bank \
+ libeufin-bank passwd \
+ -c /etc/libeufin/libeufin-bank.conf \
+ admin "${BANK_ADMIN_PASSWORD}"
+
+say "Setting up admin's debt limit..."
+sudo -u libeufin-bank \
+ libeufin-bank edit-account \
+ -c /etc/libeufin/libeufin-bank.conf \
+ admin --debit_threshold=${CURRENCY}:200000000
+
+say "Setting up SPA configuration..."
+echo "settings = { bankName: \"${BANK_NAME}\" }" >/etc/libeufin/settings.js
+
+say "Create exchange account..."
+if test -z "${EXCHANGE_PAYTO:-}"; then
+ EXCHANGE_PAYTO_NEW="$(sudo -u libeufin-bank libeufin-bank create-account -c /etc/libeufin/libeufin-bank.conf --username exchange --password "${BANK_EXCHANGE_PASSWORD}" --name Exchange --exchange)?receiver-name=Exchange"
+ echo "EXCHANGE_PAYTO=\"${EXCHANGE_PAYTO_NEW}\"" >> config/internal.conf
+fi
+
+if test -z "${EXCHANGE_WIRE_GATEWAY_URL:-}"; then
+ EXCHANGE_WIRE_GATEWAY_URL_NEW="${PROTO}://bank.$DOMAIN_NAME/accounts/exchange/taler-wire-gateway/"
+ echo "EXCHANGE_WIRE_GATEWAY_URL=\"${EXCHANGE_WIRE_GATEWAY_URL_NEW}\"" >> config/internal.conf
+fi
+
+say "Start the bank..."
+systemctl enable --now libeufin-bank
+
+say "Waiting for the bank (/config)..."
+curl --max-time 2 \
+ --retry-all-errors \
+ --retry-delay 4 \
+ --retry 10 \
+ ${PROTO}://bank.${DOMAIN_NAME}/config
+say "DONE"
+
+say "Setting conversion figures..."
+
+curl -u "admin:${BANK_ADMIN_PASSWORD}" \
+ -H 'Content-Type: application/json; charset=utf-8' \
+ ${PROTO}://bank.${DOMAIN_NAME}/conversion-info/conversion-rate \
+--data-binary @- << EOF
+{
+ "cashin_ratio": "1",
+ "cashin_fee": "${CURRENCY}:0",
+ "cashin_tiny_amount": "${CURRENCY}:2",
+ "cashin_rounding_mode": "nearest",
+ "cashin_min_amount": "${FIAT_CURRENCY}:1",
+ "cashout_ratio": "1",
+ "cashout_fee": "${FIAT_CURRENCY}:0",
+ "cashout_tiny_amount": "${FIAT_CURRENCY}:2",
+ "cashout_rounding_mode": "zero",
+ "cashout_min_amount": "${CURRENCY}:1"
+}
+EOF
+say "DONE"
diff --git a/regional-currency/config_libeufin_nexus.sh b/regional-currency/config_libeufin_nexus.sh
new file mode 100755
index 0000000..491a757
--- /dev/null
+++ b/regional-currency/config_libeufin_nexus.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# This file is in the public domain.
+#
+# This script configure and launches libeufin-bank.
+# The setup provides the admin account at the bank, and
+# another account for the exchange at the bank.
+#
+# The environment must provide the following variables:
+set -eu
+
+source functions.sh
+source config/user.conf
+
+taler-config -s nexus-ebics -o currency \
+ -V $FIAT_CURRENCY -c /etc/libeufin/libeufin-nexus.conf
+
+say "Start nexus tasks..."
+systemctl enable --now libeufin-nexus-ebics-fetch
+systemctl enable --now libeufin-nexus-ebics-submit
diff --git a/regional-currency/config_nginx.sh b/regional-currency/config_nginx.sh
new file mode 100755
index 0000000..2fe561c
--- /dev/null
+++ b/regional-currency/config_nginx.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+source functions.sh
+source config/user.conf
+
+export PROTO
+export DOMAIN_NAME
+export BANK_PORT
+
+envsubst <nginx-conf/backend.taler-nginx.conf >"/etc/nginx/sites-available/backend.${DOMAIN_NAME}"
+envsubst <nginx-conf/bank.taler-nginx.conf >"/etc/nginx/sites-available/bank.${DOMAIN_NAME}"
+envsubst <nginx-conf/exchange.taler-nginx.conf >"/etc/nginx/sites-available/exchange.${DOMAIN_NAME}"
+
+# Create nginx symlinks
+
+ln -sf /etc/nginx/sites-available/backend."${DOMAIN_NAME}" /etc/nginx/sites-enabled/backend."${DOMAIN_NAME}"
+ln -sf /etc/nginx/sites-available/bank."${DOMAIN_NAME}" /etc/nginx/sites-enabled/bank."${DOMAIN_NAME}"
+ln -sf /etc/nginx/sites-available/exchange."${DOMAIN_NAME}" /etc/nginx/sites-enabled/exchange."${DOMAIN_NAME}"
+
+if test "${ENABLE_TLS}" == "y"; then
+
+ # Replace http with https in the demobank-ui configuration
+
+ sed -i "s/http:\/\/bank./https:\/\/bank./g" /etc/libeufin/settings.json
+
+ # Certbot
+
+ say "Obtaining TLS certificates"
+
+ certbot --nginx -d backend."${DOMAIN_NAME}" \
+ -d bank."${DOMAIN_NAME}" \
+ -d exchange."${DOMAIN_NAME}"
+else
+ sed -i "s/https:\/\/bank./http:\/\/bank./g" /etc/libeufin/settings.json
+fi
+
+say "Restarting Nginx with new configuration"
+systemctl reload nginx
diff --git a/regional-currency/functions.sh b/regional-currency/functions.sh
new file mode 100755
index 0000000..a596f72
--- /dev/null
+++ b/regional-currency/functions.sh
@@ -0,0 +1,87 @@
+#!/bin/bash
+
+# Message
+function say() {
+ echo "TALER: " "$@"
+}
+
+# Check user if the user is root
+function check_user() {
+ if [ "$(whoami)" != "root" ]; then
+ say "Please run this script as root"
+ exit 1
+ fi
+}
+
+function ask_questions() {
+ if test -z "${CURRENCY:-}"; then
+ read -r -p "Enter the name of the regional currency (e.g. 'NETZBON'): " CURRENCY
+ # convert to all-caps
+ CURRENCY=$(echo "${CURRENCY}" | tr a-z A-Z)
+ # libeufin currenly doesn't like currency names less than 3 letters.
+ if [[ ${#CURRENCY} -lt 3 || ${#CURRENCY} -gt 11 ]]; then
+ say "Currency name must be between 3 and 10 letters"
+ exit 1
+ fi
+ echo "CURRENCY=${CURRENCY}" >>config/user.conf
+ fi
+ if test -z "${FIAT_CURRENCY:-}"; then
+ read -r -p "Enter the name of the fiat currency (e.g. 'CHF'): " FIAT_CURRENCY
+ # convert to all-caps
+ FIAT_CURRENCY=$(echo "${FIAT_CURRENCY}" | tr a-z A-Z)
+ # libeufin currenly doesn't like currency names less than 3 letters.
+ if [[ ${#FIAT_CURRENCY} -lt 3 || ${#FIAT_CURRENCY} -gt 11 ]]; then
+ say "Currency name must be between 3 and 10 letters"
+ exit 1
+ fi
+ echo "FIAT_CURRENCY=${FIAT_CURRENCY}" >>config/user.conf
+ fi
+ if test -z "${BANK_NAME:-}"; then
+ read -r -p "Enter the human-readable name of the bank (e.g. 'Taler Bank'): " BANK_NAME
+ echo "BANK_NAME=\"${BANK_NAME}\"" >>config/user.conf
+ fi
+ if test -z "${ENABLE_TLS:-}"; then
+ read -r -p "Use TLS? (y/n): " ENABLE_TLS
+ echo "ENABLE_TLS=${ENABLE_TLS}" >>config/user.conf
+ fi
+ if test -z "${DO_OFFLINE:-}"; then
+ read -r -p "Run taler-exchange-offline? (y/n): " DO_OFFLINE
+ echo "DO_OFFLINE=${DO_OFFLINE}" >>config/user.conf
+ fi
+ if test -z "${MASTER_PUBLIC_KEY:-}"; then
+ if test "${DO_OFFLINE:-y}" == n; then
+ read -r -p "Enter the exchange-offline master public key: " MASTER_PUBLIC_KEY
+ echo "MASTER_PUBLIC_KEY=${MASTER_PUBLIC_KEY}" >>config/user.conf
+ fi
+ fi
+ if test -z "${BANK_ADMIN_PASSWORD:-}"; then
+ read -r -s -p "Enter the admin password for the bank: " BANK_ADMIN_PASSWORD
+ echo "BANK_ADMIN_PASSWORD=$(printf '%q' "${BANK_ADMIN_PASSWORD}")" >>config/user.conf
+ echo "" # force new line
+ fi
+ if test -z "${DOMAIN_NAME:-}"; then
+ read -r -p "Enter the domain name: " DOMAIN_NAME
+ # convert to lower-case
+ DOMAIN_NAME=$(echo "${DOMAIN_NAME}" | tr A-Z a-z)
+ echo "DOMAIN_NAME=${DOMAIN_NAME}" >>config/user.conf
+ fi
+}
+
+# Set DISTRO to the detected distro or return non-zero
+# status if distro not supported.
+function detect_distro() {
+ unset DISTRO
+ # shellcheck disable=SC2034
+ uname -a | grep Ubuntu >/dev/null && DISTRO=ubuntu && return 0
+ # shellcheck disable=SC2034
+ uname -a | grep Debian >/dev/null && DISTRO=debian && return 0
+ echo "Unsupported distro, should be either ubuntu or debian" >&2
+ return 1
+}
+
+function config_services() {
+ ./config_nginx.sh
+ ./config_libeufin.sh
+ ./setup-exchange.sh
+ ./setup-merchant.sh
+}
diff --git a/regional-currency/incoming_template.xml b/regional-currency/incoming_template.xml
new file mode 100644
index 0000000..635fca7
--- /dev/null
+++ b/regional-currency/incoming_template.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.054.001.08" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:camt.054.001.08 camt.054.001.08.xsd">
+ <BkToCstmrDbtCdtNtfctn>
+ <GrpHdr>
+ <MsgId>20231106375204337320698</MsgId>
+ <CreDtTm>2023-11-06T23:39:09</CreDtTm>
+ <MsgPgntn>
+ <PgNb>1</PgNb>
+ <LastPgInd>true</LastPgInd>
+ </MsgPgntn>
+ <AddtlInf>NOT-INGESTED</AddtlInf>
+ </GrpHdr>
+ <Ntfctn>
+ <Id>20231106375204337320700</Id>
+ <CreDtTm>2023-11-06T23:39:09</CreDtTm>
+ <FrToDt>
+ <FrDtTm>2023-11-04T00:00:00</FrDtTm>
+ <ToDtTm>2023-11-06T23:59:59</ToDtTm>
+ </FrToDt>
+ <RptgSrc>
+ <Prtry>OTHR</Prtry>
+ </RptgSrc>
+ <Acct>
+ <Id>
+ <IBAN>NOT-INGESTED</IBAN>
+ </Id>
+ <Ownr>
+ <Nm>NOT-INGESTED</Nm>
+ </Ownr>
+ </Acct>
+ <Ntry>
+ <NtryRef>NOT-INGESTED</NtryRef>
+ <Amt Ccy="CHF">5.00</Amt>
+ <CdtDbtInd>CRDT</CdtDbtInd>
+ <RvslInd>false</RvslInd>
+ <Sts>
+ <Cd>BOOK</Cd>
+ </Sts>
+ <BookgDt>
+ <Dt>2023-11-06</Dt>
+ </BookgDt>
+ <ValDt>
+ <Dt>2023-11-06</Dt>
+ </ValDt>
+ <AcctSvcrRef>NOT-INGESTED</AcctSvcrRef>
+ <BkTxCd>
+ <Domn>
+ <Cd>PMNT</Cd>
+ <Fmly>
+ <Cd>RCDT</Cd>
+ <SubFmlyCd>AUTT</SubFmlyCd>
+ </Fmly>
+ </Domn>
+ </BkTxCd>
+ <NtryDtls>
+ <Btch>
+ <NbOfTxs>1</NbOfTxs>
+ </Btch>
+ <TxDtls>
+ <Refs>
+ <AcctSvcrRef>BANK_ID</AcctSvcrRef>
+ <InstrId>NOT-INGESTED</InstrId>
+ <EndToEndId>NOT-INGESTED</EndToEndId>
+ <Prtry>
+ <Tp>00</Tp>
+ <Ref>NOT-INGESTED</Ref>
+ </Prtry>
+ </Refs>
+ <Amt Ccy="CHF">5.00</Amt>
+ <CdtDbtInd>CRDT</CdtDbtInd>
+ <BkTxCd>
+ <Domn>
+ <Cd>PMNT</Cd>
+ <Fmly>
+ <Cd>RCDT</Cd>
+ <SubFmlyCd>ATXN</SubFmlyCd>
+ </Fmly>
+ </Domn>
+ </BkTxCd>
+ <RltdPties>
+ <Dbtr>
+ <Pty>
+ <Nm>Test User</Nm>
+ </Pty>
+ </Dbtr>
+ <DbtrAcct>
+ <Id>
+ <IBAN>DEBTOR_IBAN</IBAN>
+ </Id>
+ </DbtrAcct>
+ <CdtrAcct>
+ <Id>
+ <IBAN>NOT-INGESTED</IBAN>
+ </Id>
+ </CdtrAcct>
+ </RltdPties>
+ <RltdAgts>
+ <DbtrAgt>
+ <FinInstnId>
+ <ClrSysMmbId>
+ <MmbId>NOT-INGESTED</MmbId>
+ </ClrSysMmbId>
+ <Nm>NOT-INGESTED</Nm>
+ <PstlAdr>
+ <AdrLine>NOT-INGESTED</AdrLine>
+ <AdrLine>NOT-INGESTED</AdrLine>
+ </PstlAdr>
+ </FinInstnId>
+ </DbtrAgt>
+ </RltdAgts>
+ <RmtInf>
+ <Ustrd>RESERVE_PUB</Ustrd>
+ <Strd>
+ <AddtlRmtInf>?REJECT?0</AddtlRmtInf>
+ <AddtlRmtInf>?ERROR?000</AddtlRmtInf>
+ </Strd>
+ </RmtInf>
+ <RltdDts>
+ <AccptncDtTm>2023-11-06T20:00:00</AccptncDtTm>
+ </RltdDts>
+ </TxDtls>
+ </NtryDtls>
+ <AddtlNtryInf>NOT-INGESTED</AddtlNtryInf>
+ </Ntry>
+ </Ntfctn>
+ </BkToCstmrDbtCdtNtfctn>
+</Document>
diff --git a/regional-currency/install_packages.sh b/regional-currency/install_packages.sh
new file mode 100755
index 0000000..76ab05b
--- /dev/null
+++ b/regional-currency/install_packages.sh
@@ -0,0 +1,60 @@
+#!/bin/bash
+# This file is in the public domain.
+
+set -eu
+
+source functions.sh
+source config/user.conf
+source config/internal.conf
+
+detect_distro
+
+# Program versions
+PG_VERSION=15
+
+## Update
+
+apt update
+
+## General requirements
+
+apt install uuid-runtime \
+ curl \
+ jq \
+ wget \
+ nginx \
+ postgresql-${PG_VERSION} \
+ postgresql-client-${PG_VERSION} \
+ dbconfig-pgsql \
+ certbot \
+ python3-certbot-nginx -y
+
+## Add GNU Taler deb.taler.net to /etc/apt/sources.list
+
+say "Adding GNU Taler apt repository"
+say "Detected distro $DISTRO"
+
+case $DISTRO in
+debian) # TODO stable again when it is back ?
+ echo "deb [signed-by=/etc/apt/keyrings/taler-systems.gpg] https://deb.taler.net/apt/debian bookworm main" >/etc/apt/sources.list.d/taler.list
+ ;;
+ubuntu)
+ echo "deb [signed-by=/etc/apt/keyrings/taler-systems.gpg] https://deb.taler.net/apt/ubuntu stable main" >/etc/apt/sources.list.d/taler.list
+ ;;
+*)
+ say "Unsupported distro: $DISTRO"
+ exit 1
+ ;;
+esac
+
+wget -P /etc/apt/keyrings https://taler.net/taler-systems.gpg
+
+## Specific GNU Taler packages
+
+apt update
+apt install taler-exchange \
+ taler-merchant \
+ taler-harness \
+ taler-wallet-cli \
+ libeufin-bank \
+ libeufin-nexus -y
diff --git a/regional-currency/main.sh b/regional-currency/main.sh
new file mode 100755
index 0000000..97773ea
--- /dev/null
+++ b/regional-currency/main.sh
@@ -0,0 +1,86 @@
+#!/bin/bash
+# This file is in the public domain.
+
+# main.sh is the main script that asks the questions and
+# puts the answers into environment variables located at "config/taler-internal.conf or config/taler.conf" files
+# Nginx configuration - Reads values directly from these "config files".
+
+set -eu
+
+# include functions source file
+
+source functions.sh
+
+# include variables from configuration
+mkdir -p config/
+touch config/user.conf config/internal.conf
+# Values supplied by user
+source config/user.conf
+# Values we generated
+source config/internal.conf
+
+# Ask questions to user
+# START USER INTERACTION
+say "Welcome to the GNU Taler Debian setup!"
+say ""
+say "All configuration values asked during the setup script"
+say "can be changed in config/user.conf"
+
+ask_questions
+
+# END USER INTERACTION
+
+# Check if the user is root, otherwise EXIT.
+check_user
+
+# Installation of deb packages required
+. install_packages.sh
+
+# Check DNS settings
+if ! ping -c1 "exchange.${DOMAIN_NAME}" &>/dev/null; then
+ say "Could not ping exchange.${DOMAIN_NAME}."
+ say "Please make sure your DNS/network are working."
+ exit 1
+fi
+if ! ping -c1 "bank.${DOMAIN_NAME}" &>/dev/null; then
+ say "Could not ping bank.${DOMAIN_NAME}."
+ say "Please make sure your DNS/network are working."
+ exit 1
+fi
+
+if test -z "${BANK_EXCHANGE_PASSWORD:-}"; then
+ BANK_EXCHANGE_PASSWORD=$(uuidgen)
+ echo "BANK_EXCHANGE_PASSWORD=\"${BANK_EXCHANGE_PASSWORD}\"" >>config/internal.conf
+fi
+
+if test -z "${BANK_PORT:-}"; then
+ echo "BANK_PORT=8080" >>config/user.conf
+fi
+
+if test -z "${PROTO:-}"; then
+ if test "${ENABLE_TLS:-}" == "y"; then
+ PROTO="https"
+ else
+ PROTO="http"
+ fi
+ echo "PROTO=$PROTO">>config/internal.conf
+fi
+
+# FIXME: remove once the merchant .deb gets updated
+rm /usr/bin/taler-merchant-dbconfig
+wget -P /usr/bin/ https://git.taler.net/merchant.git/plain/contrib/taler-merchant-dbconfig
+chmod a+x /usr/bin/taler-merchant-dbconfig
+
+config_services
+
+# Final message to the user
+say "Congratulations, you have successfully installed GNU Taler"
+say "Your bank is at ${PROTO}://bank.${DOMAIN_NAME}/"
+say "A merchant is at ${PROTO}://backend.${DOMAIN_NAME}/"
+say "You should set credentials for the merchant soon."
+say "For the SMS cash-out TAN, make sure that telesign-secret"
+say "is found in the PATH and that it defines the CUSTOMER_ID"
+say "and API_KEY environment variables."
+
+exit 0
+# END INSTALLATION
diff --git a/regional-currency/nginx-conf/backend.taler-nginx.conf b/regional-currency/nginx-conf/backend.taler-nginx.conf
new file mode 100644
index 0000000..3e20704
--- /dev/null
+++ b/regional-currency/nginx-conf/backend.taler-nginx.conf
@@ -0,0 +1,14 @@
+server {
+
+ listen 80;
+ listen [::]:80;
+
+ server_name backend.${DOMAIN_NAME};
+
+ location / {
+ proxy_pass http://unix:/var/run/taler/merchant-httpd/merchant-http.sock;
+ proxy_set_header X-Forwarded-Proto "${PROTO}";
+ proxy_set_header X-Forwarded-Host "backend.${DOMAIN_NAME}";
+ proxy_set_header X-Forwarded-Prefix /;
+ }
+}
diff --git a/regional-currency/nginx-conf/bank.taler-nginx.conf b/regional-currency/nginx-conf/bank.taler-nginx.conf
new file mode 100644
index 0000000..9e2ce5b
--- /dev/null
+++ b/regional-currency/nginx-conf/bank.taler-nginx.conf
@@ -0,0 +1,18 @@
+server {
+ listen 80;
+ listen [::]:80;
+
+ server_name bank.${DOMAIN_NAME};
+
+ access_log /var/log/nginx/libeufin-sandbox.log;
+ error_log /var/log/nginx/libeufin-sandbox.err;
+
+ # TODO should we proxy SPA with nginx for perf and fallback to bank server on 404 ?
+ location / {
+ proxy_pass http://localhost:${BANK_PORT};
+ #Fixes withdrawal http request
+ proxy_set_header X-Forwarded-Proto "${PROTO}";
+ proxy_set_header X-Forwarded-Host "bank.${DOMAIN_NAME}";
+ proxy_set_header X-Forwarded-Prefix /;
+ }
+}
diff --git a/regional-currency/nginx-conf/exchange.taler-nginx.conf b/regional-currency/nginx-conf/exchange.taler-nginx.conf
new file mode 100644
index 0000000..0f470a1
--- /dev/null
+++ b/regional-currency/nginx-conf/exchange.taler-nginx.conf
@@ -0,0 +1,12 @@
+server {
+
+ listen 80;
+ listen [::]:80;
+
+ server_name exchange.${DOMAIN_NAME};
+
+ location / {
+ proxy_pass http://unix:/var/run/taler/exchange-httpd/exchange-http.sock;
+ }
+
+}
diff --git a/regional-currency/setup-exchange.sh b/regional-currency/setup-exchange.sh
new file mode 100755
index 0000000..2c4c06f
--- /dev/null
+++ b/regional-currency/setup-exchange.sh
@@ -0,0 +1,228 @@
+#!/bin/bash
+# This file is in the public domain.
+#
+# This script configure and launches the Taler exchange.
+#
+# The environment must provide the following variables:
+#
+# - BANK_EXCHANGE_PASSWORD (exchange password for libeufin-bank)
+# - EXCHANGE_WIRE_GATEWAY_URL (where is the exchange wire gateway / libeufin-nexus)
+# - EXCHANGE_PAYTO (exchange account PAYTO)
+# - ENABLE_TLS (http or https?)
+# - DOMAIN_NAME: DNS domain name to use for the setup
+#
+
+set -eu
+
+notify_exit() {
+ [[ $1 == 0 ]] || echo Script "$0" failed, exit code "$1"
+}
+
+notify_err() {
+ echo "errexit on line $(caller)" >&2
+}
+
+trap '(exit 130)' INT
+trap '(exit 143)' TERM
+trap notify_err ERR
+# shellcheck disable=SC2154
+trap 'rc=$?; notify_exit $rc; exit $rc' EXIT
+
+# End of error handling setup
+
+source functions.sh
+source config/user.conf
+source config/internal.conf
+
+EXCHANGE_DB="taler-exchange"
+
+say "Beginning Exchange setup"
+
+if test -z "${BANK_EXCHANGE_PASSWORD:-}"; then
+ say "Failure: BANK_EXCHANGE_PASSWORD not set"
+ exit 1
+fi
+if test -z "${EXCHANGE_WIRE_GATEWAY_URL:-}"; then
+ say "Failure: EXCHANGE_WIRE_GATEWAY_URL not set"
+ exit 1
+fi
+if test -z "${EXCHANGE_PAYTO:-}"; then
+ say "Failure: EXCHANGE_PAYTO not set"
+ exit 1
+fi
+
+function die() {
+ say "$1"
+ exit 1
+}
+
+# Just try if sudo works for diagnostics
+sudo -i -u taler-exchange-offline id >/dev/null || die "Error: Unable to switch to taler-exchange-offline user"
+
+
+chmod a+r /etc/taler/taler.conf # FIXME-CG: Debian installation should set this
+
+# Create master key as taler-exchange-offline *unless* user already
+# set the MASTER_PUBLIC_KEY to some value we can use.
+export MASTER_PRIV_DIR=.local/share/taler/exchange/offline-keys
+export MASTER_PRIV_FILE=${MASTER_PRIV_DIR}/master.priv
+export SECMOD_TOFU_FILE=${MASTER_PRIV_DIR}/secm_tofus.pub
+if test -z "${MASTER_PUBLIC_KEY:-}"; then
+ if test "${DO_OFFLINE:-y}" == n; then
+ say "Error: No MASTER_PUBLIC_KEY but DO_OFFLINE set to NO"
+ exit 1
+ fi
+ say "Setting up offline key"
+ echo -e "[exchange-offline]\n"\
+ "MASTER_PRIV_FILE=\$HOME/${MASTER_PRIV_FILE}\n"\
+ "SECM_TOFU_FILE=\$HOME/${SECMOD_TOFU_FILE}\n"\
+ >/etc/taler/conf.d/offline-setup.conf
+
+ MASTER_PUBLIC_KEY=$(sudo -i -u taler-exchange-offline taler-exchange-offline -c /etc/taler/taler.conf -LDEBUG setup)
+ echo "MASTER_PUBLIC_KEY=\"${MASTER_PUBLIC_KEY}\"" >>config/user.conf
+ if test -z "${DO_OFFLINE:-}"; then
+ # Set 'DO_OFFLINE'
+ DO_OFFLINE=y
+ echo "DO_OFFLINE=y" >>config/user.conf
+ fi
+else
+ say "Master public key is $MASTER_PUBLIC_KEY"
+ if test ${DO_OFFLINE:-y} == y; then
+ MASTER_PUBLIC_KEY2=$(sudo -i -u taler-exchange-offline taler-exchange-offline -c /etc/taler/taler.conf setup)
+ if test "${MASTER_PUBLIC_KEY2}" != "${MASTER_PUBLIC_KEY}"; then
+ say "Error: master public key missmatch ${MASTER_PUBLIC_KEY2} does not match ${MASTER_PUBLIC_KEY}"
+ exit 1
+ fi
+ fi
+fi
+
+export MASTER_PUBLIC_KEY
+
+say "Stopping running exchange before reconfiguration"
+systemctl stop taler-exchange.target
+
+say "Configuring exchange"
+
+export EXCHANGE_BASE_URL="$PROTO://exchange.${DOMAIN_NAME}/"
+
+cat << EOF > /etc/taler/conf.d/setup.conf
+[taler]
+CURRENCY=${CURRENCY}
+CURRENCY_ROUND_UNIT=${CURRENCY}:0.01
+
+[exchange]
+AML_THRESHOLD=${CURRENCY}:1000000
+MASTER_PUBLIC_KEY=${MASTER_PUBLIC_KEY}
+BASE_URL=${EXCHANGE_BASE_URL}
+STEFAN_ABS=${CURRENCY}:0
+STEFAN_LOG=${CURRENCY}:0
+STEFAN_LIN=0
+
+[merchant-exchange-${DOMAIN_NAME}]
+MASTER_KEY=${MASTER_PUBLIC_KEY}
+CURRENCY=${CURRENCY}
+EXCHANGE_BASE_URL=${EXCHANGE_BASE_URL}
+
+[exchange-account-default]
+PAYTO_URI=${EXCHANGE_PAYTO}
+ENABLE_DEBIT=YES
+ENABLE_CREDIT=YES
+@inline-secret@ exchange-accountcredentials-default ../secrets/exchange-accountcredentials-default.secret.conf
+EOF
+
+# FIXME-CG: def already in the Git, remove this
+# after the next .deb release
+cat << EOF > /etc/taler/conf.d/netzbon.conf
+[currency-netzbon]
+ENABLED=YES
+name=NetzBon
+code=NETZBON
+fractional_input_digits=2
+fractional_normal_digits=2
+fractional_trailing_zero_digits=2
+alt_unit_names = {"0":"NETZBON"}
+EOF
+chmod a+r /etc/taler/conf.d/netzbon.conf
+
+cat << EOF > /etc/taler/secrets/exchange-db.secret.conf
+[exchangedb-postgres]
+CONFIG=postgres:///exchange
+EOF
+
+chmod 440 /etc/taler/secrets/exchange-db.secret.conf
+chown root:taler-exchange-db /etc/taler/secrets/exchange-db.secret.conf
+
+cat << EOF > /etc/taler/secrets/exchange-accountcredentials-default.secret.conf
+
+[exchange-accountcredentials-default]
+WIRE_GATEWAY_URL=${EXCHANGE_WIRE_GATEWAY_URL}
+WIRE_GATEWAY_AUTH_METHOD=basic
+USERNAME=exchange
+PASSWORD=${BANK_EXCHANGE_PASSWORD}
+EOF
+
+chmod 400 /etc/taler/secrets/exchange-accountcredentials-default.secret.conf
+chown taler-exchange-wire:taler-exchange-db /etc/taler/secrets/exchange-accountcredentials-default.secret.conf
+
+taler-harness deployment gen-coin-config \
+ --min-amount "${CURRENCY}":0.01 \
+ --max-amount "${CURRENCY}":100 |
+ sed -e "s/FEE_DEPOSIT = ${CURRENCY}:0.01/FEE_DEPOSIT = ${CURRENCY}:0/" \
+ >/etc/taler/conf.d/"${CURRENCY}"-coins.conf
+
+# FIXME-DOLD: this belongs with taler-harness
+for SEC in $(taler-config -c /etc/taler/conf.d/"${CURRENCY}"-coins.conf -S | grep COIN-); do
+ taler-config -c /etc/taler/conf.d/"${CURRENCY}"-coins.conf -s "$SEC" -o CIPHER -V "RSA"
+done
+
+# NOTE: already fixed in exchange.git, leaving in place
+# until 0.9.4 release of fixed exchange Debian package. -CG
+say "Initializing exchange database"
+taler-exchange-dbconfig -c /etc/taler/taler.conf || true # FIXME-CG: no exit 77 if DB exist
+# NOTE: latest exchange.git dbconfig no longer exits with 77, should remove || true with 0.9.4 exchange release.
+
+say "Launching exchange"
+systemctl enable --now taler-exchange.target
+
+say "Waiting for exchange HTTP service (/config)..."
+curl --max-time 2 \
+ --retry-all-errors \
+ --retry-delay 1 \
+ --retry 10 \
+ "${EXCHANGE_BASE_URL}"config &>/dev/null
+say "DONE"
+
+say "Waiting for exchange management keys (this may take a while)..."
+curl --max-time 30 \
+ --retry-delay 1 \
+ --retry 60 \
+ "${EXCHANGE_BASE_URL}"management/keys &>/dev/null
+say "DONE"
+
+if test ${DO_OFFLINE} == y; then
+ say "Offline interaction..."
+
+ sudo -i -u taler-exchange-offline \
+ taler-exchange-offline \
+ -c /etc/taler/taler.conf \
+ download \
+ sign \
+ upload
+
+ sudo -i -u taler-exchange-offline \
+ taler-exchange-offline \
+ enable-account "${EXCHANGE_PAYTO}" \
+ wire-fee now iban "${CURRENCY}":0 "${CURRENCY}":0 \
+ global-fee now "${CURRENCY}":0 "${CURRENCY}":0 "${CURRENCY}":0 1h 6a 0 \
+ upload
+fi
+
+say "Waiting for exchange /keys..."
+curl --max-time 2 \
+ --retry-connrefused \
+ --retry-delay 1 \
+ --retry 10 \
+ "${EXCHANGE_BASE_URL}"keys &>/dev/null
+say "DONE"
+
+say "Exchange setup finished"
diff --git a/regional-currency/setup-merchant.sh b/regional-currency/setup-merchant.sh
new file mode 100755
index 0000000..917e653
--- /dev/null
+++ b/regional-currency/setup-merchant.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+set -eu
+
+source functions.sh
+source config/user.conf
+source config/internal.conf
+
+say "Setting up merchant database"
+taler-merchant-dbconfig
+
+say "Launching taler-merchant-httpd"
+systemctl enable --now taler-merchant-httpd
diff --git a/regional-currency/transfer.sh b/regional-currency/transfer.sh
new file mode 100755
index 0000000..d49d445
--- /dev/null
+++ b/regional-currency/transfer.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# This file is in the public domain.
+
+set -eu
+
+source functions.sh
+
+if test -z "${3:-}"; then
+ say "This tool allows you to send funds from the 'admin' account"
+ say "to a normal user's bank account within the system for testing."
+ say " "
+ say "Call with three arguments:"
+ say "1) target bank account name to credit"
+ say "2) amount to transfer (e.g. ${CURRENCY:-CURRENCY}:42.42)"
+ say "3) wire transfer subject to use"
+ say " "
+ exit 1
+fi
+
+# shellcheck disable=SC1091
+source /etc/libeufin/sandbox.env
+export LIBEUFIN_SANDBOX_DB_CONNECTION
+
+libeufin-sandbox make-transaction --credit-account "$1" --debit-account admin "$2" "$3"
diff --git a/regional-currency/vagrant/.gitignore b/regional-currency/vagrant/.gitignore
new file mode 100644
index 0000000..8000dd9
--- /dev/null
+++ b/regional-currency/vagrant/.gitignore
@@ -0,0 +1 @@
+.vagrant
diff --git a/regional-currency/vagrant/README b/regional-currency/vagrant/README
new file mode 100644
index 0000000..e9387d3
--- /dev/null
+++ b/regional-currency/vagrant/README
@@ -0,0 +1,2 @@
+This folder contains a vagrant configuration (https://developer.hashicorp.com/vagrant)
+that allows us to easily spin up a virtual machine to test the setup instructions.
diff --git a/regional-currency/vagrant/Vagrantfile b/regional-currency/vagrant/Vagrantfile
new file mode 100644
index 0000000..7cb3574
--- /dev/null
+++ b/regional-currency/vagrant/Vagrantfile
@@ -0,0 +1,77 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+
+# All Vagrant configuration is done below. The "2" in Vagrant.configure
+# configures the configuration version (we support older styles for
+# backwards compatibility). Please don't change it unless you know what
+# you're doing.
+Vagrant.configure("2") do |config|
+ # The most common configuration options are documented and commented below.
+ # For a complete reference, please see the online documentation at
+ # https://docs.vagrantup.com.
+
+ # Every Vagrant development environment requires a box. You can search for
+ # boxes at https://vagrantcloud.com/search.
+ config.vm.box = "ubuntu/kinetic64"
+
+ config.ssh.forward_agent = true
+ config.ssh.forward_x11 = true
+
+ # Disable automatic box update checking. If you disable this, then
+ # boxes will only be checked for updates when the user runs
+ # `vagrant box outdated`. This is not recommended.
+ # config.vm.box_check_update = false
+
+ # Create a forwarded port mapping which allows access to a specific port
+ # within the machine from a port on the host machine. In the example below,
+ # accessing "localhost:8080" will access port 80 on the guest machine.
+ # NOTE: This will enable public access to the opened port
+ # config.vm.network "forwarded_port", guest: 80, host: 8080
+
+ # Create a forwarded port mapping which allows access to a specific port
+ # within the machine from a port on the host machine and only allow access
+ # via 127.0.0.1 to disable public access
+ # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"
+
+ # Create a private network, which allows host-only access to the machine
+ # using a specific IP.
+ # config.vm.network "private_network", ip: "192.168.33.10"
+
+ # Create a public network, which generally matched to bridged network.
+ # Bridged networks make the machine appear as another physical device on
+ # your network.
+ # config.vm.network "public_network"
+
+ # Share an additional folder to the guest VM. The first argument is
+ # the path on the host to the actual folder. The second argument is
+ # the path on the guest to mount the folder. And the optional third
+ # argument is a set of non-required options.
+ # config.vm.synced_folder "../data", "/vagrant_data"
+
+ # Provider-specific configuration so you can fine-tune various
+ # backing providers for Vagrant. These expose provider-specific options.
+ # Example for VirtualBox:
+ #
+ config.vm.provider "virtualbox" do |vb|
+ # Display the VirtualBox GUI when booting the machine
+ vb.gui = true
+
+ # Customize the amount of memory on the VM:
+ vb.memory = "4096"
+
+ # Required, or wayland doesn't seem to work
+ vb.customize ['modifyvm', :id, '--graphicscontroller', 'vmsvga']
+ end
+ #
+ # View the documentation for the provider you are using for more
+ # information on available options.
+
+ # Enable provisioning with a shell script. Additional provisioners such as
+ # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the
+ # documentation for more information about their specific syntax and use.
+ config.vm.provision "shell", reboot: true, inline: <<-SHELL
+ apt-get update
+ apt-get upgrade -y
+ apt-get install -y ubuntu-desktop gnome-shell firefox virtualbox-guest-additions-iso git
+ SHELL
+end
diff --git a/regional-currency/withdraw.sh b/regional-currency/withdraw.sh
new file mode 100755
index 0000000..850d343
--- /dev/null
+++ b/regional-currency/withdraw.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+if test "$1" = "--help" || test "$1" = "-h"; then
+ echo "./withdraw [RESERVE_PUB]"
+ echo
+ echo "Injects one incoming CHF payment into nexus database"
+ echo "in order to trigger a Taler withdrawal. The reserve"
+ echo "pub can be passed either as the first parameter, or"
+ echo "it'll be generated by the CLI wallet. In both cases,"
+ echo "the exchange to withdraw from is \$PROTO://exchange.\$DOMAIN"
+
+ exit 0
+fi
+
+RESERVE_PUB="$1" # maybe passed
+set -eu
+
+. config/user.conf # DOMAIN_NAME & CURRENCY
+. config/internal.conf # PROTO
+
+NEXUS_CONFIG_FILE=/etc/libeufin/libeufin-nexus.conf
+if test -z "$RESERVE_PUB"; then
+ RESERVE_PUB=$(taler-wallet-cli \
+ api 'acceptManualWithdrawal' \
+ '{"exchangeBaseUrl":"'${PROTO}'://exchange.'$DOMAIN_NAME'",
+ "amount":"'$CURRENCY':5"
+ }' | jq -r .result.reservePub)
+fi
+DEBTOR_IBAN="CH8389144317421994586"
+CAMT_054=$(sed \
+ -e "s/RESERVE_PUB/$RESERVE_PUB/" \
+ -e "s/BANK_ID/$(uuidgen | cut -c-34)/" \
+ -e "s/DEBTOR_IBAN/$DEBTOR_IBAN/" \
+ incoming_template.xml)
+
+echo "$CAMT_054" | sudo -i -u libeufin-nexus \
+ libeufin-nexus ebics-fetch -c $NEXUS_CONFIG_FILE --import
+
+taler-wallet-cli run-until-done