063-libeufin-conversion-rate-classes.rst (7590B)
1 DD 63: LibEufin Conversion Rate Class 2 ##################################### 3 4 :Design status: Accepted 5 :Implementation status: Implemented 6 :DD shepherd: TBD 7 :Historical contributors: Antoine A, Sebastian, Florian Dold 8 :First published: 2025-05-12 9 :Last substantive change: 2025-07-01 10 :Implementation evidence: libeufin (2025-07-16) 11 :Normative references: ``core/api-corebank.rst``, ``core/api-bank-conversion-info.rst`` 12 13 .. note:: 14 15 API version numbers and endpoint descriptions below record the migration 16 plan. The current Core Bank and Conversion API specifications are 17 normative. 18 19 Summary 20 ======= 21 22 We need an efficient solution to set specific conversion rates for some users. By efficient this means you do not have to set or update them manually for all accounts and a good way to see what are the current rates and which accounts use them. 23 24 Proposed Solution 25 ================= 26 27 The current global conversion rate schema is: 28 29 .. ts:def:: ConversionRate 30 31 interface ConversionRate { 32 // Minimum fiat amount authorised for cashin before conversion 33 cashin_min_amount: Amount; 34 35 // Exchange rate to buy regional currency from fiat 36 cashin_ratio: DecimalNumber; 37 38 // Regional amount fee to subtract after applying the cashin ratio. 39 cashin_fee: Amount; 40 41 // Rounding mode used during cashin conversion 42 cashin_rounding_mode: "zero" | "up" | "nearest"; 43 44 // Smallest possible fiat amount, converted amount is rounded to this amount 45 cashin_tiny_amount: Amount; 46 47 // Minimum regional amount authorised for cashout before conversion 48 cashout_min_amount: Amount; 49 50 // Exchange rate to sell regional currency for fiat 51 cashout_ratio: DecimalNumber; 52 53 // Fiat amount fee to subtract after applying the cashout ratio. 54 cashout_fee: Amount; 55 56 // Rounding mode used during cashout conversion 57 cashout_rounding_mode: "zero" | "up" | "nearest"; 58 59 // Smallest possible fiat amount, converted amount is rounded to this amount 60 cashout_tiny_amount: Amount; 61 62 } 63 64 This would become the ``default`` class with ``conversion_rate_class_id = 0``, that will be used by all new users that are created with ``conversion_rate_class_id = null`` or updated with a PATCH request with ``conversion_rate_class_id = null``. The administrator would be able to create new classes with values that override some of the default properties: 65 66 .. ts:def:: ConversionRateClassRequest 67 68 interface ConversionRateClassRequest { 69 // The name of this class 70 name: string; 71 72 // A description of the class 73 description?: string; 74 75 // Minimum fiat amount authorised for cashin before conversion 76 cashin_min_amount?: Amount; 77 78 // Exchange rate to buy regional currency from fiat 79 cashin_ratio?: DecimalNumber; 80 81 // Regional amount fee to subtract after applying the cashin ratio. 82 cashin_fee?: Amount; 83 84 // Rounding mode used during cashin conversion 85 cashin_rounding_mode?: "zero" | "up" | "nearest"; 86 87 // Minimum regional amount authorised for cashout before conversion 88 cashout_min_amount?: Amount; 89 90 // Exchange rate to sell regional currency for fiat 91 cashout_ratio?: DecimalNumber; 92 93 // Fiat amount fee to subtract after applying the cashout ratio. 94 cashout_fee?: Amount; 95 96 // Rounding mode used during cashout conversion 97 cashout_rounding_mode?: "zero" | "up" | "nearest"; 98 } 99 100 .. ts:def:: ConversionRateClass 101 102 interface ConversionRateClass { 103 // The name of this class 104 name: string; 105 106 // A description of the class 107 description?: string; 108 109 // Class unique ID 110 conversion_rate_class_id: Integer; 111 112 // Number of users affected to this class 113 num_users: Integer; 114 115 // Applied conversion rate 116 conversion_rate: ConversionRate; 117 118 // Minimum fiat amount authorised for cashin before conversion 119 cashin_min_amount?: Amount; 120 121 // Exchange rate to buy regional currency from fiat 122 cashin_ratio?: DecimalNumber; 123 124 // Regional amount fee to subtract after applying the cashin ratio. 125 cashin_fee?: Amount; 126 127 // Rounding mode used during cashin conversion 128 cashin_rounding_mode?: "zero" | "up" | "nearest"; 129 130 // Minimum regional amount authorised for cashout before conversion 131 cashout_min_amount?: Amount; 132 133 // Exchange rate to sell regional currency for fiat 134 cashout_ratio?: DecimalNumber; 135 136 // Fiat amount fee to subtract after applying the cashout ratio. 137 cashout_fee?: Amount; 138 139 // Rounding mode used during cashout conversion 140 cashout_rounding_mode?: "zero" | "up" | "nearest"; 141 } 142 143 .. ts:def:: ConversionRateClasses 144 145 interface ConversionRateClasses { 146 default: ConversionRate; 147 classes: ConversionRateClass[]; 148 } 149 150 151 After creating a new converion class, that needs to be associated with the user. 152 153 When we run the conversion logic we take values from the user class and fallback to the default values when they are ``null``. 154 155 If an admin want to prevent a group of user or exchanges from doing conversion between currencies then those users should be associated with a conversion class with ``cashin_ratio = 0`` to disable any cashin operation or ``cashout_ratio = 0`` to disable any cashout operation. 156 157 158 Taler Conversion Info API 159 ------------------------- 160 161 The version changes to v2. 162 163 The migration moved the conversion-info API from ``/conversion-info/*`` to 164 ``/accounts/$USERNAME/conversion-info/*`` to take user-specific conversion 165 rates into account. 166 167 A ``/rate`` to get, the potentially private, user specific conversion rate. 168 169 Taler Core Bank API 170 ------------------- 171 172 The design targeted Core Bank API v9. The current normative Core Bank API has 173 since advanced beyond that version. 174 175 Deprecated API that should not longer be used: 176 177 178 Removed the field ``min_cashout``, not longer used. Replaced by a convertion rate class reference. 179 180 Removed sub-api ``/conversion-info/*`` 181 182 183 We added new endpoints for conversion rate class management, only accesible by the admin user: 184 185 POST ``/conversion-rate-classes`` 186 187 GET ``/conversion-rate-classes`` 188 189 GET ``/conversion-rate-classes/$CLASS-ID`` 190 191 PATCH ``/conversion-rate-classes/$CLASS-ID`` 192 193 DELETE ``/conversion-rate-classes/$CLASS-ID`` 194 195 Added an admin-only ``conversion_rate_class_id`` field of type ``Integer``. It is optional field to POST ``/accounts`` requests (creating an account) and PATCH ``/accounts/$USERNAME`` requests (updating an account). 196 197 198 199 Added query filter to GET ``/accounts`` (listing accounts) 200 201 Added ``conversion_rate_class`` field of type ``AccountConversionRateClass`` of GET ``/accounts/$USERNAME`` request with all the information about the convertion rate. ``conversion_rate_class_id`` points to the class assigned to the user but the values of the fields could be from the default class if the assigned class is not completed. 202 203 204 205 Added sub-api ``/conversion-rate-class/$CLASS-ID/conversion-info/*``. This is used by admin to run simulations to know how the conversion rate behaves regartherless of the user on the group. 206 207 Added sub-api ``/accounts/$USERNAME/conversion-info/*``. This is used by normal users get the right convertion rate for it's own operations. For user with ``is_taler_exchange = true`` this sub-api will be public. 208 209 210 211 There are also new error code reported by the API, like ``TALER_EC_BANK_CONVERSION_RATE_CLASS_UNKNOWN`` when the client is trying to create or update an account. 212 213 Specification follow-up 214 ^^^^^^^^^^^^^^^^^^^^^^^ 215 216 The conversion-rate-class endpoints and error codes are now part of the 217 normative Core Bank API. Clients should use that specification rather than 218 the historical endpoint inventory above.