exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

commit 5bcfa61aee3e1d741407372f7f5141322f9cdd95
parent 900bdc7b777411648772962276dfd3c49dcd28d6
Author: Christian Grothoff <christian@grothoff.org>
Date:   Thu,  3 Jul 2025 16:34:46 +0200

implement #10117

Diffstat:
Msrc/exchange/taler-exchange-httpd_config.c | 2+-
Msrc/exchange/taler-exchange-httpd_config.h | 2+-
Msrc/exchange/taler-exchange-httpd_keys.c | 2+-
Msrc/include/taler/taler_json_lib.h | 12++++++++++++
Msrc/include/taler/taler_util.h | 23+++++++++++------------
Msrc/json/Makefile.am | 2+-
Msrc/json/json.c | 34++++++++++++++++++++++++++++++++++
Msrc/json/json_helper.c | 32++++++++++++++++++++++++++++++++
Msrc/lib/exchange_api_handle.c | 2+-
Msrc/util/Makefile.am | 2+-
Msrc/util/config.c | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Msrc/util/currencies.conf | 10++++++++++
12 files changed, 158 insertions(+), 40 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd_config.c b/src/exchange/taler-exchange-httpd_config.c @@ -51,7 +51,7 @@ TEH_handler_config (struct TEH_RequestContext *rc, json_array ()), GNUNET_JSON_pack_object_steal ( "currency_specification", - TALER_CONFIG_currency_specs_to_json (TEH_cspec)), + TALER_JSON_currency_specs_to_json (TEH_cspec)), GNUNET_JSON_pack_string ( "currency", TEH_currency), diff --git a/src/exchange/taler-exchange-httpd_config.h b/src/exchange/taler-exchange-httpd_config.h @@ -41,7 +41,7 @@ * * Returned via both /config and /keys endpoints. */ -#define EXCHANGE_PROTOCOL_VERSION "30:0:8" +#define EXCHANGE_PROTOCOL_VERSION "30:2:8" /** diff --git a/src/exchange/taler-exchange-httpd_keys.c b/src/exchange/taler-exchange-httpd_keys.c @@ -2439,7 +2439,7 @@ create_krd (struct TEH_KeyStateHandle *ksh, TEH_bank_compliance_language)), GNUNET_JSON_pack_object_steal ( "currency_specification", - TALER_CONFIG_currency_specs_to_json (TEH_cspec)), + TALER_JSON_currency_specs_to_json (TEH_cspec)), GNUNET_JSON_pack_array_incref ( "hard_limits", TEH_hard_limits), diff --git a/src/include/taler/taler_json_lib.h b/src/include/taler/taler_json_lib.h @@ -285,6 +285,18 @@ TALER_JSON_from_amount (const struct TALER_Amount *amount); /** + * Convert a currency specification to the + * respective JSON object. + * + * @param cspec currency specification + * @return JSON object encoding @a cspec for `/config`. + */ +json_t * +TALER_JSON_currency_specs_to_json ( + const struct TALER_CurrencySpecification *cspec); + + +/** * Generate packer for a fixed length array (tuple) of packers. * The packers should be build with GNUNET_JSON_PACK. * diff --git a/src/include/taler/taler_util.h b/src/include/taler/taler_util.h @@ -256,6 +256,17 @@ struct TALER_CurrencySpecification */ json_t *map_alt_unit_names; + /** + * Amounts wallet should display as short-cuts (for example, + * in the withdraw dialog). + */ + struct TALER_Amount *common_amounts; + + /** + * Length of the @e common_amounts array. + */ + unsigned int num_common_amounts; + }; @@ -291,18 +302,6 @@ TALER_CONFIG_free_currencies ( /** - * Convert a currency specification to the - * respective JSON object. - * - * @param cspec currency specification - * @return JSON object encoding @a cspec for `/config`. - */ -json_t * -TALER_CONFIG_currency_specs_to_json ( - const struct TALER_CurrencySpecification *cspec); - - -/** * Check that @a map contains a valid currency scale * map that maps integers from [-12,24] to currency * symbols given as strings. diff --git a/src/json/Makefile.am b/src/json/Makefile.am @@ -17,7 +17,7 @@ libtalerjson_la_SOURCES = \ json_pack.c \ json_wire.c libtalerjson_la_LDFLAGS = \ - -version-info 5:1:1 \ + -version-info 6:0:2 \ -no-undefined libtalerjson_la_LIBADD = \ $(top_builddir)/src/util/libtalerutil.la \ diff --git a/src/json/json.c b/src/json/json.c @@ -896,4 +896,38 @@ TALER_JSON_extensions_manifests_hash (const json_t *manifests, } +json_t * +TALER_JSON_currency_specs_to_json ( + const struct TALER_CurrencySpecification *cspec) +{ + json_t *ca; + + ca = json_array (); + GNUNET_assert (NULL != ca); + for (unsigned int i = 0; i<cspec->num_common_amounts; i++) + GNUNET_assert ( + 0 == + json_array_append_new ( + ca, + TALER_JSON_from_amount (&cspec->common_amounts[i]))); + return GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("name", + cspec->name), + /* 'currency' is deprecated as of exchange v18 and merchant v6; + remove this line once current-age > 6*/ + GNUNET_JSON_pack_string ("currency", + cspec->currency), + GNUNET_JSON_pack_array_steal ("common_amounts", + ca), + GNUNET_JSON_pack_uint64 ("num_fractional_input_digits", + cspec->num_fractional_input_digits), + GNUNET_JSON_pack_uint64 ("num_fractional_normal_digits", + cspec->num_fractional_normal_digits), + GNUNET_JSON_pack_uint64 ("num_fractional_trailing_zero_digits", + cspec->num_fractional_trailing_zero_digits), + GNUNET_JSON_pack_object_incref ("alt_unit_names", + cspec->map_alt_unit_names)); +} + + /* End of json/json.c */ diff --git a/src/json/json_helper.c b/src/json/json_helper.c @@ -168,6 +168,7 @@ parse_cspec (void *cls, uint32_t fnd; uint32_t ftzd; const json_t *map; + const json_t *ca; struct GNUNET_JSON_Specification gspec[] = { GNUNET_JSON_spec_string ("name", &name), @@ -179,6 +180,8 @@ parse_cspec (void *cls, &ftzd), GNUNET_JSON_spec_object_const ("alt_unit_names", &map), + GNUNET_JSON_spec_array_const ("common_amounts", + &ca), GNUNET_JSON_spec_end () }; const char *emsg; @@ -229,6 +232,35 @@ parse_cspec (void *cls, } r_cspec->name = GNUNET_strdup (name); r_cspec->map_alt_unit_names = json_incref ((json_t *) map); + { + size_t i; + json_t *v; + + json_array_foreach ((json_t *) ca, i, v) + { + struct TALER_Amount val; + const char *vstr; + + vstr = json_string_value (v); + if ( (NULL == vstr) || + (GNUNET_OK != + TALER_string_to_amount (vstr, + &val)) ) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (0 != strcasecmp (val.currency, + r_cspec->currency)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + GNUNET_array_append (r_cspec->common_amounts, + r_cspec->num_common_amounts, + val); + } + } return GNUNET_OK; } diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c @@ -2593,7 +2593,7 @@ TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd) GNUNET_JSON_pack_string ("currency", kd->currency), GNUNET_JSON_pack_object_steal ("currency_specification", - TALER_CONFIG_currency_specs_to_json ( + TALER_JSON_currency_specs_to_json ( &kd->cspec)), TALER_JSON_pack_amount ("stefan_abs", &kd->stefan_abs), diff --git a/src/util/Makefile.am b/src/util/Makefile.am @@ -126,7 +126,7 @@ libtalerutil_la_LIBADD = \ -lm libtalerutil_la_LDFLAGS = \ - -version-info 8:0:0 \ + -version-info 9:0:0 \ -no-undefined diff --git a/src/util/config.c b/src/util/config.c @@ -23,6 +23,7 @@ #include "taler/taler_util.h" #include <gnunet/gnunet_json_lib.h> + enum GNUNET_GenericReturnValue TALER_config_get_amount (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, @@ -280,6 +281,55 @@ parse_currencies_cb (void *cls, cspec->name = str; if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cpc->cfg, + section, + "COMMON_AMOUNTS", + &str)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING, + section, + "COMMON_AMOUNTS"); + } + else + { + for (const char *tok = strtok (str, + " "); + NULL != tok; + tok = strtok (NULL, + " ")) + { + struct TALER_Amount val; + + if (GNUNET_OK != + TALER_string_to_amount (tok, + &val)) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + section, + "COMMON_AMOUNTS", + tok); + GNUNET_free (str); + cpc->failure = true; + return; + } + if (0 != strcasecmp (val.currency, + cspec->currency)) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + section, + "COMMON_AMOUNTS", + "currency mismatch"); + GNUNET_free (str); + cpc->failure = true; + return; + } + GNUNET_array_append (cspec->common_amounts, + cspec->num_common_amounts, + val); + } + GNUNET_free (str); + } + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cpc->cfg, section, "FRACTIONAL_INPUT_DIGITS", @@ -516,28 +566,6 @@ TALER_CONFIG_parse_currencies (const struct GNUNET_CONFIGURATION_Handle *cfg, } -json_t * -TALER_CONFIG_currency_specs_to_json (const struct - TALER_CurrencySpecification *cspec) -{ - return GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("name", - cspec->name), - /* 'currency' is deprecated as of exchange v18 and merchant v6; - remove this line once current-age > 6*/ - GNUNET_JSON_pack_string ("currency", - cspec->currency), - GNUNET_JSON_pack_uint64 ("num_fractional_input_digits", - cspec->num_fractional_input_digits), - GNUNET_JSON_pack_uint64 ("num_fractional_normal_digits", - cspec->num_fractional_normal_digits), - GNUNET_JSON_pack_uint64 ("num_fractional_trailing_zero_digits", - cspec->num_fractional_trailing_zero_digits), - GNUNET_JSON_pack_object_incref ("alt_unit_names", - cspec->map_alt_unit_names)); -} - - void TALER_CONFIG_free_currencies ( unsigned int num_currencies, @@ -549,6 +577,9 @@ TALER_CONFIG_free_currencies ( GNUNET_free (cspec->name); json_decref (cspec->map_alt_unit_names); + GNUNET_array_grow (cspec->common_amounts, + cspec->num_common_amounts, + 0); } GNUNET_array_grow (cspecs, num_currencies, diff --git a/src/util/currencies.conf b/src/util/currencies.conf @@ -6,6 +6,7 @@ fractional_input_digits = 2 fractional_normal_digits = 2 fractional_trailing_zero_digits = 2 alt_unit_names = {"0":"€"} +common_amounts = "EUR:5 EUR:10 EUR:25 EUR:50" [currency-swiss-francs] ENABLED = YES @@ -15,6 +16,7 @@ fractional_input_digits = 2 fractional_normal_digits = 2 fractional_trailing_zero_digits = 2 alt_unit_names = {"0":"Fr.","-2":"Rp."} +common_amounts = "CHF:5 CHF:10 CHF:25 CHF:50" [currency-forint] ENABLED = NO @@ -24,6 +26,7 @@ fractional_input_digits = 0 fractional_normal_digits = 0 fractional_trailing_zero_digits = 0 alt_unit_names = {"0":"Ft"} +common_amounts = "HUF:100 HUF:500 HUF:1000 HUF:5000" [currency-us-dollar] ENABLED = NO @@ -33,6 +36,7 @@ fractional_input_digits = 2 fractional_normal_digits = 2 fractional_trailing_zero_digits = 2 alt_unit_names = {"0":"$"} +common_amounts = "USD:5 USD:10 USD:25 USD:50" [currency-kudos] ENABLED = YES @@ -42,6 +46,7 @@ fractional_input_digits = 2 fractional_normal_digits = 2 fractional_trailing_zero_digits = 2 alt_unit_names = {"0":"ク"} +common_amounts = "KUDOS:5 KUDOS:10 KUDOS:25 KUDOS:50" [currency-testkudos] ENABLED = YES @@ -51,6 +56,7 @@ fractional_input_digits = 2 fractional_normal_digits = 2 fractional_trailing_zero_digits = 2 alt_unit_names = {"0":"テ","3":"kテ","-3":"mテ"} +common_amounts = "TESTKUDOS:5 TESTKUDOS:10 TESTKUDOS:25 TESTKUDOS:50" [currency-japanese-yen] ENABLED = NO @@ -60,6 +66,7 @@ fractional_input_digits = 2 fractional_normal_digits = 0 fractional_trailing_zero_digits = 2 alt_unit_names = {"0":"¥"} +common_amounts = "JPY:1000 JPY:5000 JPY:10000 JPY:20000" [currency-bitcoin-mainnet] ENABLED = NO @@ -69,6 +76,7 @@ fractional_input_digits = 8 fractional_normal_digits = 3 fractional_trailing_zero_digits = 0 alt_unit_names = {"0":"BTC","-3":"mBTC"} +common_amounts = "BITCOINBTC:0.001 BITCOINBTC:0.01 BITCOINBTC:0.02 BITCOINBTC:0.025" [currency-ethereum] ENABLED = NO @@ -78,6 +86,7 @@ fractional_input_digits = 0 fractional_normal_digits = 0 fractional_trailing_zero_digits = 0 alt_unit_names = {"0":"WAI","3":"KWAI","6":"MWAI","9":"GWAI","12":"Szabo","15":"Finney","18":"Ether","21":"KEther","24":"MEther"} +common_amounts = "EthereumWAI:0.001 EthereumWAI:0.01" [currency-netzbon] ENABLED=YES @@ -87,3 +96,4 @@ fractional_input_digits=2 fractional_normal_digits=2 fractional_trailing_zero_digits=2 alt_unit_names = {"0":"NETZBON"} +common_amounts = "NETZBON:5 NETZBON:10 NETZBON:25 NETZBON:50"