10.63. DD 63: LibEufin Conversion Rate Class#

10.63.1. Summary#

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.

10.63.2. Proposed Solution#

The current global conversion rate schema is:

interface ConversionRate {
  // Minimum fiat amount authorised for cashin before conversion
  cashin_min_amount: Amount;

  // Exchange rate to buy regional currency from fiat
  cashin_ratio: DecimalNumber;

  // Regional amount fee to subtract after applying the cashin ratio.
  cashin_fee: Amount;

  // Rounding mode used during cashin conversion
  cashin_rounding_mode: "zero" | "up" | "nearest";

  // Smallest possible fiat amount, converted amount is rounded to this amount
  cashin_tiny_amount: Amount;

  // Minimum regional amount authorised for cashout before conversion
  cashout_min_amount: Amount;

  // Exchange rate to sell regional currency for fiat
  cashout_ratio: DecimalNumber;

  // Fiat amount fee to subtract after applying the cashout ratio.
  cashout_fee: Amount;

  // Rounding mode used during cashout conversion
  cashout_rounding_mode: "zero" | "up" | "nearest";

  // Smallest possible fiat amount, converted amount is rounded to this amount
  cashout_tiny_amount: Amount;

}

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:

interface ConversionRateClassRequest {
  // The name of this class
  name: string;

  // A description of the class
  description?: string;

  // Minimum fiat amount authorised for cashin before conversion
  cashin_min_amount?: Amount;

  // Exchange rate to buy regional currency from fiat
  cashin_ratio?: DecimalNumber;

  // Regional amount fee to subtract after applying the cashin ratio.
  cashin_fee?: Amount;

  // Rounding mode used during cashin conversion
  cashin_rounding_mode?: "zero" | "up" | "nearest";

  // Minimum regional amount authorised for cashout before conversion
  cashout_min_amount?: Amount;

  // Exchange rate to sell regional currency for fiat
  cashout_ratio?: DecimalNumber;

  // Fiat amount fee to subtract after applying the cashout ratio.
  cashout_fee?: Amount;

  // Rounding mode used during cashout conversion
  cashout_rounding_mode?: "zero" | "up" | "nearest";
}
interface ConversionRateClass {
  // The name of this class
  name: string;

  // A description of the class
  description?: string;

  // Class unique ID
  conversion_rate_class_id: Integer;

  // Number of users affected to this class
  num_users: Integer;

  // Applied conversion rate
  conversion_rate: ConversionRate;

  // Minimum fiat amount authorised for cashin before conversion
  cashin_min_amount?: Amount;

  // Exchange rate to buy regional currency from fiat
  cashin_ratio?: DecimalNumber;

  // Regional amount fee to subtract after applying the cashin ratio.
  cashin_fee?: Amount;

  // Rounding mode used during cashin conversion
  cashin_rounding_mode?: "zero" | "up" | "nearest";

  // Minimum regional amount authorised for cashout before conversion
  cashout_min_amount?: Amount;

  // Exchange rate to sell regional currency for fiat
  cashout_ratio?: DecimalNumber;

  // Fiat amount fee to subtract after applying the cashout ratio.
  cashout_fee?: Amount;

  // Rounding mode used during cashout conversion
  cashout_rounding_mode?: "zero" | "up" | "nearest";
}
interface ConversionRateClasses {
  default: ConversionRate;
  classes: ConversionRateClass[];
}

After creating a new converion class, that needs to be associated with the user.

When we run the conversion logic we take values from the user class and fallback to the default values when they are null.

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.

10.63.2.1. Taler Conversion Info API#

The version changes to v2.

We need to move the current conversion-info API from /conversion-info/* to /accounts/$USERNAME/conversion-info/* to take into account user specific conversion rate.

A /rate to get, the potentially private, user specific conversion rate.

10.63.2.2. Taler Core Bank API#

The version changes to v9.

Deprecated API that should not longer be used:

Removed the field min_cashout, not longer used. Replaced by a convertion rate class reference.

Removed sub-api /conversion-info/*

We added new endpoints for conversion rate class management, only accesible by the admin user:

POST /conversion-rate-classes

GET /conversion-rate-classes

GET /conversion-rate-classes/$CLASS-ID

PATCH /conversion-rate-classes/$CLASS-ID

DELETE /conversion-rate-classes/$CLASS-ID

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).

Added query filter to GET /accounts (listing accounts)

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.

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.

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.

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.

10.63.2.2.1. TODO: Add to the spec#

  • Add missing error code so the client can create better error message for those