diff --git a/src/exchange/exchange.conf b/src/exchange/exchange.conf index 2dd934f4e..590b9c39f 100644 --- a/src/exchange/exchange.conf +++ b/src/exchange/exchange.conf @@ -87,6 +87,10 @@ PRIVACY_ETAG = 0 # Set to "OAUTH2" to use OAuth 2.0 for KYC authorization. KYC_MODE = NONE +# Balance threshold above which wallets are told +# to undergo a KYC check at the exchange. Optional, +# if not given there is no limit. +# KYC_WALLET_BALANCE_LIMIT = 150:CURRENCY [exchange-kyc-oauth2] diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c index 9f0abb0e3..e9aa94c0a 100644 --- a/src/exchange/taler-exchange-httpd.c +++ b/src/exchange/taler-exchange-httpd.c @@ -1279,6 +1279,35 @@ exchange_serve_process_config (void) "CURRENCY"); return GNUNET_SYSERR; } + if (TEH_KYC_NONE != TEH_kyc_config.mode) + { + if (GNUNET_YES == + GNUNET_CONFIGURATION_have_value (TEH_cfg, + "exchange", + "KYC_WALLET_BALANCE_LIMIT")) + { + if ( (GNUNET_OK != + TALER_config_get_amount (TEH_cfg, + "exchange", + "KYC_WALLET_BALANCE_LIMIT", + &TEH_kyc_config.wallet_balance_limit)) || + (0 != strcasecmp (TEH_currency, + TEH_kyc_config.wallet_balance_limit.currency)) ) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + "exchange", + "KYC_WALLET_BALANCE_LIMIT", + "valid amount expected"); + return GNUNET_SYSERR; + } + } + else + { + memset (&TEH_kyc_config.wallet_balance_limit, + 0, + sizeof (TEH_kyc_config.wallet_balance_limit)); + } + } { char *master_public_key_str; diff --git a/src/exchange/taler-exchange-httpd.h b/src/exchange/taler-exchange-httpd.h index 7c95c9dc0..3f934dbd5 100644 --- a/src/exchange/taler-exchange-httpd.h +++ b/src/exchange/taler-exchange-httpd.h @@ -64,6 +64,14 @@ struct TEH_KycOptions */ struct TALER_Amount withdraw_limit; + /** + * Maximum balance a wallet can hold without + * needing KYC. + * Only valid if @e mode is not #TEH_KYC_NONE and + * if the amount specified is valid. + */ + struct TALER_Amount wallet_balance_limit; + /** * Time period over which @e withdraw_limit applies. * Only valid if @e mode is not #TEH_KYC_NONE. diff --git a/src/exchange/taler-exchange-httpd_keys.c b/src/exchange/taler-exchange-httpd_keys.c index 0e0005305..99c727450 100644 --- a/src/exchange/taler-exchange-httpd_keys.c +++ b/src/exchange/taler-exchange-httpd_keys.c @@ -1473,6 +1473,18 @@ create_krd (struct TEH_KeyStateHandle *ksh, GNUNET_JSON_pack_data_auto ("eddsa_sig", &exchange_sig)); GNUNET_assert (NULL != keys); + if ( (TEH_KYC_NONE != TEH_kyc_config.mode) && + (GNUNET_OK == + TALER_amount_is_valid (&TEH_kyc_config.wallet_balance_limit)) ) + { + GNUNET_assert ( + 0 == + json_object_set_new ( + keys, + "wallet_balance_limit_without_kyc", + TALER_JSON_from_amount ( + &TEH_kyc_config.wallet_balance_limit))); + } { char *keys_json; diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h index d861dbe85..2bfb08547 100644 --- a/src/include/taler_exchange_service.h +++ b/src/include/taler_exchange_service.h @@ -264,6 +264,12 @@ struct TALER_EXCHANGE_Keys */ struct GNUNET_TIME_Relative reserve_closing_delay; + /** + * Maximum amount a wallet is allowed to hold from + * this exchange before it must undergo a KYC check. + */ + struct TALER_Amount wallet_balance_limit_without_kyc; + /** * Timestamp indicating the /keys generation. */ diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c index 142ed18e6..5ce5285d0 100644 --- a/src/lib/exchange_api_handle.c +++ b/src/lib/exchange_api_handle.c @@ -685,8 +685,6 @@ decode_keys_json (const json_t *resp_obj, &sig), GNUNET_JSON_spec_fixed_auto ("eddsa_pub", &pub), - /* sig and pub must be first, as we skip those if - check_sig is false! */ GNUNET_JSON_spec_fixed_auto ("master_public_key", &key_data->master_pub), TALER_JSON_spec_absolute_time ("list_issue_date", @@ -695,6 +693,10 @@ decode_keys_json (const json_t *resp_obj, &key_data->reserve_closing_delay), GNUNET_JSON_spec_string ("currency", ¤cy), + GNUNET_JSON_spec_mark_optional ( + TALER_JSON_spec_amount ("wallet_balance_limit_without_kyc", + currency, + &key_data->wallet_balance_limit_without_kyc)), GNUNET_JSON_spec_end () };