libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

commit 0dbf446b4f07778ac8556b483dcda65b66402b78
parent 2bc6907cb1f3b1bb6b207e85294bfa57c28bb2e9
Author: Antoine A <>
Date:   Fri, 10 Nov 2023 12:10:13 +0000

Replace 'internal' and 'external' with 'regional' and 'fiat'

Diffstat:
M.gitignore | 1+
Mbank/conf/test.conf | 2+-
Mbank/conf/test_no_tan.conf | 2+-
Mbank/src/main/kotlin/tech/libeufin/bank/Config.kt | 18+++++++++---------
Mbank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt | 24++++++++++++------------
Mbank/src/main/kotlin/tech/libeufin/bank/Error.kt | 10+++++-----
Mbank/src/main/kotlin/tech/libeufin/bank/Main.kt | 4++--
Mbank/src/main/kotlin/tech/libeufin/bank/TalerMessage.kt | 12++++++------
Mbank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt | 4++--
Mbank/src/main/kotlin/tech/libeufin/bank/db/CashoutDAO.kt | 2+-
Mbank/src/main/kotlin/tech/libeufin/bank/db/ConversionDAO.kt | 4++--
Mbank/src/main/kotlin/tech/libeufin/bank/db/Database.kt | 44++++++++++++++++++++++----------------------
Mbank/src/test/kotlin/StatsTest.kt | 26+++++++++++++-------------
Mbank/src/test/kotlin/helpers.kt | 2+-
Mdatabase-versioning/libeufin-bank-0001.sql | 26+++++++++++++-------------
Mdatabase-versioning/libeufin-bank-procedures.sql | 56++++++++++++++++++++++++++++----------------------------
16 files changed, 119 insertions(+), 118 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,4 +1,5 @@ .idea/* +.vscode /nexus/bin/ /sandbox/bin/ /util/bin/ diff --git a/bank/conf/test.conf b/bank/conf/test.conf @@ -5,7 +5,7 @@ DEFAULT_ADMIN_DEBT_LIMIT = KUDOS:10000 REGISTRATION_BONUS_ENABLED = NO SUGGESTED_WITHDRAWAL_EXCHANGE = https://exchange.example.com have_cashout = YES -external_currency = FIAT +fiat_currency = FIAT tan_sms = libeufin-tan-file.sh tan_email = libeufin-tan-fail.sh diff --git a/bank/conf/test_no_tan.conf b/bank/conf/test_no_tan.conf @@ -5,7 +5,7 @@ DEFAULT_ADMIN_DEBT_LIMIT = KUDOS:10000 REGISTRATION_BONUS_ENABLED = NO SUGGESTED_WITHDRAWAL_EXCHANGE = https://exchange.example.com have_cashout = YES -external_currency = FIAT +fiat_currency = FIAT [libeufin-bankdb-postgres] SQL_DIR = $DATADIR/sql/ diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Config.kt b/bank/src/main/kotlin/tech/libeufin/bank/Config.kt @@ -36,7 +36,7 @@ private val BANK_CONFIG_SOURCE = ConfigSource("libeufin-bank", "libeufin-bank") */ data class BankConfig( /** - * Main, internal currency of the bank. + * Main, regional currency of the bank. */ val currency: String, val currencySpecification: CurrencySpecification, @@ -78,7 +78,7 @@ data class BankConfig( */ val spaCaptchaURL: String?, val haveCashout: Boolean, - val externalCurrency: String?, + val fiatCurrency: String?, val conversionInfo: ConversionInfo?, val tanSms: String?, val tanEmail: String?, @@ -128,12 +128,12 @@ fun TalerConfig.loadBankConfig(): BankConfig = catchError { val currencySpecification = sections.find { it.startsWith("CURRENCY-") && requireBoolean(it, "enabled") && requireString(it, "code") == currency }?.let { loadCurrencySpecification(it) } ?: throw TalerConfigError("missing currency specification for $currency") - var externalCurrency: String? = null; + var fiatCurrency: String? = null; var conversionInfo: ConversionInfo? = null; val haveCashout = lookupBoolean("libeufin-bank", "have_cashout") ?: false; if (haveCashout) { - externalCurrency = requireString("libeufin-bank", "external_currency"); - conversionInfo = loadConversionInfo(currency, externalCurrency) + fiatCurrency = requireString("libeufin-bank", "fiat_currency"); + conversionInfo = loadConversionInfo(currency, fiatCurrency) } BankConfig( currency = currency, @@ -147,23 +147,23 @@ fun TalerConfig.loadBankConfig(): BankConfig = catchError { restrictAccountDeletion = lookupBoolean("libeufin-bank", "restrict_account_deletion") ?: true, currencySpecification = currencySpecification, haveCashout = haveCashout, - externalCurrency = externalCurrency, + fiatCurrency = fiatCurrency, conversionInfo = conversionInfo, tanSms = lookupPath("libeufin-bank", "tan_sms"), tanEmail = lookupPath("libeufin-bank", "tan_email"), ) } -private fun TalerConfig.loadConversionInfo(currency: String, externalCurrency: String): ConversionInfo = catchError { +private fun TalerConfig.loadConversionInfo(currency: String, fiatCurrency: String): ConversionInfo = catchError { ConversionInfo( buy_ratio = requireDecimalNumber("libeufin-bank-conversion", "buy_ratio"), buy_fee = requireDecimalNumber("libeufin-bank-conversion", "buy_fee"), buy_tiny_amount = amount("libeufin-bank-conversion", "buy_tiny_amount", currency) ?: TalerAmount(0, 1, currency), buy_rounding_mode = RoundingMode("libeufin-bank-conversion", "buy_rounding_mode") ?: RoundingMode.zero, - buy_min_amount = amount("libeufin-bank-conversion", "buy_min_amount", externalCurrency) ?: TalerAmount(0, 0, externalCurrency), + buy_min_amount = amount("libeufin-bank-conversion", "buy_min_amount", fiatCurrency) ?: TalerAmount(0, 0, fiatCurrency), sell_ratio = requireDecimalNumber("libeufin-bank-conversion", "sell_ratio"), sell_fee = requireDecimalNumber("libeufin-bank-conversion", "sell_fee"), - sell_tiny_amount = amount("libeufin-bank-conversion", "sell_tiny_amount", externalCurrency) ?: TalerAmount(0, 1, externalCurrency), + sell_tiny_amount = amount("libeufin-bank-conversion", "sell_tiny_amount", fiatCurrency) ?: TalerAmount(0, 1, fiatCurrency), sell_rounding_mode = RoundingMode("libeufin-bank-conversion", "sell_rounding_mode") ?: RoundingMode.zero, sell_min_amount = amount("libeufin-bank-conversion", "sell_min_amount", currency) ?: TalerAmount(0, 0, currency), ) diff --git a/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt @@ -47,7 +47,7 @@ fun Routing.coreBankApi(db: Database, ctx: BankConfig) { Config( currency = ctx.currencySpecification, have_cashout = ctx.haveCashout, - external_currency = ctx.externalCurrency, + fiat_currency = ctx.fiatCurrency, conversion_info = ctx.conversionInfo, allow_registrations = !ctx.restrictRegistration, allow_deletions = !ctx.restrictAccountDeletion @@ -218,7 +218,7 @@ private fun Routing.coreBankAccountsMgmtApi(db: Database, ctx: BankConfig) { auth(db, TokenScope.readwrite, allowAdmin = true) { patch("/accounts/{USERNAME}") { val req = call.receive<AccountReconfiguration>() - req.debit_threshold?.run { ctx.checkInternalCurrency(this) } + req.debit_threshold?.run { ctx.checkRegionalCurrency(this) } if (req.is_taler_exchange != null && username == "admin") throw forbidden("admin account cannot be an exchange") @@ -348,7 +348,7 @@ private fun Routing.coreBankTransactionsApi(db: Database, ctx: BankConfig) { val subject = tx.payto_uri.message ?: throw badRequest("Wire transfer lacks subject") val amount = tx.payto_uri.amount ?: tx.amount ?: throw badRequest("Wire transfer lacks amount") - ctx.checkInternalCurrency(amount) + ctx.checkRegionalCurrency(amount) val result = db.bankTransaction( creditAccountPayto = tx.payto_uri, debitAccountUsername = username, @@ -383,7 +383,7 @@ private fun Routing.coreBankWithdrawalApi(db: Database, ctx: BankConfig) { auth(db, TokenScope.readwrite) { post("/accounts/{USERNAME}/withdrawals") { val req = call.receive<BankAccountCreateWithdrawalRequest>() - ctx.checkInternalCurrency(req.amount) + ctx.checkRegionalCurrency(req.amount) val opId = UUID.randomUUID() when (db.withdrawal.create(username, opId, req.amount)) { WithdrawalCreationResult.ACCOUNT_NOT_FOUND -> throw notFound( @@ -475,8 +475,8 @@ private fun Routing.coreBankCashoutApi(db: Database, ctx: BankConfig) { post("/accounts/{USERNAME}/cashouts") { val req = call.receive<CashoutRequest>() - ctx.checkInternalCurrency(req.amount_debit) - ctx.checkexternalCurrency(req.amount_credit) + ctx.checkRegionalCurrency(req.amount_debit) + ctx.checkFiatCurrency(req.amount_credit) val tanChannel = req.tan_channel ?: TanChannel.sms val tanScript = when (tanChannel) { @@ -638,11 +638,11 @@ private fun Routing.coreBankCashoutApi(db: Database, ctx: BankConfig) { get("/cashout-rate") { val params = RateParams.extract(call.request.queryParameters) - params.debit?.let { ctx.checkInternalCurrency(it) } - params.credit?.let { ctx.checkexternalCurrency(it) } + params.debit?.let { ctx.checkRegionalCurrency(it) } + params.credit?.let { ctx.checkFiatCurrency(it) } if (params.debit != null) { - val credit = db.conversion.internalToExternal(params.debit) ?: + val credit = db.conversion.regionalToFiat(params.debit) ?: throw conflict( "${params.debit} is too small to be converted", TalerErrorCode.BANK_BAD_CONVERSION @@ -655,11 +655,11 @@ private fun Routing.coreBankCashoutApi(db: Database, ctx: BankConfig) { get("/cashin-rate") { val params = RateParams.extract(call.request.queryParameters) - params.debit?.let { ctx.checkexternalCurrency(it) } - params.credit?.let { ctx.checkInternalCurrency(it) } + params.debit?.let { ctx.checkFiatCurrency(it) } + params.credit?.let { ctx.checkRegionalCurrency(it) } if (params.debit != null) { - val credit = db.conversion.externalToInternal(params.debit) ?: + val credit = db.conversion.fiatToRegional(params.debit) ?: throw conflict( "${params.debit} is too small to be converted", TalerErrorCode.BANK_BAD_CONVERSION diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Error.kt b/bank/src/main/kotlin/tech/libeufin/bank/Error.kt @@ -84,16 +84,16 @@ fun badRequest( ): LibeufinBankException = libeufinError(HttpStatusCode.BadRequest, hint, error) -fun BankConfig.checkInternalCurrency(amount: TalerAmount) { +fun BankConfig.checkRegionalCurrency(amount: TalerAmount) { if (amount.currency != currency) throw badRequest( - "Wrong currency: expected internal currency $currency got ${amount.currency}", + "Wrong currency: expected regional currency $currency got ${amount.currency}", TalerErrorCode.GENERIC_CURRENCY_MISMATCH ) } -fun BankConfig.checkexternalCurrency(amount: TalerAmount) { - if (amount.currency != externalCurrency) throw badRequest( - "Wrong currency: expected external currency $externalCurrency got ${amount.currency}", +fun BankConfig.checkFiatCurrency(amount: TalerAmount) { + if (amount.currency != fiatCurrency) throw badRequest( + "Wrong currency: expected fiat currency $fiatCurrency got ${amount.currency}", TalerErrorCode.GENERIC_CURRENCY_MISMATCH ) } \ No newline at end of file diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt @@ -303,7 +303,7 @@ class ServeBank : CliktCommand("Run libeufin-bank HTTP server", name = "serve") logger.info("Can only serve libeufin-bank via TCP") exitProcess(1) } - val db = Database(dbCfg.dbConnStr, ctx.currency, ctx.externalCurrency) + val db = Database(dbCfg.dbConnStr, ctx.currency, ctx.fiatCurrency) runBlocking { if (!maybeCreateAdminAccount(db, ctx)) // logs provided by the helper exitProcess(1) @@ -326,7 +326,7 @@ class ChangePw : CliktCommand("Change account password", name = "passwd") { val cfg = talerConfig(configFile) val ctx = cfg.loadBankConfig() val dbCfg = cfg.loadDbConfig() - val db = Database(dbCfg.dbConnStr, ctx.currency, ctx.externalCurrency) + val db = Database(dbCfg.dbConnStr, ctx.currency, ctx.fiatCurrency) runBlocking { if (!maybeCreateAdminAccount(db, ctx)) // logs provided by the helper exitProcess(1) diff --git a/bank/src/main/kotlin/tech/libeufin/bank/TalerMessage.kt b/bank/src/main/kotlin/tech/libeufin/bank/TalerMessage.kt @@ -95,7 +95,7 @@ data class RegisterAccountRequest( val is_public: Boolean = false, val is_taler_exchange: Boolean = false, val challenge_contact_data: ChallengeContactData? = null, - // External bank account where to send cashout amounts. + // Fiat bank account where to send cashout amounts. val cashout_payto_uri: IbanPayTo? = null, // Bank account internal to Libeufin-Bank. val internal_payto_uri: IbanPayTo? = null @@ -145,11 +145,11 @@ data class MonitorNoConversion( @SerialName("with-conversions") data class MonitorWithConversion( val cashinCount: Long, - val cashinInternalVolume: TalerAmount, - val cashinExternalVolume: TalerAmount, + val cashinRegionalVolume: TalerAmount, + val cashinFiatVolume: TalerAmount, val cashoutCount: Long, - val cashoutInternalVolume: TalerAmount, - val cashoutExternalVolume: TalerAmount, + val cashoutRegionalVolume: TalerAmount, + val cashoutFiatVolume: TalerAmount, override val talerInCount: Long, override val talerInVolume: TalerAmount, override val talerOutCount: Long, @@ -254,7 +254,7 @@ data class TalerWithdrawalOperation( data class Config( val currency: CurrencySpecification, val have_cashout: Boolean, - val external_currency: String?, + val fiat_currency: String?, val conversion_info: ConversionInfo?, val allow_registrations: Boolean, val allow_deletions: Boolean diff --git a/bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt @@ -45,7 +45,7 @@ fun Routing.wireGatewayApi(db: Database, ctx: BankConfig) { auth(db, TokenScope.readwrite) { post("/accounts/{USERNAME}/taler-wire-gateway/transfer") { val req = call.receive<TransferRequest>() - ctx.checkInternalCurrency(req.amount) + ctx.checkRegionalCurrency(req.amount) val dbRes = db.exchange.transfer( req = req, username = username, @@ -117,7 +117,7 @@ fun Routing.wireGatewayApi(db: Database, ctx: BankConfig) { authAdmin(db, TokenScope.readwrite) { post("/accounts/{USERNAME}/taler-wire-gateway/admin/add-incoming") { val req = call.receive<AddIncomingRequest>() - ctx.checkInternalCurrency(req.amount) + ctx.checkRegionalCurrency(req.amount) val timestamp = Instant.now() val dbRes = db.exchange.addIncoming( req = req, diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/CashoutDAO.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/CashoutDAO.kt @@ -234,7 +234,7 @@ class CashoutDAO(private val db: Database) { amount_credit = TalerAmount( value = it.getLong("amount_credit_val"), frac = it.getInt("amount_credit_frac"), - db.externalCurrency!! + db.fiatCurrency!! ), subject = it.getString("subject"), creation_time = TalerProtocolTimestamp( diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/ConversionDAO.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/ConversionDAO.kt @@ -82,6 +82,6 @@ class ConversionDAO(private val db: Database) { } } - suspend fun internalToExternal(amount: TalerAmount): TalerAmount? = conversion(amount, "sell", db.externalCurrency!!) - suspend fun externalToInternal(amount: TalerAmount): TalerAmount? = conversion(amount, "buy", db.bankCurrency) + suspend fun regionalToFiat(amount: TalerAmount): TalerAmount? = conversion(amount, "sell", db.fiatCurrency!!) + suspend fun fiatToRegional(amount: TalerAmount): TalerAmount? = conversion(amount, "buy", db.bankCurrency) } \ No newline at end of file diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/Database.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/Database.kt @@ -55,7 +55,7 @@ private val logger: Logger = LoggerFactory.getLogger("tech.libeufin.bank.Databas internal fun faultyTimestampByBank() = internalServerError("Bank took overflowing timestamp") internal fun faultyDurationByClient() = badRequest("Overflowing duration, please specify 'forever' instead.") -class Database(dbConfig: String, internal val bankCurrency: String, internal val externalCurrency: String?): java.io.Closeable { +class Database(dbConfig: String, internal val bankCurrency: String, internal val fiatCurrency: String?): java.io.Closeable { val dbPool: HikariDataSource internal val notifWatcher: NotificationWatcher @@ -847,15 +847,15 @@ class Database(dbConfig: String, internal val bankCurrency: String, internal val val stmt = conn.prepareStatement(""" SELECT cashin_count - ,(cashin_internal_volume).val as cashin_internal_volume_val - ,(cashin_internal_volume).frac as cashin_internal_volume_frac - ,(cashin_external_volume).val as cashin_external_volume_val - ,(cashin_external_volume).frac as cashin_external_volume_frac + ,(cashin_regional_volume).val as cashin_regional_volume_val + ,(cashin_regional_volume).frac as cashin_regional_volume_frac + ,(cashin_fiat_volume).val as cashin_fiat_volume_val + ,(cashin_fiat_volume).frac as cashin_fiat_volume_frac ,cashout_count - ,(cashout_internal_volume).val as cashout_internal_volume_val - ,(cashout_internal_volume).frac as cashout_internal_volume_frac - ,(cashout_external_volume).val as cashout_external_volume_val - ,(cashout_external_volume).frac as cashout_external_volume_frac + ,(cashout_regional_volume).val as cashout_regional_volume_val + ,(cashout_regional_volume).frac as cashout_regional_volume_frac + ,(cashout_fiat_volume).val as cashout_fiat_volume_val + ,(cashout_fiat_volume).frac as cashout_fiat_volume_frac ,taler_in_count ,(taler_in_volume).val as taler_in_volume_val ,(taler_in_volume).frac as taler_in_volume_frac @@ -871,28 +871,28 @@ class Database(dbConfig: String, internal val bankCurrency: String, internal val stmt.setNull(2, java.sql.Types.INTEGER) } stmt.oneOrNull { - externalCurrency?.run { + fiatCurrency?.run { MonitorWithConversion( cashinCount = it.getLong("cashin_count"), - cashinInternalVolume = TalerAmount( - value = it.getLong("cashin_internal_volume_val"), - frac = it.getInt("cashin_internal_volume_frac"), + cashinRegionalVolume = TalerAmount( + value = it.getLong("cashin_regional_volume_val"), + frac = it.getInt("cashin_regional_volume_frac"), currency = bankCurrency ), - cashinExternalVolume = TalerAmount( - value = it.getLong("cashin_external_volume_val"), - frac = it.getInt("cashin_external_volume_frac"), + cashinFiatVolume = TalerAmount( + value = it.getLong("cashin_fiat_volume_val"), + frac = it.getInt("cashin_fiat_volume_frac"), currency = this ), cashoutCount = it.getLong("cashout_count"), - cashoutInternalVolume = TalerAmount( - value = it.getLong("cashout_internal_volume_val"), - frac = it.getInt("cashout_internal_volume_frac"), + cashoutRegionalVolume = TalerAmount( + value = it.getLong("cashout_regional_volume_val"), + frac = it.getInt("cashout_regional_volume_frac"), currency = bankCurrency ), - cashoutExternalVolume = TalerAmount( - value = it.getLong("cashout_external_volume_val"), - frac = it.getInt("cashout_external_volume_frac"), + cashoutFiatVolume = TalerAmount( + value = it.getLong("cashout_fiat_volume_val"), + frac = it.getInt("cashout_fiat_volume_frac"), currency = this ), talerInCount = it.getLong("taler_in_count"), diff --git a/bank/src/test/kotlin/StatsTest.kt b/bank/src/test/kotlin/StatsTest.kt @@ -65,18 +65,18 @@ class StatsTest { suspend fun monitor( dbCount: (MonitorWithConversion) -> Long, count: Long, - internalVolume: (MonitorWithConversion) -> TalerAmount, - internalAmount: String, - externalVolume: ((MonitorWithConversion) -> TalerAmount)? = null, - externalAmount: String? = null + regionalVolume: (MonitorWithConversion) -> TalerAmount, + regionalAmount: String, + fiatVolume: ((MonitorWithConversion) -> TalerAmount)? = null, + fiatAmount: String? = null ) { Timeframe.entries.forEach { timestamp -> client.get("/monitor?timestamp=${timestamp.name}") { basicAuth("admin", "admin-password") }.assertOk().run { println(bodyAsText()) val resp = json<MonitorResponse>() as MonitorWithConversion assertEquals(count, dbCount(resp)) - assertEquals(TalerAmount(internalAmount), internalVolume(resp)) - externalVolume?.run { assertEquals(TalerAmount(externalAmount!!), this(resp)) } + assertEquals(TalerAmount(regionalAmount), regionalVolume(resp)) + fiatVolume?.run { assertEquals(TalerAmount(fiatAmount!!), this(resp)) } } } } @@ -85,10 +85,10 @@ class StatsTest { monitor({it.talerInCount}, count, {it.talerInVolume}, amount) suspend fun monitorTalerOut(count: Long, amount: String) = monitor({it.talerOutCount}, count, {it.talerOutVolume}, amount) - suspend fun monitorCashin(count: Long, internalAmount: String, externalAmount: String) = - monitor({it.cashinCount}, count, {it.cashinInternalVolume}, internalAmount, {it.cashinExternalVolume}, externalAmount) - suspend fun monitorCashout(count: Long, internalAmount: String, externalAmount: String) = - monitor({it.cashoutCount}, count, {it.cashoutInternalVolume}, internalAmount, {it.cashoutExternalVolume}, externalAmount) + suspend fun monitorCashin(count: Long, regionalAmount: String, fiatAmount: String) = + monitor({it.cashinCount}, count, {it.cashinRegionalVolume}, regionalAmount, {it.cashinFiatVolume}, fiatAmount) + suspend fun monitorCashout(count: Long, regionalAmount: String, fiatAmount: String) = + monitor({it.cashoutCount}, count, {it.cashoutRegionalVolume}, regionalAmount, {it.cashoutFiatVolume}, fiatAmount) monitorTalerIn(0, "KUDOS:0") monitorTalerOut(0, "KUDOS:0") @@ -165,14 +165,14 @@ class StatsTest { } stmt.oneOrNull { val talerOutCount = it.getLong("taler_out_count") - val talerOutInternalVolume = TalerAmount( + val talerOutVolume = TalerAmount( value = it.getLong("taler_out_volume_val"), frac = it.getInt("taler_out_volume_frac"), currency = "KUDOS" ) - println("$timeframe $talerOutCount $talerOutInternalVolume") + println("$timeframe $talerOutCount $talerOutVolume") assertEquals(count, talerOutCount) - assertEquals(amount, talerOutInternalVolume) + assertEquals(amount, talerOutVolume) }!! } diff --git a/bank/src/test/kotlin/helpers.kt b/bank/src/test/kotlin/helpers.kt @@ -25,7 +25,7 @@ fun setup( resetDatabaseTables(dbCfg, "libeufin-bank") initializeDatabaseTables(dbCfg, "libeufin-bank") val ctx = config.loadBankConfig() - Database(dbCfg.dbConnStr, ctx.currency, ctx.externalCurrency).use { + Database(dbCfg.dbConnStr, ctx.currency, ctx.fiatCurrency).use { runBlocking { ctx.conversionInfo?.run { it.conversion.updateConfig(this) } lambda(it, ctx) diff --git a/database-versioning/libeufin-bank-0001.sql b/database-versioning/libeufin-bank-0001.sql @@ -69,7 +69,7 @@ CREATE TABLE IF NOT EXISTS customers ); COMMENT ON COLUMN customers.cashout_payto - IS 'RFC 8905 payto URI to collect external payments that come from the conversion of internal currency cash-out operations.'; + IS 'RFC 8905 payto URI to collect fiat payments that come from the conversion of regional currency cash-out operations.'; COMMENT ON COLUMN customers.name IS 'Full name of the customer.'; @@ -253,32 +253,32 @@ COMMENT ON COLUMN taler_withdrawal_operations.confirmation_done CREATE TABLE IF NOT EXISTS bank_stats ( timeframe stat_timeframe_enum NOT NULL ,start_time timestamp NOT NULL - ,cashin_count BIGINT NOT NULL DEFAULT 0 - ,cashin_internal_volume taler_amount NOT NULL DEFAULT (0, 0) - ,cashin_external_volume taler_amount NOT NULL DEFAULT (0, 0) - ,cashout_count BIGINT NOT NULL DEFAULT 0 - ,cashout_internal_volume taler_amount NOT NULL DEFAULT (0, 0) - ,cashout_external_volume taler_amount NOT NULL DEFAULT (0, 0) ,taler_in_count BIGINT NOT NULL DEFAULT 0 ,taler_in_volume taler_amount NOT NULL DEFAULT (0, 0) ,taler_out_count BIGINT NOT NULL DEFAULT 0 ,taler_out_volume taler_amount NOT NULL DEFAULT (0, 0) + ,cashin_count BIGINT NOT NULL DEFAULT 0 + ,cashin_regional_volume taler_amount NOT NULL DEFAULT (0, 0) + ,cashin_fiat_volume taler_amount NOT NULL DEFAULT (0, 0) + ,cashout_count BIGINT NOT NULL DEFAULT 0 + ,cashout_regional_volume taler_amount NOT NULL DEFAULT (0, 0) + ,cashout_fiat_volume taler_amount NOT NULL DEFAULT (0, 0) ,PRIMARY KEY (start_time, timeframe) ); -- TODO garbage collection COMMENT ON TABLE bank_stats IS 'Stores statistics about the bank usage.'; COMMENT ON COLUMN bank_stats.timeframe IS 'particular timeframe that this row accounts for'; COMMENT ON COLUMN bank_stats.start_time IS 'timestamp of the start of the timeframe that this row accounts for, truncated according to the precision of the timeframe'; -COMMENT ON COLUMN bank_stats.cashin_count IS 'how many cashin operations took place in the timeframe'; -COMMENT ON COLUMN bank_stats.cashin_internal_volume IS 'how much internal currency was cashed in in the timeframe'; -COMMENT ON COLUMN bank_stats.cashin_external_volume IS 'how much external currency was cashed in in the timeframe'; -COMMENT ON COLUMN bank_stats.cashout_count IS 'how many cashout operations took place in the timeframe'; -COMMENT ON COLUMN bank_stats.cashout_internal_volume IS 'how much internal currency was payed by the bank to customers in the timeframe'; -COMMENT ON COLUMN bank_stats.cashout_external_volume IS 'how much external currency was payed by the bank to customers in the timeframe'; COMMENT ON COLUMN bank_stats.taler_out_count IS 'how many internal payments were made by a Taler exchange'; COMMENT ON COLUMN bank_stats.taler_out_volume IS 'how much internal currency was paid by a Taler exchange'; COMMENT ON COLUMN bank_stats.taler_in_count IS 'how many internal payments were made to a Taler exchange'; COMMENT ON COLUMN bank_stats.taler_in_volume IS 'how much internal currency was paid to a Taler exchange'; +COMMENT ON COLUMN bank_stats.cashin_count IS 'how many cashin operations took place in the timeframe'; +COMMENT ON COLUMN bank_stats.cashin_regional_volume IS 'how much regional currency was cashed in in the timeframe'; +COMMENT ON COLUMN bank_stats.cashin_fiat_volume IS 'how much fiat currency was cashed in in the timeframe'; +COMMENT ON COLUMN bank_stats.cashout_count IS 'how many cashout operations took place in the timeframe'; +COMMENT ON COLUMN bank_stats.cashout_regional_volume IS 'how much regional currency was payed by the bank to customers in the timeframe'; +COMMENT ON COLUMN bank_stats.cashout_fiat_volume IS 'how much fiat currency was payed by the bank to customers in the timeframe'; -- end of: Statistics diff --git a/database-versioning/libeufin-bank-procedures.sql b/database-versioning/libeufin-bank-procedures.sql @@ -1349,11 +1349,11 @@ CREATE OR REPLACE FUNCTION stats_get_frame( IN in_timeframe stat_timeframe_enum, IN which INTEGER, OUT cashin_count BIGINT, - OUT cashin_internal_volume taler_amount, - OUT cashin_external_volume taler_amount, + OUT cashin_regional_volume taler_amount, + OUT cashin_fiat_volume taler_amount, OUT cashout_count BIGINT, - OUT cashout_internal_volume taler_amount, - OUT cashout_external_volume taler_amount, + OUT cashout_regional_volume taler_amount, + OUT cashout_fiat_volume taler_amount, OUT taler_in_count BIGINT, OUT taler_in_volume taler_amount, OUT taler_out_count BIGINT, @@ -1372,15 +1372,15 @@ BEGIN END; SELECT s.cashin_count - ,(s.cashin_internal_volume).val - ,(s.cashin_internal_volume).frac - ,(s.cashin_external_volume).val - ,(s.cashin_external_volume).frac + ,(s.cashin_regional_volume).val + ,(s.cashin_regional_volume).frac + ,(s.cashin_fiat_volume).val + ,(s.cashin_fiat_volume).frac ,s.cashout_count - ,(s.cashout_internal_volume).val - ,(s.cashout_internal_volume).frac - ,(s.cashout_external_volume).val - ,(s.cashout_external_volume).frac + ,(s.cashout_regional_volume).val + ,(s.cashout_regional_volume).frac + ,(s.cashout_fiat_volume).val + ,(s.cashout_fiat_volume).frac ,s.taler_in_count ,(s.taler_in_volume).val ,(s.taler_in_volume).frac @@ -1389,15 +1389,15 @@ BEGIN ,(s.taler_out_volume).frac INTO cashin_count - ,cashin_internal_volume.val - ,cashin_internal_volume.frac - ,cashin_external_volume.val - ,cashin_external_volume.frac + ,cashin_regional_volume.val + ,cashin_regional_volume.frac + ,cashin_fiat_volume.val + ,cashin_fiat_volume.frac ,cashout_count - ,cashout_internal_volume.val - ,cashout_internal_volume.frac - ,cashout_external_volume.val - ,cashout_external_volume.frac + ,cashout_regional_volume.val + ,cashout_regional_volume.frac + ,cashout_fiat_volume.val + ,cashout_fiat_volume.frac ,taler_in_count ,taler_in_volume.val ,taler_in_volume.frac @@ -1412,15 +1412,15 @@ END $$; CREATE OR REPLACE PROCEDURE stats_register_payment( IN name TEXT, IN now TIMESTAMP, - IN internal_amount taler_amount, - IN external_amount taler_amount + IN regional_amount taler_amount, + IN fiat_amount taler_amount ) LANGUAGE plpgsql AS $$ DECLARE frame stat_timeframe_enum; query TEXT; BEGIN - IF external_amount IS NULL THEN + IF fiat_amount IS NULL THEN query = format('INSERT INTO bank_stats AS s ' '(timeframe, start_time, %1$I_count, %1$I_volume) ' 'VALUES ($1, $2, 1, $3) ' @@ -1429,19 +1429,19 @@ BEGIN ', %1$I_volume=(SELECT amount_add(s.%1$I_volume, $3))', name); FOREACH frame IN ARRAY enum_range(null::stat_timeframe_enum) LOOP - EXECUTE query USING frame, date_trunc(frame::text, now), internal_amount; + EXECUTE query USING frame, date_trunc(frame::text, now), regional_amount; END LOOP; ELSE query = format('INSERT INTO bank_stats AS s ' - '(timeframe, start_time, %1$I_count, %1$I_internal_volume, %1$I_external_volume) ' + '(timeframe, start_time, %1$I_count, %1$I_regional_volume, %1$I_fiat_volume) ' 'VALUES ($1, $2, 1, $3, $4)' 'ON CONFLICT (timeframe, start_time) DO UPDATE ' 'SET %1$I_count=s.%1$I_count+1 ' - ', %1$I_internal_volume=(SELECT amount_add(s.%1$I_internal_volume, $3))' - ', %1$I_external_volume=(SELECT amount_add(s.%1$I_external_volume, $4))', + ', %1$I_regional_volume=(SELECT amount_add(s.%1$I_regional_volume, $3))' + ', %1$I_fiat_volume=(SELECT amount_add(s.%1$I_fiat_volume, $4))', name); FOREACH frame IN ARRAY enum_range(null::stat_timeframe_enum) LOOP - EXECUTE query USING frame, date_trunc(frame::text, now), internal_amount, external_amount; + EXECUTE query USING frame, date_trunc(frame::text, now), regional_amount, fiat_amount; END LOOP; END IF; END $$;